
You're midway through an MSSP web application engagement. The client says downloads are restricted, uploads are renamed, and the report generator only serves approved documents. Burp Suite's automated checks are quiet, so the endpoint is close to being marked clean.
Then a legacy export route catches your attention. Its filename parameter behaves differently from the newer download function. A controlled traversal request confirms arbitrary file read, and a second test shows that the same path-handling logic can reach a writable location. The finding isn't just “an attacker can read /etc/passwd.” It's a potential route to configuration overwrite, persistence, credential exposure, or code execution, depending on the server-side sink.
That pattern appears repeatedly in penetration testing. Teams protect the obvious file browser while overlooking report generation, archive extraction, template loading, and upload workflows. This guide approaches the path traversal vulnerability as a filesystem-boundary failure, with special attention to write primitives, manual verification, MSSP evidence, and remediation that survives a client's QA review.
Table of Contents
- The Engagement Scenario Every Pentester Recognizes
- What Path Traversal Actually Is
- Variants That Still Bypass Naive Filters
- Real-World Payloads and Case Studies
- Testing Methodology From Recon to Verification
- Manual Testing Versus Automated Detection
- Secure Coding Fixes and Mitigation Strategies
- Compliance Mapping and Reporting for MSSPs
The Engagement Scenario Every Pentester Recognizes
The application under test has a document-download feature. The development team has already added extension validation, blocked obvious ../ strings, and placed the service in a container. A scanner reports no confirmed path traversal, and the client's security contact points to the result as evidence that the file surface is covered.
During feature mapping, you find a separate report endpoint. It accepts a document name, builds a temporary output path, and returns a generated file. The route isn't linked from the main interface, but it appears in older JavaScript and API traffic. A single request with a controlled relative path produces an error that reveals the application's base directory. That error is more useful than a large automated payload set because it tells you which resolver and sink you're dealing with.
The next probe should stay inside the engagement's rules of engagement. Use a harmless, approved file for read confirmation, and never write to a production path unless the client has explicitly authorized a safe marker-file test. The objective is to prove the boundary failure, not to create persistence or damage data.
Practical rule: A read primitive establishes exposure. A verified write primitive changes the risk conversation.
This is why path traversal remains a meaningful penetration-testing target rather than a legacy checklist item. One independent analysis reported that path traversal represented roughly 5% of new CVEs each year since 2014 and about 5% of CISA's Known Exploited Vulnerabilities catalog, while a May 2024 Secure by Design alert from CISA and the FBI called out the issue directly. The OWASP directory traversal testing guidance reflects why testers still encounter this class at scale.
The scenario also explains why MSSP workflows need stronger verification. Automated tools can identify a suspicious parameter, but a client-ready finding needs a reproducible request, a safe impact demonstration, and a clear distinction between arbitrary read, arbitrary write, and code execution potential.
What Path Traversal Actually Is
A path traversal vulnerability occurs when external input helps construct a filesystem path, and the application fails to keep the resolved path inside the directory it intended to expose. CWE-22 describes this as improper limitation of a pathname to a restricted directory. Special path elements such as .. allow the operating system or runtime to resolve a path above the application's intended root.
The important word is resolved. The string the application receives may look harmless before normalization, yet resolve somewhere dangerous after URL decoding, separator handling, dot removal, or symbolic-link resolution. A secure test therefore follows the value through the entire processing chain, from HTTP parameter to filesystem API.
Consider an endpoint served from a Linux container with an intended base directory of /var/www/uploads. A request such as:
GET /download?file=../../../../etc/passwd
may be joined to that base directory as:
/var/www/uploads/../../../../etc/passwd
The filesystem resolves each .. component by moving to the parent directory. The resulting path can escape /var/www/uploads and reach /etc/passwd, assuming the process has permission to read it. The bug isn't that /etc/passwd is special. The bug is that an attacker controls a path component that should have remained confined.

