Overview
A path traversal vulnerability has been disclosed in libks, the foundational C library that underpins SignalWire's telephony products, including FreeSWITCH. Tracked as CVE-2026-49846, the flaw lives in clean_uri(), the function libks's HTTP request parser uses to canonicalize incoming URI paths before they are handed off to consuming applications.
Versions of libks prior to 2.0.11 fail to reject URIs whose path contains more segments than the internal canonicalization buffer is designed to hold. Rather than rejecting or safely truncating such a request, clean_uri() silently passes the oversized path through with embedded ../ sequences intact. Any consumer that later joins that unsanitized path with a filesystem location — for example, to serve a static file — inherits a directory traversal primitive it never asked for.
The issue carries a CVSS 3.1 score of 7.5 (High), is remotely exploitable over the network, requires no authentication or user interaction, and results in high-confidentiality impact (arbitrary file read) with no integrity or availability impact. The fix ships in libks 2.0.11.
Key Details
| Field | Value |
|---|---|
| CVE ID | CVE-2026-49846 |
| Severity | High |
| CVSS Score | 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) |
| Attack Vector | Network |
| Auth Required | None |
| Impact | Arbitrary file read via path traversal (CWE-22, CWE-697) |
How It Works
The root cause is a classic sizeof() mix-up in clean_uri() (src/kws.c). The function is supposed to cap the number of path segments it will process at 64, but the bounds check uses sizeof(argv) — the byte size of a pointer array (512 bytes on 64-bit systems, 256 on 32-bit) — instead of the actual element count. That mismatch means the segment-count guard doesn't kick in where it should.
When an incoming URI has more path segments than ks_separate_string() is configured to split, the splitting function stops after the expected number of segments and dumps everything left over — slashes included — into a single, unsplit array slot. Because the canonicalization loop that strips . and .. sequences only inspects properly split segments, it never looks inside that leftover blob, and any ../ sequences buried in it survive untouched.
In practice this means an attacker can pad a request with enough directory segments to exhaust the parser's expected segment count, then append real traversal sequences afterward — something in the shape of:
GET /a/a/a/.../a/../../../../etc/passwd HTTP/1.1
with roughly 63 or more padding segments ahead of the traversal payload. The padding "hides" the actual ../../../.. from the canonicalizer, and the resulting path — still containing the traversal — is returned to the caller as if it had already been sanitized.
Impact Assessment
The blast radius depends on how a given libks consumer uses the parsed URI. Reachability has been confirmed in FreeSWITCH, where mod_verto's HTTP-static handler is the primary code path that joins a client-supplied URI with a filesystem path. That handler is disabled by default, but deployments that enable virtual hosts — particularly those without authentication in front of the static handler — are exposed to unauthenticated, remote file disclosure.
More broadly, any product built on libks's HTTP/websocket request parser that later concatenates the "cleaned" URI with a local file path (for serving static assets, loading configuration, or resolving includes) inherits the same risk, even if it is not FreeSWITCH itself. Because the vulnerability requires no authentication and no user interaction, and is triggerable with a single crafted HTTP request, exposed instances should be treated as reachable by any attacker with network access to the listening service.
Files of concern include application configuration containing credentials or connection strings, TLS/SSH private keys, and any other data readable by the service account running the libks-based process.
Mitigation
Immediate Actions
- Upgrade to libks 2.0.11 or later, which corrects the segment-count bounds check in
clean_uri(). - If you run FreeSWITCH with
mod_vertovhosts enabled, confirm the module and libks version, and prioritize patching or temporarily disabling the HTTP-static handler until upgraded. - Where an immediate upgrade isn't possible, place an authenticating reverse proxy or WAF in front of any libks-based HTTP listener and reject requests with abnormally long or deeply nested paths.
Detection Opportunities
- Monitor access logs for requests with an unusually high number of path segments, especially many repeated identical segments (e.g.
/a/a/a/...) followed by../sequences. - Alert on HTTP requests to FreeSWITCH/
mod_vertoendpoints that resolve to files outside the expected web root, or on file-access anomalies from the process's service account. - Flag URIs containing
..anywhere after normalization at the WAF or reverse-proxy layer, even if the origin application is expected to sanitize them itself.
Defence-in-Depth
- Run FreeSWITCH and other libks-based services under a least-privilege service account with filesystem access restricted to only what is required.
- Where feasible, run the service inside a container or chroot so a successful traversal cannot reach sensitive host paths.
- Disable
mod_vertovhosts and other HTTP-static handlers that are not actively required. - Maintain an inventory of applications embedding libks so future advisories can be triaged quickly.