Severity Daily

IT and AI security incidents, checked against the primary source

Tag: CVE-2026-90780

  • Three SIPp buffer overflows are fixed on master and in no release; 3.7.7 is still the newest tag

    Three SIPp buffer overflows are fixed on master and in no release; 3.7.7 is still the newest tag

    VulnCheck published three buffer overflows in SIPp on Sunday; all three are fixed in the master branch, and none of them are in a release, because there has not been one since 3.7.7.

    What happened

    NVD published CVE-2026-90778, CVE-2026-90779 and CVE-2026-90780 on September 13, 2026, within 300 milliseconds of one another at 12:17 p.m. UTC. All three are assigned by VulnCheck, all three name SIPp — the open-source SIP traffic generator and test tool — and all three give the affected range as “through 3.7.7.” Each carries a CVSS v3.1 base score of 7.5 with the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H and a secondary CVSS v4.0 score of 8.7, both assigned by VulnCheck. All three records were still at vulnStatus Received when this story was checked. The VulnCheck advisory for the first credits Tristan Madani.

    The three descriptions, verbatim:

    • CVE-2026-90778: “SIPp through 3.7.7 contains a buffer overflow vulnerability in get_peer_tag() function when processing SIP To headers with tag parameters of 2049 bytes or more.” CWE-120.
    • CVE-2026-90779: “SIPp through 3.7.7 contains a stack buffer overflow vulnerability in createAuthHeader() when processing SIP authentication challenges with oversized algorithm parameters.” CWE-121.
    • CVE-2026-90780: “SIPp through 3.7.7 contains a buffer overflow vulnerability in the get_header() function in src/sip_parser.cpp when processing SIP messages with header content exceeding 20,490 bytes.” CWE-120.

    The oddly specific byte counts come from one constant. include/sip_parser.hpp at tag v3.7.7 defines MAX_HEADER_LEN as 2049. get_peer_tag() writes into static char tag[MAX_HEADER_LEN], which is where 2,049 comes from. get_header() writes into static char last_header[MAX_HEADER_LEN * 10], which is where 20,490 comes from. The numbers in the CVE descriptions are the buffer sizes, and they line up exactly with the source at the tag.

    Reading that source at v3.7.7 shows three plain misses. get_peer_tag() copies the To-header tag one character at a time with tag[tag_i++] = *(ptr++) inside a loop whose only exit conditions are the end of the string and a set of delimiter characters; the index is never compared against the buffer. get_header() accumulates matched headers with dest += sprintf(dest, "%s", src), with no bound on dest. createAuthHeader() declares char algo[32] = "MD5", locates algorithm= in the challenge, measures the value with strcspn, and then calls strncpy(algo, start, end - start) — passing the length of the source rather than the size of the destination, which is the failure mode strncpy is most often reached for and least protects against.

    The fixes exist, and are not in a release

    Each NVD record references a commit and a pull request: ddf22d1 and PR #879 for the tag overflow, 1d4a562 and PR #880 for the auth header, 8ddfb43 and PR #881 for get_header(). Severity Daily read the same files on the master branch rather than relying on the commit references, and the repairs are there:

    • get_peer_tag() on master carries the same copy loop with one added condition: && tag_i < (int) sizeof(tag) - 1.
    • get_header() on master computes last_header_end from sizeof(last_header) and replaces every sprintf with a bounded snprintf against the remaining space, jumping to a truncation path when the return value will not fit.
    • createAuthHeader() on master deletes the stristr/strcspn/strncpy sequence entirely and calls getAuthParameter("algorithm", auth, algo, sizeof(algo)), which takes the destination size, falling back to MD5 when the parameter is absent.

    The remaining question is which release contains them, and the answer is none. Severity Daily probed the repository for tags after v3.7.7 by requesting a known source file at each candidate tag: v3.7.6 and v3.7.7 return the file, while v3.7.8, v3.7.9, v3.8.0 and v4.0.0 all return 404. v3.7.7 is the newest tag in the repository. Every published SIPp release is inside the affected range.

    The project’s own changelog does not help either. CHANGES.md at master and at v3.7.7 both stop at a heading reading “Features added in 3.7.5.” Neither 3.7.6 nor 3.7.7 has an entry, so a reader who upgrades has no document describing what changed, and no place where a security fix would be announced if one were made.

    Why it matters

    The scoring deserves reading carefully before anyone treats this as an emergency. The vector is availability-only — C:N/I:N/A:H. VulnCheck is describing crashes, not code execution. These are stack and static-buffer overflows in C++ string handling, which is the category from which exploitation sometimes follows, but no one has claimed it here and this site is not going to claim it either.

    What makes it worth attention is the direction the attack runs. SIPp is a test tool, and the instinct is to file test tools under “lab, not production, not exposed.” But the data SIPp parses does not come from its operator. It comes from the system under test, over the network, in responses to the traffic SIPp generated. The overflowing inputs here are a To-header tag, an authentication challenge, and header content — all of them fields the far end supplies. In client mode the attacker position is the device SIPp is pointed at. In server mode, which SIPp supports and which is how it is run as a responder in automated suites, the attacker position is anyone who can reach the port.

    That is the useful lesson, and it generalizes past SIPp. Test harnesses are written on the assumption that the operator controls both ends, so their parsers are built for well-formed input from a cooperating peer. When the peer is a piece of equipment being evaluated, or a soak-test target on a shared lab network, or a CI runner reachable from more of the network than anyone intended, the assumption stops holding — and the harness is usually running with fewer restrictions than the software it is testing, because nobody hardens the thing that is only used for testing.

    This is the second SIP tool in two days to arrive with a fix that exists only outside a release. sngrep CVE-2026-90558 ran here on Saturday on precisely that shape. The pattern in both cases is a small, long-lived, single-purpose C tool that many people install once and never update, maintained actively enough that fixes land in the branch but not actively enough that a release follows. For the operator the consequence is the same either way: the remedy on offer is not a version number.

    Distribution makes it worse here than it was for sngrep. Debian’s package tracker reports that sipp “is not part of any Debian distribution” and shows the last version as 3.1-11, removed from testing in 2007. There is no distribution security team positioned to backport these three commits into a package most SIPp users would receive. Whoever is running SIPp almost certainly built it from a tarball or a checkout, which means the upgrade path is a decision each operator makes alone.

    What to do

    There is no release to move to. The fixes are on master, and taking them means building from the branch rather than from v3.7.7.

    That is a real cost and worth stating plainly: master has diverged from 3.7.7 by more than these three commits. The authentication code in particular has been reworked, with the MD5-specific hashing types replaced by generic ones and the USE_SHA256 build guards removed. Building master is not equivalent to applying three patches, and anyone with a scenario suite that depends on current behavior should expect to re-test it.

    The narrower option is to cherry-pick ddf22d1, 1d4a562 and 8ddfb43 onto a v3.7.7 checkout. The first two are small and self-contained. The get_header() change is larger, because converting sprintf to bounded snprintf touched every write in the function and added a truncation path.

    Independent of either, treat SIPp the way you would treat any other network-facing parser. Do not leave a server-mode instance listening past the run that needed it, do not point SIPp at equipment you do not control from a host that matters, and do not assume a crashed test harness in a long soak run is a flaky tool rather than a signal.

    Sourcing note

    Checked: the NVD records for CVE-2026-90778, CVE-2026-90779 and CVE-2026-90780, read from the NVD REST API, for descriptions, scores, vectors, CWEs, affected ranges, timestamps and status. The VulnCheck advisory for CVE-2026-90778 for the researcher credit. SIPp source at tag v3.7.7 and at master, retrieved as raw files, for the vulnerable code, the MAX_HEADER_LEN constant and each repair. The presence and absence of release tags, established by requesting a known file at each candidate tag. CHANGES.md at both refs. Debian’s package tracker for packaging status.

    Not reached: the GitHub API is unavailable from this environment, so pull requests #879, #880 and #881 were not read directly and their merge status was not confirmed from GitHub. The fixes were verified by reading the code on master instead, which establishes that the repairs are in the branch regardless of how they arrived. The release date of v3.7.7 was not established; the project publishes no changelog entry for it. VulnCheck advisory pages for CVE-2026-90779 and CVE-2026-90780 were not individually read.

    Unresolved: no SIPp maintainer statement on these three records was found, and the project has issued no advisory. Whether a release carrying the fixes is planned is unknown. No exploitation has been reported by anyone, and none is claimed here. cisa.gov returns 403 to automated retrieval and was not consulted; none of the three records carries CISA fields in NVD, and no federal deadline attaches to them.