Summary
A third file-URI shape, the file::http forced getter, bypasses the allow-dirs sandbox because the containment check treats it as a relative path under the working directory while go-getter opens the inner URL's absolute path. Live at HEAD 0.4.6+3 (981f706).
The defect
module/restrictions.go lines 61-96. The 0.4.6 fix (GHSA-j4wj) handled two file: shapes (its code comment enumerates them). It does not handle a third: a forced getter of the form file::http://host/abs/path. isRemoteSource and stripFileScheme treat file::http://host/abs/path as a LOCAL RELATIVE PATH under the working directory, so it passes the containment check, while go-getter's forced file getter opens the INNER URL's absolute u.Path. The two components disagree about what the string denotes, the same divergence class this campaign has confirmed repeatedly, here between the validator and go-getter.
Verified by execution through the real csv_reader vtable entry point: payloads read a file OUTSIDE --allow-dirs (content asserted) and read /etc/passwd, while FIVE negative controls, including the two already-fixed file: shapes, were correctly denied. That control set shows this is a genuinely new third shape rather than a re-report. Precondition, stated honestly: the same deployment shape the maintainer ALREADY ACCEPTED for GHSA-j4wj (the working directory being inside an allowed directory), and server mode is unauthenticated by default.
Suggested fix
Resolve the source to the exact path go-getter will open BEFORE the containment check, rather than inferring it, and reject any forced-getter prefix whose inner target escapes the allowlist. The durable fix is to derive the path to be opened and the path to be validated from the same resolution, so a third, fourth or fifth scheme shape cannot diverge again.
Also checked and sound: the ATTACH authorizer, the read_log grok gate, the MCP and GPT authentication, and the plugin-registry hash-pinning.
Tooling
I used AI assistance while investigating. The escape was executed through the real csv_reader entry point reading a file outside the allowlist and /etc/passwd, with five negative controls including the two already-fixed shapes, and I confirmed the cited helpers at HEAD.
I manually verified this finding against the project's source at the location cited above before reporting it; the AI assistance noted above was for the audit and the drafting.
Summary
A third file-URI shape, the file::http forced getter, bypasses the allow-dirs sandbox because the containment check treats it as a relative path under the working directory while go-getter opens the inner URL's absolute path. Live at HEAD 0.4.6+3 (981f706).
The defect
module/restrictions.go lines 61-96. The 0.4.6 fix (GHSA-j4wj) handled two file: shapes (its code comment enumerates them). It does not handle a third: a forced getter of the form
file::http://host/abs/path. isRemoteSource and stripFileScheme treatfile::http://host/abs/pathas a LOCAL RELATIVE PATH under the working directory, so it passes the containment check, while go-getter's forced file getter opens the INNER URL's absolute u.Path. The two components disagree about what the string denotes, the same divergence class this campaign has confirmed repeatedly, here between the validator and go-getter.Verified by execution through the real csv_reader vtable entry point: payloads read a file OUTSIDE --allow-dirs (content asserted) and read /etc/passwd, while FIVE negative controls, including the two already-fixed file: shapes, were correctly denied. That control set shows this is a genuinely new third shape rather than a re-report. Precondition, stated honestly: the same deployment shape the maintainer ALREADY ACCEPTED for GHSA-j4wj (the working directory being inside an allowed directory), and server mode is unauthenticated by default.
Suggested fix
Resolve the source to the exact path go-getter will open BEFORE the containment check, rather than inferring it, and reject any forced-getter prefix whose inner target escapes the allowlist. The durable fix is to derive the path to be opened and the path to be validated from the same resolution, so a third, fourth or fifth scheme shape cannot diverge again.
Also checked and sound: the ATTACH authorizer, the read_log grok gate, the MCP and GPT authentication, and the plugin-registry hash-pinning.
Tooling
I used AI assistance while investigating. The escape was executed through the real csv_reader entry point reading a file outside the allowlist and /etc/passwd, with five negative controls including the two already-fixed shapes, and I confirmed the cited helpers at HEAD.
I manually verified this finding against the project's source at the location cited above before reporting it; the AI assistance noted above was for the audit and the drafting.