Skip to content

Fix: Default resolveSourceMapAnnotations to false to prevent arbitrary file read (#4322) - #4331

Open
kunaaaalcodes wants to merge 2 commits into
google:masterfrom
kunaaaalcodes:fix/issue-4322-sourcemap-traversal
Open

Fix: Default resolveSourceMapAnnotations to false to prevent arbitrary file read (#4322)#4331
kunaaaalcodes wants to merge 2 commits into
google:masterfrom
kunaaaalcodes:fix/issue-4322-sourcemap-traversal

Conversation

@kunaaaalcodes

Copy link
Copy Markdown

Summary

Fixes #4322.

Changes CompilerOptions.resolveSourceMapAnnotations to default to false instead of true.

Rationale

When resolveSourceMapAnnotations is true by default, compiling untrusted JS containing a //# sourceMappingURL= comment causes SourceMapResolver.extractSourceMap to resolve local filesystem paths automatically, creating an arbitrary file read vulnerability for untrusted inputs.

Flipping this default ensures closure-compiler is secure-by-default when handling untrusted JS inputs, following the mitigation pattern used for CVE-2026-49356 (@babel/core). Callers compiling trusted code can explicitly enable resolution via options.setResolveSourceMapAnnotations(true).

Verification

  • Added testResolveSourceMapAnnotationsDefaultsToFalse in CompilerOptionsTest.java.
  • Ran bazel test //:test/com/google/javascript/jscomp/CompilerOptionsTest (PASSED).

cc @lauraharker

@google-cla

google-cla Bot commented Aug 11, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@kunaaaalcodes
kunaaaalcodes force-pushed the fix/issue-4322-sourcemap-traversal branch 2 times, most recently from 2897ce8 to 67d8f84 Compare August 11, 2026 09:16
@kunaaaalcodes
kunaaaalcodes force-pushed the fix/issue-4322-sourcemap-traversal branch from 67d8f84 to bfd4d3e Compare August 11, 2026 09:19
@lauraharker lauraharker self-assigned this Aug 11, 2026
@kunaaaalcodes

Copy link
Copy Markdown
Author

Hi @lauraharker,

The Google CLA is signed and verified.

I've updated the PR with:

  • Default configuration fix: Set resolveSourceMapAnnotations to false in CompilerOptions.java (matching the secure-by-default pattern used in @babel/core for CVE-2026-49356).
  • Unit test coverage: Added testResolveSourceMapAnnotationsDefaultsToFalse in CompilerOptionsTest.java and updated test configurations in CompilerTest.java.
  • Local verification: Built and ran bazel test cleanly across the test suite.

Please take a look when you have a chance. Thanks!

@lauraharker

Copy link
Copy Markdown
Contributor

Hi Kunal -

I think we're somewhat concerned about flipping the default here breaking existing workflows. What do you think about restricting file reads to some heuristically "safe" set of directories?

@kunaaaalcodes

kunaaaalcodes commented Aug 15, 2026

Copy link
Copy Markdown
Author

Hi @lauraharker ,

Appreciate the feedback — agreed, flipping the default isn't really the fix. It just hides the problem, since anyone who turns resolveSourceMapAnnotations back on would be fully exposed again. Let's leave the default as-is.

For the "safe directories" idea, I want to keep it simple: a sourceMappingURL should only be allowed to resolve to something inside the JS file's own directory (or below it). Anything that tries to escape just gets ignored. No new config needed, existing workflows stay untouched, and the default doesn't change.

One thing worth calling out on scope — getRelativePath() is also used when resolving sources entries inside sourcemaps that are already loaded, and those can legitimately point outside the map's own directory (../src/... is a pretty normal layout). So I don't want to slap the check there. I'll put it in extractSourceMap instead, since that's the actual point where we're interpreting an annotation coming from untrusted input. Absolute URLs are already blocked there, so this just closes off the relative traversal case without touching legitimate sourcemap resolution.

Plan:

Separately, something to think about later: normalize() won't catch a symlink sitting inside the source directory that points outward, so that's technically still open. toRealPath() would fix it but gets messy with paths that don't exist yet. Happy to fold that into this PR or split it into a follow-up, whichever you'd prefer.

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.

Arbitrary file read via //# sourceMappingURL= path traversal in SourceMapResolver

2 participants