feat: Add support for environment protection (scrubbing) (#327)

* feat: Add support for environment variable protection for sandbox

* chore: Update dangerous env var list

* fix: Split profiles for improved environment protection

* fix: pipx sandbox profile separation

* chore: Show sandbox scrub info on error exit

* fix: Code review fixes

* test: Add e2e for sandbox environment scrubbing
This commit is contained in:
Abhisek Datta
2026-06-11 11:40:33 +05:30
committed by GitHub
parent 7620097613
commit c7244f921a
39 changed files with 1385 additions and 49 deletions
+19
View File
@@ -0,0 +1,19 @@
name: bun
description: Profile for bun, extending npm-restrictive with bun environment variables
inherits: npm-restrictive
package_managers:
- bun
environment:
# Bun authenticates via BUN_AUTH_TOKEN and also reads .npmrc with env
# interpolation and npm_config_* conventions. Sibling tokens
# (YARN_NPM_AUTH_*) stay scrubbed.
allow:
- BUN_AUTH_TOKEN
- NPM_TOKEN
- NPM_AUTH_TOKEN
- NODE_AUTH_TOKEN
- npm_config_*
- NPM_CONFIG_*
- NODE_EXTRA_CA_CERTS
+8
View File
@@ -93,6 +93,14 @@ network:
deny_outbound:
- "*:*"
environment:
# This profile is the shared base for the npm ecosystem and deliberately
# allows no environment variables: everything in the built-in
# DANGEROUS_ENV_VARS list is scrubbed. Each package manager's leaf profile
# (npm, yarn, bun, pnpm, npx) re-allows only the variables that
# package manager needs for auth, registry config, and TLS.
allow: []
process:
allow_exec:
- /usr/bin/node
+21
View File
@@ -0,0 +1,21 @@
name: npm
description: Profile for npm, extending npm-restrictive with npm environment variables
inherits: npm-restrictive
package_managers:
- npm
environment:
# The npm-restrictive base allows no environment variables. Re-allow only
# what npm needs for auth, registry config, and TLS.
#
# Accepted trade-off: a malicious JS package executed during install can read
# the npm publishing token below, but NOT yarn/bun tokens, PyPI tokens, AWS
# keys, or other cloud/secret-manager credentials, which remain scrubbed.
allow:
- NPM_TOKEN
- NPM_AUTH_TOKEN
- NODE_AUTH_TOKEN
- npm_config_*
- NPM_CONFIG_*
- NODE_EXTRA_CA_CERTS
+13
View File
@@ -16,6 +16,19 @@ allow_pty: true
# npx generators and dev servers frequently need to bind to localhost ports
allow_network_bind: true
environment:
# The npm-restrictive base allows no environment variables. npx and pnpx
# execute npm-ecosystem packages and use the npm auth and config
# conventions. Sibling tokens (YARN_NPM_AUTH_*, BUN_AUTH_TOKEN) stay
# scrubbed.
allow:
- NPM_TOKEN
- NPM_AUTH_TOKEN
- NODE_AUTH_TOKEN
- npm_config_*
- NPM_CONFIG_*
- NODE_EXTRA_CA_CERTS
filesystem:
# Add write permissions for common generator outputs
allow_write:
+15
View File
@@ -0,0 +1,15 @@
name: pip
description: Profile for pip and pip3, extending pypi-restrictive with pip environment variables
inherits: pypi-restrictive
package_managers:
- pip
- pip3
environment:
# The pypi-restrictive base allows no environment variables. pip needs its
# own config namespace for index auth, mirrors, and TLS (e.g. PIP_INDEX_URL,
# PIP_CERT). Sibling tool credentials (UV_PUBLISH_TOKEN, POETRY_*) and
# TWINE_* stay scrubbed.
allow:
- PIP_*
+22 -1
View File
@@ -15,17 +15,38 @@ allow_pty: true
# pipx-executed tools may need to bind to localhost ports (e.g., dev servers)
allow_network_bind: true
environment:
# The pypi-restrictive base allows no environment variables. pipx delegates
# to pip inside its venvs, so it needs the pip config namespace for index
# auth and TLS. Sibling tool credentials (UV_PUBLISH_TOKEN, POETRY_*) and
# TWINE_* stay scrubbed.
allow:
- PIP_*
filesystem:
allow_read:
# pipx installs and manages packages in ~/.local/pipx
# pipx venv homes: ~/.local/pipx is the legacy default. pipx >= 1.5
# defaults PIPX_HOME to platformdirs locations when the legacy dir does
# not exist: ~/.local/share/pipx on Linux, ~/Library/Application Support/pipx
# on macOS.
- ${HOME}/.local/pipx/**
- ${HOME}/.local/share/pipx/**
- ${HOME}/Library/Application Support/pipx/**
- ${HOME}/.local/bin/**
# pipx run caches ephemeral venvs here
- ${HOME}/.cache/pipx/**
- ${HOME}/Library/Caches/pipx/**
# Add write permissions for pipx-specific paths
allow_write:
- ${CWD}/**
- ${HOME}/.local/pipx/**
- ${HOME}/.local/share/pipx/**
- ${HOME}/Library/Application Support/pipx/**
- ${HOME}/.local/bin/**
- ${HOME}/.cache/pipx/**
- ${HOME}/Library/Caches/pipx/**
# Additional deny rules for extra security
deny_write:
@@ -1,10 +1,23 @@
name: pnpm-restrictive
description: Profile for pnpm with write access to current directory
name: pnpm
description: Profile for pnpm, extending npm-restrictive with pnpm write paths and environment variables
inherits: npm-restrictive
package_managers:
- pnpm
environment:
# The npm-restrictive base allows no environment variables. pnpm uses the
# npm auth and config conventions (.npmrc with env interpolation,
# npm_config_*). Sibling tokens (YARN_NPM_AUTH_*, BUN_AUTH_TOKEN) stay
# scrubbed.
allow:
- NPM_TOKEN
- NPM_AUTH_TOKEN
- NODE_AUTH_TOKEN
- npm_config_*
- NPM_CONFIG_*
- NODE_EXTRA_CA_CERTS
filesystem:
allow_write:
# pnpm needs write access here
+17
View File
@@ -0,0 +1,17 @@
name: poetry
description: Profile for poetry, extending pypi-restrictive with poetry environment variables
inherits: pypi-restrictive
package_managers:
- poetry
environment:
# The pypi-restrictive base allows no environment variables. poetry needs
# its own config namespace and can delegate to pip. Sibling tool credentials
# (UV_PUBLISH_TOKEN) and TWINE_* stay scrubbed.
#
# Accepted trade-off: POETRY_* re-allows POETRY_PYPI_TOKEN_PYPI and
# POETRY_HTTP_BASIC_PYPI_PASSWORD, poetry's own publishing credentials.
allow:
- POETRY_*
- PIP_*
+10
View File
@@ -3,6 +3,7 @@ description: Restrictive sandbox policy for PyPI ecosystem (pip, poetry, uv)
package_managers:
- pip
- pip3
- pipx
- poetry
- uv
@@ -71,6 +72,15 @@ network:
deny_outbound:
- "*:*"
environment:
# This profile is the shared base for the PyPI ecosystem and deliberately
# allows no environment variables: everything in the built-in
# DANGEROUS_ENV_VARS list is scrubbed. Each package manager's leaf profile
# (pip, uv, poetry) re-allows only the variables that package manager needs.
# TWINE_* is allowed nowhere: twine is not a package manager PMG wraps, so
# its publishing credentials stay scrubbed during installs.
allow: []
process:
allow_exec:
- /usr/bin/python*
+17
View File
@@ -0,0 +1,17 @@
name: uv
description: Profile for uv, extending pypi-restrictive with uv environment variables
inherits: pypi-restrictive
package_managers:
- uv
environment:
# The pypi-restrictive base allows no environment variables. uv needs its
# own config namespace and honors pip env conventions via the uv pip
# interface. Sibling tool credentials (POETRY_*) and TWINE_* stay scrubbed.
#
# Accepted trade-off: UV_* re-allows UV_PUBLISH_TOKEN, uv's own publishing
# credential.
allow:
- UV_*
- PIP_*
+20
View File
@@ -0,0 +1,20 @@
name: yarn
description: Profile for yarn, extending npm-restrictive with yarn environment variables
inherits: npm-restrictive
package_managers:
- yarn
environment:
# Yarn berry authenticates via YARN_NPM_AUTH_*. Yarn classic reads .npmrc
# with env interpolation and npm_config_* conventions, so the shared npm
# auth set is also needed. Sibling tokens (BUN_AUTH_TOKEN) stay scrubbed.
allow:
- YARN_NPM_AUTH_TOKEN
- YARN_NPM_AUTH_IDENT
- NPM_TOKEN
- NPM_AUTH_TOKEN
- NODE_AUTH_TOKEN
- npm_config_*
- NPM_CONFIG_*
- NODE_EXTRA_CA_CERTS