REVIEW 4 major objections 4 minor 18 references
A Simple and Intuitive Algorithm for Preventing Directory Traversal Attacks
T0 review · 4 major / 4 minor · reviewed 2026-08-14 · deepseek-v4-flash
Pith's one-line read The paper proposes a stack-based path canonicalizer that admits a user path only if its resolved form is whitelisted, claiming this is a portable, verifiable defense against directory traversal attacks.
desk verdict A clean write-up of a standard path-normalization routine whose central equivalence theorem is false as stated, admitted by the paper's own Section V.B. read the letter →
The pith
A machine-rendered reading of the paper's core claim, the machinery that carries it, and where it could break.
The reading
What carries the argument
The load-bearing object is Algorithm 1 (sanitize), a stack machine for path strings: tokenize on the slash separator, push ordinary tokens, skip . tokens, and on .. either pop the stack or, if the stack is empty, drop the token. Its companion toString method reconstitutes the canonical path as a slash-joined string, which is then checked against the whitelist with an array contains operation. The central identity is Theorem 1, which ties the stack's final contents to filesystem reference equality under the no-symlink, canonicalized-whitelist assumptions. The stack's behavior is the entire mechanism; there is no filesystem access, no symlink resolution, and no unbounded loop beyond the input length.
What would settle it
Run sanitize("/home/NonexistentUserFolder/../ActualUserFolder/", ["/home/ActualUserFolder/"]) ; it returns true while the operating system reports that the first path does not exist, so the claimed if-and-only-if relationship with the filesystem fails for a concrete input.
Extended reading notes
Core claim
The central discovery is that directory traversal defense can be reduced to a pure string-collapsing operation: treat every path as a stack of directory names, where . is a no-op and .. pops the current top, then compare the resulting canonical string against a whitelist. The stack is entirely in memory, never touching the filesystem, which makes the routine cross-platform and free of symlink-resolution pitfalls if whitelist entries are canonical and symlink-free. The paper proves Theorem 1 to establish the soundness and completeness of this comparison, and reports that symbolic execution over all strings of length up to 12 finds no output containing /../ or /./, supporting the claim that no traversal token survives canonicalization.
Load-bearing premise
The load-bearing premise is that a purely textual collapse of . and .. matches the operating system's own path resolution for every path that reaches the whitelist check, including the existence of intermediate directories and the behavior of .. at the root.
Editorial extensions
If this is right
- Whitelist maintenance becomes tractable: infinitely many path spellings of one file all reduce to a single canonical string, so a small, static whitelist can govern access.
- Verification is practical enough for regression testing: exhaustive symbolic execution over bounded input lengths runs in minutes and finds no traversal tokens in the output.
- The routine ports to any language with a stack container and requires no system calls, making it usable in sandboxed or minimal web-application environments.
- When the algorithm accepts a path the filesystem later rejects, the actual I/O fails closed; the paper contends this does not weaken the defense because whitelisted entries are valid paths.
Reading between the lines
- A corrected variant could push a root sentinel onto the stack before processing, so a leading .. at the root pops the sentinel instead of being silently discarded; that would align the algorithm with POSIX resolution while preserving the rest of the machinery.
- The same stack collapse could be extended to case-insensitive or mount-aware filesystems by adding a normalization step before the final contains check, though the paper does not address those environments.
- If the final check were changed from exact string equality to prefix or wildcard matching, the algorithm would lose its correctness guarantee; an implementer wanting wildcards would need a new theorem.
Signed reviews
Editorial analysis
A structured set of objections, weighed in public.
Referee Report
Summary. The paper proposes a stack-based algorithm, 'sanitize', that tokenizes a user-supplied path string, resolves '.' and '..' tokens, and returns true if the resulting canonical string is contained in a whitelist of allowed path strings. The authors claim this provides a portable, lightweight, and easily verifiable defense against directory traversal attacks, and they support the claim with a proof of correctness (Theorem 1, an if-and-only-if statement about file identity) and with symbolic-execution experiments using KLEE. The paper also surveys existing mitigations (character removal, canonicalization, whitelisting) and argues that the new algorithm combines the benefits of whitelisting and syntactic canonicalization while avoiding filesystem calls.
Significance. If Theorem 1 were true, the algorithm would indeed be a useful building block: it is simple, self-contained, and amenable to formal verification, and the paper deserves credit for attempting a proof and for shipping reproducible verification artifacts (KLEE runs and a GitHub implementation). However, the central if-and-only-if claim is false as stated, and the paper's own Section V.B provides counterexamples that the authors dismiss without adequate justification. Because the security guarantee rests entirely on Theorem 1, the significance of the contribution as presented is not established. The symbolic-execution checks are limited to a bounded string length and do not verify the theorem's file-identity semantics.
major comments (4)
- [§III.A (Theorem 1)] The forward direction of Theorem 1 is false, and the paper's own Section V.B supplies the counterexamples. For S1 = '/home/NonexistentUserFolder/../ActualUserFolder/' and S2 = '/home/ActualUserFolder/', sanitize(S1, [S2]) returns true because the token 'NonexistentUserFolder' is popped by the following '..', yet the filesystem cannot resolve S1 because the intermediate directory does not exist. Similarly, S1 = '/etc/passwd/./' is accepted even though the filesystem rejects a path that treats a regular file as a directory. In both cases S1 does not refer to the same file as S2 (indeed, S1 refers to no file), contradicting the claim that sanitize(S1, [S2]) is true if and only if S1 and S2 refer to the same file. The proof of (⇒) only shows that the algorithmic output string equals S2; it does not bridge the gap between the output string and filesystem semantics.
- [§III.A (Lemma 2 and Lemma 3)] Lemma 2 is stated without a rigorous proof; the sentence 'This follows from the assumptions...' is an assertion, not a derivation, and it is not obvious why the length inequality must hold for every pair of path strings that denote the same file, especially when '..' tokens cross non-existent or non-directory components. Lemma 3's Case 2 relies on an informal red/green coloring argument and asserts that every 'red' directory must be popped by a later '..', but this is exactly the invariant that needs a formal inductive proof. The subsequent case analysis in Theorem 1's backward direction also never analyzes the situation where the stack is empty and a '..' token is silently discarded at the root; this interacts with the prefix invariant in a way the proof does not address.
- [§III.A and §V.B] The paper acknowledges in Section V.B that sanitize 'does not process path strings in the same way as most operating systems or file systems' and then asserts that the resulting mismatches 'do not pose problems' because whitelisted path strings are valid. This assertion is not justified. The algorithm returns only a boolean, so a secure application must obtain the canonicalized string elsewhere for the actual file operation; the paper does not specify this usage or analyze the consequences of the application instead using the original user-supplied path after sanitize returns true. The acknowledged mismatches directly invalidate the theorem's file-identity claim, regardless of whether they constitute an exploit, because the theorem is stated about filesystem reference, not about string containment.
- [§III (assumptions)] The algorithm treats relative path tokens as though they were rooted at '/', but the paper never states an explicit input assumption that user-supplied path strings are absolute. Definition 1 defines path strings as absolute, but the assumptions paragraph in Section III mentions only symbolic links and wildcards. If an implementation applies sanitize to a relative path such as 'a/b/c', the stack becomes '/a/b/c' and may be accepted by a whitelist containing '/a/b/c', even though the application would resolve the relative path against some current working directory. The absolute-path requirement needs to be stated prominently, and the security consequences of violating it need to be discussed.
minor comments (4)
- [§IV] The symbolic-execution verification uses strings of length at most 12 and single-letter directory names; the paper claims this is 'an effective and equivalent way' to represent longer paths, but no formal equivalence argument is given, and the experiments verify only that certain traversal tokens do not appear in the output and that a particular output string is enumerable, not the full if-and-only-if claim of Theorem 1.
- [§III (Algorithm 2)] In Algorithm 2, the loop condition 'for i← 0 to s.size' combined with 'result.append(s.data[i])' appears to access s.data[s.size] on the final iteration, which is out of bounds in a 0-indexed array; the pseudocode should clarify the intended bounds and indexing convention.
- [§II.C.1] The footnote and Figure 3 caption contain typographical inconsistencies ('mini httpd' vs. 'mini_httpd', 't httpd'), and several references have URLs with unescaped spaces (e.g., [1]); these presentational issues should be cleaned up before any revised submission.
- [§III.A] The proof of Theorem 1 contains several wording glitches, including 'contain smethod' and 'S2a re allowed', and the proof's forward direction repeatedly refers to S1 after canonicalization as if it were the original input string, which obscures the distinction between the input string and the algorithm's output.
Circularity Check
No significant circularity; the algorithm and proof are self-contained, though Theorem 1's semantic equivalence is not established.
full rationale
The paper does not fit parameters to data, does not import load-bearing results from the authors' prior work, and does not rename an existing result as a new derivation. sanitize is defined independently as a stack-based canonicalizer, and the claimed contribution is the proof that its output matches filesystem identity. The only self-reference is to the author's own GitHub implementation [16], used for reproducibility and KLEE runs; it is not cited as evidence for the correctness theorem, so it is not load-bearing. The theorem proof does contain a gap: the forward direction reduces 'refers to the same file' to string equality without proving that the syntactic canonicalization matches the OS's resolution, and Section V.B explicitly gives counterexamples ('/home/NonexistentUserFolder/../ActualUserFolder/' and '/etc/passwd/./') where sanitize accepts strings the filesystem rejects. These are correctness and soundness problems with Theorem 1, not circular reasoning. Since no derivation step is equivalent to its input by construction, the circularity score is 0.
Assumptions & free parameters
assumptions (4)
- domain assumption Path strings contain no symbolic links and no wildcard characters.
- domain assumption The whitelisted path string S2 is canonicalized.
- ad hoc to paper All user-supplied path strings are absolute and relative '..' tokens are interpreted from the root, so a leading '..' with an empty stack is discarded instead of being resolved against a current working directory.
- ad hoc to paper Lemma 2: if S1 and S2 refer to the same file and S2 is canonicalized, then S1.length >= S2.length; used to argue that all extra directories are eventually popped.
Cite this review
Pith. "Pith review of A Simple and Intuitive Algorithm for Preventing Directory Traversal Attacks." pith.science (2026). https://pith.science/paper/LB6LPW5S
@misc{pith2026190804502,
author = {Pith},
title = {Pith review of: A Simple and Intuitive Algorithm for Preventing Directory Traversal Attacks},
year = {2026},
howpublished = {\url{https://pith.science/paper/LB6LPW5S}},
note = {Machine review of arXiv:1908.04502}
}
read the original abstract
With web applications becoming a preferred method of presenting graphical user interfaces to users, software vulnerabilities affecting web applications are becoming more and more prevalent and devastating. Some of these vulnerabilities, such as directory traversal attacks, have varying defense mechanisms and mitigations that can be difficult to understand, analyze, and test. Gaps in the testing of these directory traversal defense mechanisms can lead to vulnerabilities that allow attackers to read sensitive data from files or even execute malicious code. This paper presents an analysis of some currently used directory traversal attack defenses and presents a new, stack-based algorithm to help prevent these attacks by safely canonicalizing user-supplied path strings. The goal of this algorithm is to be small, easy to test, cross-platform compatible, and above all, intuitive. We provide a proof of correctness and verification strategies using symbolic execution for the algorithm. We hope that the algorithm is simple and effective enough to help move developers towards a unified defense against directory traversal attacks.
Figures
Figures from the paper (2 more)
Reference graph
Works this paper leans on
-
[1]
(2019) 2018 application security research update
Micro Focus Fortify Software Security Research Team. (2019) 2018 application security research update. [Online]. Avail- able: https://www.microfocus.com/media/report/application security research update report.pdf
work page 2019
-
[2]
Pixy: a static analysis tool for detecting web application vulnerabilities,
N. Jovanovic, C. Kruegel, and E. Kirda, “Pixy: a static analysis tool for detecting web application vulnerabilities,” in 2006 IEEE Symposium on Security and Privacy (S P’06) , May 2006, pp. 6 pp.–263
work page 2006
-
[3]
A static analysis framework for detecting sql injection vulnerabilities,
X. Fu, X. Lu, B. Peltsverger, S. Chen, K. Qian, and L. Tao, “A static analysis framework for detecting sql injection vulnerabilities,” in 31st Annual International Computer Software and Applications Conference (COMPSAC 2007), vol. 1, July 2007, pp. 87–96
work page 2007
-
[4]
Static detection of cross-site scripting vulnerabilities,
G. Wassermann and Z. Su, “Static detection of cross-site scripting vulnerabilities,” in 2008 ACM/IEEE 30th International Conference on Software Engineering, May 2008, pp. 171–180
work page 2008
-
[5]
Why johnny cant pentest: An analysis of black-box web vulnerability scanners,
A. Doup, M. Cova, and G. Vigna, “Why johnny cant pentest: An analysis of black-box web vulnerability scanners,” Proc. DIMVA 2010, vol. 6201, pp. 111–131, 07 2010
work page 2010
-
[6]
L. Kohnfelder, E. Heymann, and B. P. Miller, “University of Wisconsin- Madison Lecture Notes - Introduction to Software Security: Chapter 3.3 Directory Traversal Attacks.” 03 2019
work page 2019
-
[7]
A survey of symbolic execution techniques,
R. Baldoni, E. Coppa, D. C. D’Elia, C. Demetrescu, and I. Finocchi, “A survey of symbolic execution techniques,” ACM Comput. Surv., vol. 51, no. 3, 2018
work page 2018
-
[8]
Bacik, Information Security Management Handbook: Whitelisting , 6th ed
S. Bacik, Information Security Management Handbook: Whitelisting , 6th ed. Auerbach Publications, 2011, vol. 5
work page 2011
Show all 18 references
-
[9]
[Online]
thttpd. [Online]. Available: https://acme.com/software/thttpd/
-
[10]
[Online]
mini httpd. [Online]. Available: https://acme.com/software/mini httpd/
-
[11]
(2019, 06) Knowledge Base: Create a Symbolic Link in Unix
Indiana University. (2019, 06) Knowledge Base: Create a Symbolic Link in Unix. [Online]. Available: https://kb.iu.edu/d/abbe
2019
-
[12]
realpath
Coreutils. realpath. [Online]. Available: https://github.com/coreutils/ coreutils/blob/master/src/realpath.c
-
[13]
Manual: realpath
PHP. Manual: realpath. [Online]. Available: https://www.php.net/ manual/en/function.realpath.php
-
[14]
How to Open a File and Not Get Hacked,
J. A. Kupsch and B. P. Miller, “How to Open a File and Not Get Hacked,” in 2008 Third International Conference on Availability, Re- liability and Security , March 2008, pp. 1196–1203
2008
-
[15]
(2018, 10) CVE-2018-18778 Details
National Vulnerability Database. (2018, 10) CVE-2018-18778 Details. [Online]. Available: https://nvd.nist.gov/vuln/detail/CVE-2018-18778
2018
-
[16]
sanitize,
M. Flanders, “sanitize,” https://github.com/flandini/sanitize, 2019
2019
-
[17]
The Single UNIX Specification - 2nd Version, string.h: strtok r
The Open Group. The Single UNIX Specification - 2nd Version, string.h: strtok r. [Online]. Available: http://pubs.opengroup.org/onlinepubs/ 7908799/xsh/strtok r.html
-
[18]
KLEE: Unassisted and Automatic Generation of High-coverage Tests for Complex Systems Programs,
C. Cadar, D. Dunbar, and D. Engler, “KLEE: Unassisted and Automatic Generation of High-coverage Tests for Complex Systems Programs,” in Proceedings of the 8th USENIX Conference on Operating Systems Design and Implementation , ser. OSDI’08. Berkeley, CA, USA: USENIX Association...
2008
Reviewed August 14, 2026 · model on record in the stance chip above.
Discussion (0). Continue with ORCID to comment.