CWE-22 is the right primary classification for this behavior. Related cases can overlap with file inclusion when the application executes or includes the resolved file, but a read-only download endpoint should not be overstated as remote code execution without evidence. OWASP places the access-control aspect of this problem within the broader A01:2021 Broken Access Control family.
The same boundary mistake can affect writes. An upload handler that stores user-controlled-name beneath an upload directory may overwrite a configuration file, place content where a template loader will process it, or create a link that redirects future operations. That's why a penetration tester should trace both read and write sinks before closing the finding.
The scale is measurable. A 2024 to 2025 academic study analyzed 40,546 open-source projects, 41,870 unique files, and 33,436 samples judged safe by static analysis, yet identified 8,397 vulnerable samples and 1,756 exploitable path traversal instances. The researchers generated 1,600 valid local patches, submitted 433 pull requests, and recorded 63 fixed repositories, as documented by the OWASP Path Traversal community page.
Variants That Still Bypass Naive Filters
A blacklist is not a path-security model. It's a guess about how an attacker will spell a path, and the guess often fails because different layers decode and normalize input at different times.
| Variant | Naive Defense Bypassed | Testing Signal |
|---|---|---|
Encoded traversal such as %2e%2e%2f or double-encoded input |
String filters that inspect only literal dots and slashes | Response changes after one or more decoding stages |
Absolute paths such as /etc/passwd or file URI forms |
Filters that block only ../ |
The endpoint accepts a fully qualified path |
| Nested or repeated traversal sequences | One-pass string replacement | A rejected obvious payload behaves differently when separators are represented indirectly |
Legacy null-byte forms such as %00.jpg |
Extension allowlists in older runtimes | Validation accepts the suffix, while the underlying file API truncates earlier |
| Symlinks inside uploads or archives | Prefix checks performed before link resolution | A path appears inside the allowed directory but resolves elsewhere |
| Write-path traversal | Read-only scanner assumptions | Uploaded, extracted, rendered, or generated content lands outside the intended directory |
Encoding and canonicalization
Test encoding only when you have permission and a clear reason. A value may arrive URL-decoded at the web server, decoded again by a framework, and normalized later by a library. If validation occurs before the final decoding step, the validator may inspect a harmless representation while the filesystem receives traversal syntax.
Absolute paths deserve a separate probe. A filter that rejects ../ but accepts /etc/passwd, a Windows drive path, or a file URI hasn't established confinement. Likewise, a startsWith() check can approve /var/www/uploads/../../etc/passwd if it tests the raw string rather than the canonical result.
Write sinks and symlinks
Older null-byte techniques are mainly relevant to legacy stacks, but they still matter during assessments of unmaintained applications. More important in current engagements is the write path. Archive extraction, report generation, template storage, and upload renaming can all create files. If the application follows symlinks during extraction or writes through a link already present in the destination, a safe-looking directory can become a route to an unintended target.
Don't stop after a read response. Ask what the application does with the same input when it creates, extracts, copies, or overwrites a file.
Real-World Payloads and Case Studies
A useful modern case study is CVE-2022-23457 in OWASP ESAPI. In versions before 2.3.0.0, Validator.getValidDirectoryPath(String, String, File, boolean) could mishandle directory validation and incorrectly treat attacker-controlled input as a child of the specified parent directory. The issue was patched in ESAPI 2.3.0.0, as described in this CVE-2022-23457 vulnerability record.
The lesson isn't to memorize one Java method. It's to identify the gap between a validation decision and the final filesystem operation. A function can believe that a path belongs beneath a parent directory while the operating system resolves the path somewhere else. In a live engagement, that means you should record the supplied value, the application's interpreted path where available, and the final read or write effect.
Recent advisories show why write behavior deserves equal attention. The referenced vulnerability coverage includes node-tar linkpath sanitization issues, OliveTin arbitrary file writes, Tenable Agent arbitrary file writes, and .NET Core write-to-arbitrary-files behavior. The Aqua vulnerability advisory coverage frames the practical concern: a write primitive can become credential overwrite, persistence, or remote code execution when it reaches a consequential sink.
Use a sink-oriented cheat sheet during authorized testing:
| Sink Type | Payload Example | Verification Indicator |
|---|---|---|
| File download or viewer | ../../../../etc/passwd |
Response contains a known, approved system-file marker |
| Archive extraction | ../../tmp/marker.txt as an archive entry |
A harmless marker appears outside the extraction root |
| Upload filename | ../marker.txt |
Server records or creates the marker outside the upload directory |
| Report or export generation | ../reports/marker.txt |
Generated output appears in an unintended location |
| Template loader | ../templates/known-file |
Application loads content from outside the template directory |
Use non-destructive markers for write tests. Don't upload a webshell, overwrite a live configuration file, or attempt command execution merely to make a report look more severe. If the sink can reach executable content, document that as an impact path and obtain explicit approval before any further validation.
Reporting and document-processing components deserve special scrutiny. Vulnerabilities reported in Allure Report, Bold Reports, Cacti reporting functionality, and related components show that traversal can surface in report workflows, with impacts ranging from arbitrary file read to command execution, according to this CVE-2026-33166 vulnerability entry. A team that tests only download routes can miss the component with the most authority over the filesystem.
Testing Methodology From Recon to Verification
Start with feature mapping, not payload spraying. During reconnaissance, inventory every function that accepts or derives a filename, path, template, archive member, document identifier, or export destination. Downloads and image loaders are obvious, but report generators, static asset routes, upload handlers, backup restoration, API imports, and template previews often reveal the more valuable sinks.
Map the application's file operations
Capture normal requests first. Note the parameter name, content type, authentication context, error behavior, and whether the response contains file content, a generated document, or only a job identifier. Trace asynchronous workflows as well, because the initial request may queue a file operation that executes later under a different service account.
Look for values such as file, filename, path, template, document, resource, export, and custom names that behave like them. JavaScript bundles, API schemas, OpenAPI documents, and server error messages can expose routes that the user interface doesn't show.
Craft a test around the sink
For a read endpoint, begin with a harmless known file and then use a controlled traversal value. For a write endpoint, use a marker that has no operational meaning and target an approved test directory. Test the transformations that the observed stack suggests, including URL encoding, double decoding, separator changes, absolute-path handling, and canonicalization.
The testing workflow is easier to standardize when it follows the application's behavior rather than a generic payload list. A documented penetration testing methodology for MSSP delivery can help teams keep reconnaissance, exploitation, verification, and reporting aligned.
Probe manually before automating
Send a single confirmation request through Burp Repeater or an equivalent client. Compare status, response length, content type, error text, timing, and downstream job behavior against the baseline. Manual probing keeps the signal interpretable and reduces the chance that a scanner's concurrent requests alter the application state.
Automation belongs at the handoff point. If the parameter produces an anomalous response but no confirmation, use targeted Intruder payloads or a purpose-built script to vary encoding and depth. Don't launch broad fuzzing before you know whether the sink reads, writes, extracts, or renders content.
The verification standard should be concrete:
- File existence: Show that the server reached the intended test file or marker.
- Content match: Capture a stable, non-sensitive content fragment or approved marker.
- Boundary escape: Demonstrate that the resolved location lies outside the allowed directory.
- Clean reproduction: Preserve the exact request, prerequisites, response, and cleanup action.
- Impact separation: Report read, write, link-following, and execution effects as distinct observations.
For write testing, include filesystem evidence from the server or a controlled application response when the client can provide it. A successful HTTP status alone doesn't prove a write occurred.
A short practical demonstration can reinforce the sequence, but keep it separate from the evidence record.
Manual Testing Versus Automated Detection
Manual testing and automated scanning answer different questions. A scanner is good at breadth across common request patterns and textbook traversal strings. A senior tester is better at deciding whether an unusual response represents a real filesystem effect, especially when the application queues work, transforms filenames, or writes through an archive library.
Burp Suite Active Scan and similar tools can reliably identify straightforward file-read cases when the parameter is visible, the response contains a recognizable change, and the application uses conventional request and response flows. They're less dependable when traversal appears in an archive entry, a generated report name, a template-loader argument, or a symlink chain. Those cases often require understanding the server-side sink, not just comparing response bodies.
| Dimension | Manual Testing | Automated Scanning |
|---|---|---|
| Legacy parameter coverage | Strong when the tester maps hidden and obsolete routes | Limited to discovered and supported request patterns |
| Encoded variants | Deep, because the tester can infer decoding order | Broad for known encodings, weaker for application-specific transformations |
| Write-path verification | Strong, with controlled markers and server-side confirmation | Often limited to inferred behavior or response anomalies |
| False positives | Lower after a human confirms the filesystem effect | Higher when a status or error change is treated as proof |
| Time to evidence | Slower per endpoint, stronger client-ready context | Fast triage and repeatable coverage |
| MSSP workflow fit | Best for escalation and final validation | Best for continuous coverage and candidate generation |
The most common operational mistake is treating a scanner's “not vulnerable” result as proof that no write primitive exists. Many tools focus on read disclosures because they can confirm them from the response. An archive extraction bug may return a normal success page while writing outside the intended directory, and a template loader may fail until a later request uses the created file.
False-positive control needs the same discipline. A useful false-positive reduction workflow should require evidence from the sink, not just a changed response. For MSSPs, the practical division is clear. Keep manual judgment for destructive-risk decisions, write confirmation, chained impact, and client-facing severity. Hand repetitive discovery and regression checks to automation once the endpoint and expected signal are understood.
ThreatExploit AI is one platform option for security providers that need automated reconnaissance, exploitation, verification, and reporting across web applications, APIs, networks, and cloud environments. Its role fits the candidate-generation and evidence-collection side of this workflow, while authorized human review remains important for confirming write effects and deciding how far exploitation should proceed.
Secure Coding Fixes and Mitigation Strategies
The strongest fix removes direct path control from the user. Give the client an opaque document ID, resolve that ID to a server-side record, and keep the actual filesystem name outside the request. This approach avoids a large class of normalization and encoding mistakes because the caller never supplies a path component.
When a user-controlled name is unavoidable, apply defenses in order:
- Resolve against an allowlist. Build the path beneath a permitted base directory, canonicalize it, resolve symbolic links, and reject the request unless the final path remains within the approved root. Use path-aware APIs rather than string concatenation.
- Normalize before validation. Decode according to the actual framework pipeline, handle separator variants, and account for Unicode normalization. Validate the representation that the filesystem API will receive.
- Reject links and unsafe archive entries. A path can pass a textual prefix check and still escape through a symlink. Archive extraction should inspect each entry and refuse absolute paths, parent traversal, and link entries unless there's a tightly controlled reason to support them.
- Reduce filesystem authority. Run the application with only the permissions needed for its task. Sandboxing, chroot or jail controls, and container isolation can limit blast radius, but they don't replace path validation.

