diff --git a/src/com/google/javascript/jscomp/CompilerOptions.java b/src/com/google/javascript/jscomp/CompilerOptions.java index 74a6737d36f..deeee4b897b 100644 --- a/src/com/google/javascript/jscomp/CompilerOptions.java +++ b/src/com/google/javascript/jscomp/CompilerOptions.java @@ -1165,8 +1165,18 @@ void addReportGenerator(SortingErrorManager.ErrorReportGenerator generator) { /** * Whether to resolve source mapping annotations. Cannot do this in an appengine or js environment * since we don't have access to the filesystem. - */ - private boolean resolveSourceMapAnnotations = true; + * + *
Defaults to {@code false}. When enabled, a {@code //# sourceMappingURL=} comment in
+ * compiled JS is followed to a file on the local filesystem (see {@link
+ * SourceMapResolver#extractSourceMap}), including via relative paths such as {@code
+ * ../../../../etc/passwd} that resolve outside the directory of the file being compiled. If
+ * this defaulted to {@code true}, compiling untrusted or third-party JavaScript source (e.g. in
+ * a hosted minification service or CI environment) would let the input JS trigger an arbitrary
+ * local file read with no explicit opt-in required. Callers who need to resolve source mapping
+ * annotations over source they fully trust can opt back in with {@link
+ * #setResolveSourceMapAnnotations}.
+ */
+ private boolean resolveSourceMapAnnotations = false;
private ImmutableList extends SourceMap.LocationMapping> sourceMapLocationMappings =
ImmutableList.of();
diff --git a/test/com/google/javascript/jscomp/CompilerOptionsTest.java b/test/com/google/javascript/jscomp/CompilerOptionsTest.java
index b08ecbc95a5..1b1fb65432a 100644
--- a/test/com/google/javascript/jscomp/CompilerOptionsTest.java
+++ b/test/com/google/javascript/jscomp/CompilerOptionsTest.java
@@ -39,6 +39,15 @@
@RunWith(JUnit4.class)
public final class CompilerOptionsTest {
+ @Test
+ public void testResolveSourceMapAnnotationsDefaultsToFalse() {
+ CompilerOptions options = new CompilerOptions();
+ assertThat(options.getResolveSourceMapAnnotations()).isFalse();
+
+ options.setResolveSourceMapAnnotations(true);
+ assertThat(options.getResolveSourceMapAnnotations()).isTrue();
+ }
+
@Test
public void testBrowserFeaturesetYearOptionSetsLanguageOut() {
CompilerOptions options = new CompilerOptions();
diff --git a/test/com/google/javascript/jscomp/CompilerTest.java b/test/com/google/javascript/jscomp/CompilerTest.java
index 21b9447face..1e3882983c3 100644
--- a/test/com/google/javascript/jscomp/CompilerTest.java
+++ b/test/com/google/javascript/jscomp/CompilerTest.java
@@ -259,6 +259,7 @@ function X(input) {
public void testInputSourceMapInline() {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
+ compiler.getOptions().setResolveSourceMapAnnotations(true);
String code = SOURCE_MAP_TEST_CODE + "\n//# sourceMappingURL=" + BASE64_ENCODED_SOURCE_MAP;
CompilerInput input = new CompilerInput(SourceFile.fromCode("tmp", code));
input.getAstRoot(compiler);
@@ -290,6 +291,7 @@ function A(input) {
public void testInputSourceMapInlineContent() {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
+ compiler.getOptions().setResolveSourceMapAnnotations(true);
String code =
SOURCE_MAP_TEST_CODE + "\n//# sourceMappingURL=" + BASE64_ENCODED_SOURCE_MAP_WITH_CONTENT;
CompilerInput input = new CompilerInput(SourceFile.fromCode("tmp", code));
@@ -305,6 +307,7 @@ public void testInputSourceMapInlineContent() {
public void testResolveRelativeSourceMap() throws Exception {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
+ compiler.getOptions().setResolveSourceMapAnnotations(true);
File tempDir = Files.createTempDir();
String code = SOURCE_MAP_TEST_CODE + "\n//# sourceMappingURL=foo.js.map";
File jsFile = new File(tempDir, "foo.js");
@@ -330,6 +333,7 @@ public void testResolveRelativeSourceMap() throws Exception {
public void testResolveRelativeDirSourceMap() throws Exception {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
+ compiler.getOptions().setResolveSourceMapAnnotations(true);
File tempDir = Files.createTempDir();
File relativedir = new File(tempDir, "/relativedir");
relativedir.mkdir();
@@ -356,6 +360,7 @@ public void testResolveRelativeDirSourceMap() throws Exception {
public void testMissingSourceMapFile() throws Exception {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
+ compiler.getOptions().setResolveSourceMapAnnotations(true);
File tempDir = Files.createTempDir();
String code = SOURCE_MAP_TEST_CODE + "\n//# sourceMappingURL=foo-does-not-exist.js.map";
File jsFile = new File(tempDir, "foo2.js");
@@ -434,6 +439,7 @@ public void testKeepInputSourceMapsSourcesContent() throws Exception {
options.setLanguageIn(LanguageMode.ECMASCRIPT3);
options.setSourceMapOutputPath("fake/source_map_path.js.map");
options.setApplyInputSourceMaps(true);
+ options.setResolveSourceMapAnnotations(true);
options.setSourceMapIncludeSourcesContent(true);
String code =
SOURCE_MAP_TEST_CODE + "\n//# sourceMappingURL=" + BASE64_ENCODED_SOURCE_MAP_WITH_CONTENT;
@@ -1563,6 +1569,7 @@ public void testCheckSaveRestore3StagesSourceMaps() throws Exception {
// maps when running the final stage later.
options.setAlwaysGatherSourceMapInfo(true);
options.setApplyInputSourceMaps(true);
+ options.setResolveSourceMapAnnotations(true);
options.setSourceMapIncludeSourcesContent(true);
CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
List