mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
5bca403c29
readSourceFragment() previously accepted any `file` field on the
SourceLocation it was given:
- if absolute, it read it directly (anywhere on disk);
- if relative, it joined with projectRoot but never verified the
resolved path stayed inside (so "../../../etc/passwd" worked).
The `file` field originates in a React fiber's _debugSource.fileName,
which a malicious app — or a cross-origin browser tab leveraging Vuln 1
to call debugger-evaluate — can mutate to any string. Combined with the
no-auth HTTP surface, this was an arbitrary file-read primitive
(~/.gitconfig, ~/.aws/credentials, /etc/passwd, ...).
Adds two gates inside readSourceFragment:
1. Containment: path.resolve the absolute candidate, then
path.relative(projectRoot, absPath) — null if it starts with `..`
or is itself absolute (escaped projectRoot).
2. Extension allowlist: only .js/.jsx/.ts/.tsx/.mjs/.cjs/.json. Even
.env files inside the project are out of scope here.
Both checks return null silently; the fiber-source-fragment path is
opportunistic (the inspector never required it to succeed) so attackers
get no signal about whether a file existed.