How to fix path traversal in embedded firmware
Path traversal (MITRE CWE-22, read 2026-10-29) happens when firmware builds a filesystem path from external input — a filename in a web UI request, an upload parameter, an exported-log name — without removing or rejecting the special sequences (../, absolute paths, encoded separators) that let that path resolve outside its intended directory. MITRE rates it a high likelihood of exploit, and its own description covers both reading files it shouldn't (confidentiality) and, in upload or import handlers, writing or overwriting files it shouldn't (integrity, and potentially code execution if an attacker can overwrite something the system later runs).
1. Detect
- Audit every firmware web-UI or API handler that accepts a filename, path fragment, or file-upload destination as a parameter: log download/export, configuration backup/restore, firmware-image upload, certificate import, captive-portal asset serving.
- For each one, trace whether the supplied name is used directly (or lightly concatenated) to build a path passed to a file-open, read, write or delete call, without a canonicalization-and-containment check afterward.
- Test with both classic traversal (
../../../etc/passwd) and encoded/alternate variants (URL-encoded%2e%2e%2f, double-encoding, backslash separators, absolute paths) — a denylist that only blocks the literal../string will often miss these. - Check upload and import handlers specifically for write-path traversal, which is more severe than read-path traversal because it can let an attacker place a file anywhere the process can write, including executable locations.
2. Fix
- Canonicalize, then verify containment. Resolve the supplied path to its canonical absolute form with a built-in function (
realpath()in C, or your language's equivalent) — MITRE notes this "effectively removes '..' sequences and symbolic links" — and then explicitly check that the canonical result is still inside the restricted parent directory before opening it. Reject the request if it isn't. - Validate the raw input with an allowlist, not a denylist. Restrict filenames to a strict character set (alphanumeric, hyphen, underscore, a single extension) and explicitly reject path separators (
/,\\) in the component itself, so traversal sequences never reach the path-construction step. - Prefer an indirection layer over raw filenames where possible. Map a request to a file via an internal ID or lookup table (e.g. "log #3" rather than a raw filename), so user input never becomes part of a filesystem path at all.
- Run file operations inside a sandbox or chroot/jail where feasible. MITRE lists this as an operation-phase mitigation: it won't fix the underlying bug, but it bounds the damage if a traversal check is ever missed.
- Apply the same fix pattern everywhere the pattern repeats. Path traversal in firmware is usually a repeated handler pattern (one file-serving utility function reused across many endpoints) — fix the shared utility, then confirm every call site actually uses the fixed version.
3. Verify
- Re-test the same traversal payloads (plain and encoded) against the patched handler and confirm every one is rejected, not just the exact proof-of-concept string originally reported.
- Confirm legitimate requests (normal filenames, expected extensions) still work — an over-broad fix that breaks the intended feature is as much a problem as a missed bypass.
- Add the traversal test cases to your regression suite so a future handler added to the same code path inherits the same protection by default (ideally by calling the shared, fixed utility rather than re-implementing path handling).
4. Ship an update
Path-traversal fixes are usually self-contained to the affected handler(s); distribute the update through your normal signed-firmware channel, and use your firmware SBOM to confirm which product lines share the vulnerable file-serving utility, since it is common for the same code to be reused across several models.
5. Disclose via PSIRT
Path traversal in an unauthenticated web endpoint is frequently exploited at scale by internet-wide scanners once published, so treat disclosure timing accordingly — see KEV + EPSS prioritization. Run the advisory through your coordinated disclosure process (CVD process explained; PSIRT setup for a hardware company if you don't have one yet), and check the Cyber Resilience Act's 24-/72-hour reporting duty for EU-market products if there is evidence of active exploitation (CRA 24h/72h reporting).
SoftWSP's firmware and web-UI scanning traces exactly this pattern — user input reaching a filesystem path — across a device's firmware image: see device & firmware security.
This guide summarises public MITRE CWE guidance; it is not a substitute for a full code review, and does not constitute legal advice.
Frequently asked questions
What is path traversal?
MITRE's CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) defines it as a product that "uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but... does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory." CWE-22's own page, read 2026-10-29, notes this most commonly uses `../` sequences to climb out of the intended directory (relative path traversal), or a crafted absolute path (`/etc/passwd`-style, absolute path traversal).
Where does this show up in device firmware specifically?
Embedded web UIs frequently expose file operations by name — a log download, a configuration-file export/import, a firmware-update upload, a captive-portal asset server — where the filename comes from a request parameter. If that parameter is used to build a filesystem path without checks, a request for `../../etc/shadow` or similar can read or, in upload/import handlers, overwrite files well outside the intended directory. MITRE's CWE-22 page rates this weakness's **Likelihood of Exploit as High**.
What does CWE-22 say the impact can be?
MITRE lists four consequence categories: reading files or directories outside the restricted path (confidentiality — including, per MITRE, bypassing authentication by reading a password file); modifying or overwriting files (integrity); executing unauthorized code if an attacker can place or overwrite an executable or library the system later runs; and denial of service if a critical file is deleted or corrupted via the same path.
What is the correct fix, per MITRE?
Two mitigations working together: canonicalize the path and check it, and validate the input before it ever reaches path construction. MITRE's Implementation-phase mitigation says to "use a built-in path canonicalization function (such as realpath() in C)... that produces the canonical version of the pathname, which effectively removes '..' sequences and symbolic links," and then verify the canonical result is still inside the intended restricted directory before using it. Separately, validate the raw filename against a strict allowlist of characters, explicitly excluding path separators (`/`, `\`) so a crafted pathname component never reaches the canonicalization step with traversal sequences already baked in.
Is blocking the literal string '../' enough?
No — MITRE's input-validation guidance calls for an "accept known good" allowlist strategy (reject anything that doesn't strictly match an expected filename pattern) rather than a denylist that tries to block specific bad substrings, because denylists are routinely bypassed with encoding tricks (URL-encoded separators, double-encoding, mixed slash styles, or absolute paths that don't contain '../' at all but still escape the intended directory). Canonicalizing the path and then checking it is inside the intended directory catches these cases that a substring denylist misses.