The upload-then-serve anti-pattern needs special attention. Storing an uploaded file under a user-influenced name and later serving it from a predictable route creates two opportunities for abuse. The upload operation may write outside its root, and the serving operation may interpret attacker-controlled content in a sensitive context.
Developer handoff checklist
- Decode consistently: Confirm where the web server, framework, reverse proxy, and application each decode input. Test double encoding during regression.
- Canonicalize at the correct point: Resolve
..components and symlinks before the boundary comparison, not after the file has already been opened. - Use generated names: Store uploads under server-generated identifiers and retain the original name only as metadata.
- Limit permissions: Separate read and write directories, and prevent the application account from modifying executable code or credentials.
- Log security decisions: Record the endpoint, authenticated principal, normalized path decision, rejection reason, and destination class without logging secrets.
- Retest the sink: Confirm that read, write, extraction, and rendering paths all enforce the same boundary policy.
Refuse three tempting shortcuts. Extension blacklists don't control directories. A naive startsWith() check doesn't prove canonical containment. Container boundaries alone don't make an unsafe path construction routine safe, especially when the process can reach mounted secrets or shared volumes.
Compliance Mapping and Reporting for MSSPs
A path traversal finding becomes useful to an audit team when the technical proof, business impact, and control mapping agree. Map the primary defect to CWE-22, then use the surrounding implementation to identify related categories such as CWE-23, CWE-36, CWE-41, or CWE-59 for symlink behavior. OWASP mapping commonly points to A01:2021 Broken Access Control, while an inclusion or execution path may justify a separate classification rather than inflating the traversal finding.
The evidence package should let a reviewer reproduce the result without guessing:
- Request and response: Preserve the unsanitized parameter, relevant headers, authentication context, and response evidence.
- Resolved location: Record the absolute file path accessed or written, using a safe target and redacting sensitive content.
- Reproduction steps: State prerequisites, exact sequence, expected signal, cleanup, and limitations.
- Patch evidence: Attach the code change, configuration change, test result, or server-side validation showing that the sink now enforces containment.
- Impact boundary: Distinguish arbitrary read, arbitrary write, symlink following, credential exposure, and execution potential.
| Framework | Control ID | Requirement | Evidence Required |
|---|---|---|---|
| OWASP Top 10 | A01:2021 | Enforce authorization and prevent access outside the intended resource boundary | Reproducible request, resolved path, and access-control remediation |
| CWE | CWE-22, with related variants where applicable | Properly limit pathnames to restricted directories | Root cause, affected sink, and patched validation logic |
| PCI DSS | 6.2.4 | Secure software development and protection against common coding vulnerabilities | Secure coding review, test evidence, and remediation record |
| NIST SP 800-53 | SI-10 and SC-7 | Validate inputs and restrict communications or system boundaries | Validation rules, boundary controls, logs, and retest results |
| ISO 27001 | A.14.2.5 | Secure system engineering principles | Development standard, review record, test output, and closure evidence |
Use the compliance documentation workflow to keep the technical finding connected to the client's audit artifacts. Severity should reflect the actual sink and environment, using CVSS 4.0 with environment modifiers where appropriate. A read-only disclosure of a public file is not equivalent to an authenticated write primitive that reaches a configuration directory.
The first 48 hours after confirmation
Triage the affected endpoint and determine whether the flaw is exposed externally, limited to authenticated users, or reachable through an internal service. Rotate credentials if the vulnerable path could expose secrets, review relevant access and application logs for suspicious filenames and traversal representations, preserve evidence, and schedule a retest with the development owner.
The remediation deliverable should name the vulnerable parameter, the filesystem sink, the containment failure, and the exact fix required. After the patch, test the original payload, encoded forms, absolute paths, symlink behavior, archive entries, and the write workflow. Close the finding only when the application rejects the normalized path and the evidence shows that the intended operation still works safely.
ThreatExploit AI offers MSSPs automated penetration testing workflows covering reconnaissance, exploitation, verification, and evidence-backed reporting across web applications and APIs. Visit ThreatExploit AI to evaluate how automated coverage can support path traversal discovery while your testers retain control of write-path verification and compliance-ready delivery.
