Skip to content

Harden two hostile-input paths reaching the crawl (project name, UTF-8)#19

Merged
xroche merged 5 commits into
masterfrom
fix/native-hostile-input
Jul 18, 2026
Merged

Harden two hostile-input paths reaching the crawl (project name, UTF-8)#19
xroche merged 5 commits into
masterfrom
fix/native-hostile-input

Conversation

@xroche

@xroche xroche commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Two hostile-input paths that a crawled server can drive.

The project name becomes the engine's -O destination with no validation, and File does not fold .., so a name like ../../sdcard/evil writes outside the Websites tree. It is typeable, and a crafted winprofile.ini supplies it without the user typing anything, since the profile load overwrites the name in the map. A pure StoragePaths.isValidProjectName now rejects empty, ., .., and any path separator. It is enforced when advancing past the name pane (with a message) and as a backstop in getTargetFile, where the crawl aborts cleanly rather than escaping. A unit test covers it, and it is mutation-checked: a naive /-only validator fails the bare-.. case.

newStringSafe relied on NewStringUTF raising a Java exception on malformed modified UTF-8, which it does not, so its guard was dead code and its "ignore invalid UTF-8" contract was false. build_stats() feeds it server-controlled bytes (Content-Type, charset, HTTP status, URLs). It now sanitizes to well-formed modified UTF-8 first (invalid sequences become ?), so hostile bytes cannot reach NewStringUTF and trip a CheckJNI abort.

From the pre-KVM audit (findings #7, #8, medium). The real abort-vs-clean-String behavior and the profile-import rejection need a device to confirm; the validator and the sanitizer are covered by the -Werror native build and the JUnit test.

xroche and others added 5 commits July 18, 2026 19:03
The project name became the engine's -O destination with no validation, and
File does not fold "..", so a name like "../../sdcard/evil" — typeable, or
supplied by a crafted winprofile.ini that overwrites the map on load — steered
writes outside the Websites tree. A pure StoragePaths.isValidProjectName now
rejects empty, ".", ".." and any path separator, enforced when advancing past
the name pane (with a message) and as a backstop in getTargetFile, where the
crawl then aborts cleanly instead of escaping. Covered by a discriminating
unit test.

newStringSafe relied on NewStringUTF raising a Java exception on malformed
modified UTF-8, which it does not, so its guard was dead and its "ignore
invalid UTF-8" contract false; build_stats feeds it server-controlled bytes
(Content-Type, charset, status, urls). It now sanitizes to well-formed
modified UTF-8 first, so hostile bytes cannot reach NewStringUTF and trip a
CheckJNI abort.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
Review follow-up. When sanitizeModifiedUtf8's malloc fails, newStringSafe fell
back to the raw string, which under CheckJNI on hostile input is exactly the
abort the sanitizer exists to prevent. Return null there instead: a null field
beats an abort. Also dropped a redundant project-name test; the bare ".." case
is already covered by refusesEmptyOrDotSegments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche merged commit 23e0c17 into master Jul 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant