Fixed 4 critical bugs in main.py#1
Open
ranujasanmir wants to merge 2 commits into
Open
Conversation
Fixed 4 critical bugs in main.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Security Fix: Path Traversal, Symlink Traversal, XSS, and Header Injection in
main.pySummary
This PR fixes 4 security vulnerabilities in
main.py's HTTP request handler, ranging from critical path traversal bugs to stored XSS and HTTP header injection. No new dependencies are introduced — all fixes use Python's standard library (html,os.path.realpath,urllib.parse.quote).Vulnerabilities Fixed
🔴 Fix #1 — Path Traversal via
startswith()Prefix BypassSeverity: Critical
The bug:
str.startswith()matches on raw characters, not on path segments. If a shared root is/data/share, then a resolved path of/data/shareother/secret.txtpasses the check because the string literally starts with/data/share. An attacker on the network could potentially access files outside the intended shared directory if the filesystem layout has directories whose names are prefixes of a shared root name.The fix:
The traversal check is replaced entirely by
_safe_join(), a new dedicated helper that appendsos.sepbefore comparing, making the boundary exact:🔴 Fix #2 — Symlink Traversal (
normpathdoes not resolve symlinks)Severity: Critical
The bug:
os.path.normpath()only collapses redundant separators and../..components lexically. It does not follow symbolic links on disk. A symlink placed inside a shared folder and pointing to/etc/passwd(Linux) orC:\Windows\System32(Windows) would resolve to a path that still passed the oldstartswithcheck, allowing its target to be read and downloaded.The fix:
_safe_join()callsos.path.realpath()which fully resolves all symlinks before any comparison is made:🔴 Fix #3 — Stored XSS via Unescaped Filenames in HTML
Severity: Critical
The bug:
File and directory names were interpolated into the HTML response without any escaping. A file named
<script>alert(document.cookie)</script>.txtinside a shared folder would execute JavaScript in every browser that navigates to that directory. This is a stored XSS vulnerability affecting every connected device.The fix:
All user-controlled values — filenames, directory names, hrefs, and the page title — are now passed through
html.escape()before being placed in HTML context:URL values in
hrefattributes are additionally processed withurllib.parse.quote()to ensure they are valid and cannot break out of the attribute.🟠 Fix #4 — HTTP Header Injection via
Content-DispositionFilenameSeverity: High
The bug:
A filename containing
",\r, or\ncharacters could break out of the filename token and inject arbitrary HTTP response headers or corrupt the header block entirely. On some HTTP stacks this can lead to response splitting.The fix:
A new helper
_safe_filename_header()produces a dual-tokenContent-Dispositionvalue per RFC 6266 / RFC 5987:filename— ASCII-only fallback with dangerous characters stripped, safe for legacy browsersfilename*— full UTF-8 filename percent-encoded per RFC 5987, safe for modern browsersChanges at a Glance
main.pyimport htmlmain.py_safe_join(root, rel_path)— path traversal + symlink guardmain.py_safe_filename_header(filename)— RFC 5987 Content-Dispositionmain.pybuild_index_html()— all filenames and hrefs nowhtml.escape()'dmain.pybuild_dir_html()— all filenames, hrefs, and title nowhtml.escape()'dmain.pyhtml_shell()— title parameter nowhtml.escape()'dmain.pyserve_file()— uses_safe_filename_header()instead of raw f-stringmain.pydo_GET()— replaced inline traversal check with_safe_join()callNo changes to
gui.py. No new dependencies.Testing
To verify the fixes manually:
Path traversal (#1 & #2):
XSS (#3):
Header injection (#4):
Related Issues
Discovered during a security audit of the repository. No CVE assigned (local network tool, not publicly exposed).
Checklist
realpath()consistently