generated from bazel-contrib/rules-template
-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: add helper plugin to keep paths within sandbox (#160)
* fix: add helper plugin to keep paths within sandbox * respond to comments, attempt to incorporate into launcher.js * respond to PR review * make non-ESM and fix paths * remove semicolon * rename plugin to "bazel-sandbox", add an opt-out parameter and add debug logs and the ability to set the JS and esbuild log levels * Update docs * Handle external module resolutions --------- Co-authored-by: Greg Magolan <[email protected]>
- Loading branch information
1 parent
4f9895f
commit e39ac34
Showing
7 changed files
with
155 additions
and
16 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
const path = require('path') | ||
const process = require('process') | ||
|
||
// Regex matching any non-relative import path | ||
const pkgImport = /^[^.]/ | ||
|
||
const bindir = process.env.BAZEL_BINDIR | ||
const execroot = process.env.JS_BINARY__EXECROOT | ||
|
||
// Under Bazel, esbuild will follow symlinks out of the sandbox when the sandbox is enabled. See https://github.com/aspect-build/rules_esbuild/issues/58. | ||
// This plugin using a separate resolver to detect if the the resolution has left the execroot (which is the root of the sandbox | ||
// when sandboxing is enabled) and patches the resolution back into the sandbox. | ||
function bazelSandboxPlugin() { | ||
return { | ||
name: 'bazel-sandbox', | ||
setup(build) { | ||
const moduleCache = new Map() | ||
build.onResolve( | ||
{ filter: /./ }, | ||
async ({ path: importPath, ...otherOptions }) => { | ||
// NB: these lines are to prevent infinite recursion when we call `build.resolve`. | ||
if (otherOptions.pluginData) { | ||
if (otherOptions.pluginData.executedSandboxPlugin) { | ||
return | ||
} | ||
} else { | ||
otherOptions.pluginData = {} | ||
} | ||
otherOptions.pluginData.executedSandboxPlugin = true | ||
|
||
// Prevent us from loading different forms of a module (CJS vs ESM). | ||
if (pkgImport.test(importPath)) { | ||
if (!moduleCache.has(importPath)) { | ||
moduleCache.set( | ||
importPath, | ||
resolveInExecroot(build, importPath, otherOptions) | ||
) | ||
} | ||
return await moduleCache.get(importPath) | ||
} | ||
return await resolveInExecroot(build, importPath, otherOptions) | ||
} | ||
) | ||
}, | ||
} | ||
} | ||
|
||
async function resolveInExecroot(build, importPath, otherOptions) { | ||
const result = await build.resolve(importPath, otherOptions) | ||
|
||
if (result.errors && result.errors.length) { | ||
// There was an error resolving, just return the error as-is. | ||
return result | ||
} | ||
|
||
if ( | ||
!result.path.startsWith('.') && | ||
!result.path.startsWith('/') && | ||
!result.path.startsWith('\\') | ||
) { | ||
// Not a relative or absolute path. Likely a module resolution that is marked "external" | ||
return result | ||
} | ||
|
||
// If esbuild attempts to leave the execroot, map the path back into the execroot. | ||
if (!result.path.startsWith(execroot)) { | ||
// If it tried to leave bazel-bin, error out completely. | ||
if (!result.path.includes(bindir)) { | ||
throw new Error( | ||
`Error: esbuild resolved a path outside of BAZEL_BINDIR (${bindir}): ${result.path}` | ||
) | ||
} | ||
// Otherwise remap the bindir-relative path | ||
const correctedPath = path.join( | ||
execroot, | ||
result.path.substring(result.path.indexOf(bindir)) | ||
) | ||
if (!!process.env.JS_BINARY__LOG_DEBUG) { | ||
console.error( | ||
`DEBUG: [bazel-sandbox] correcting esbuild resolution ${result.path} that left the sandbox to ${correctedPath}.` | ||
) | ||
} | ||
result.path = correctedPath | ||
} | ||
return result | ||
} | ||
|
||
module.exports = { bazelSandboxPlugin } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters