mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
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:
@@ -24,6 +24,162 @@ var DANGEROUS_FILES = []string{
|
||||
".config/gh",
|
||||
}
|
||||
|
||||
// DANGEROUS_ENV_VARS are credential-bearing environment variables scrubbed from
|
||||
// the child process by default when the sandbox is enabled (see ScrubEnv). This
|
||||
// is an explicit, curated list of known secret names. There are deliberately
|
||||
// no generic "*_TOKEN" / "*_SECRET" catch-alls here, because broad wildcards in
|
||||
// the default would risk clipping legitimate build variables for every user.
|
||||
// The matcher (ScrubEnv) does support glob patterns, so users who want broader
|
||||
// coverage opt into it per profile via environment.deny.
|
||||
//
|
||||
// Matching is case-insensitive (see ScrubEnv). A package manager's own
|
||||
// publishing token is intentionally left scrubbable here and re-allowed per
|
||||
// ecosystem in the profile's environment.allow (e.g. npm re-allows NPM_TOKEN).
|
||||
var DANGEROUS_ENV_VARS = []string{
|
||||
// Cloud providers
|
||||
"AWS_ACCESS_KEY_ID",
|
||||
"AWS_SECRET_ACCESS_KEY",
|
||||
"AWS_SESSION_TOKEN",
|
||||
"AWS_SECURITY_TOKEN",
|
||||
"AZURE_CLIENT_SECRET",
|
||||
"AZURE_CLIENT_ID",
|
||||
"AZURE_TENANT_ID",
|
||||
"ARM_CLIENT_SECRET",
|
||||
"GOOGLE_APPLICATION_CREDENTIALS",
|
||||
"GOOGLE_CREDENTIALS",
|
||||
"GOOGLE_OAUTH_ACCESS_TOKEN",
|
||||
"GCP_SERVICE_ACCOUNT_KEY",
|
||||
"CLOUDSDK_AUTH_ACCESS_TOKEN",
|
||||
"DIGITALOCEAN_ACCESS_TOKEN",
|
||||
"DIGITALOCEAN_TOKEN",
|
||||
"CLOUDFLARE_API_TOKEN",
|
||||
"CLOUDFLARE_API_KEY",
|
||||
"HEROKU_API_KEY",
|
||||
"FLY_API_TOKEN",
|
||||
"RAILWAY_TOKEN",
|
||||
"VERCEL_TOKEN",
|
||||
"NETLIFY_AUTH_TOKEN",
|
||||
|
||||
// Package registry / publishing tokens
|
||||
"NPM_TOKEN",
|
||||
"NPM_AUTH_TOKEN",
|
||||
"NODE_AUTH_TOKEN",
|
||||
"NPM_CONFIG__AUTH",
|
||||
"YARN_NPM_AUTH_TOKEN",
|
||||
"YARN_NPM_AUTH_IDENT",
|
||||
"BUN_AUTH_TOKEN",
|
||||
"TWINE_USERNAME",
|
||||
"TWINE_PASSWORD",
|
||||
"PYPI_TOKEN",
|
||||
"UV_PUBLISH_TOKEN",
|
||||
"FLIT_PASSWORD",
|
||||
"POETRY_PYPI_TOKEN_PYPI",
|
||||
"POETRY_HTTP_BASIC_PYPI_PASSWORD",
|
||||
"ANACONDA_API_TOKEN",
|
||||
"GEM_HOST_API_KEY",
|
||||
"RUBYGEMS_API_KEY",
|
||||
"CARGO_REGISTRY_TOKEN",
|
||||
"COMPOSER_AUTH",
|
||||
"HEX_API_KEY",
|
||||
"NUGET_API_KEY",
|
||||
"CONAN_LOGIN_PASSWORD",
|
||||
"CONAN_PASSWORD",
|
||||
"DENO_AUTH_TOKENS",
|
||||
"EXPO_TOKEN",
|
||||
"JFROG_ACCESS_TOKEN",
|
||||
"ARTIFACTORY_ACCESS_TOKEN",
|
||||
"ARTIFACTORY_API_KEY",
|
||||
"ARTIFACTORY_PASSWORD",
|
||||
|
||||
// VCS / CI
|
||||
"GITHUB_TOKEN",
|
||||
"GH_TOKEN",
|
||||
"GH_ENTERPRISE_TOKEN",
|
||||
"GITLAB_TOKEN",
|
||||
"CI_JOB_TOKEN",
|
||||
"CIRCLE_TOKEN",
|
||||
"BUILDKITE_AGENT_TOKEN",
|
||||
"BUILDKITE_API_TOKEN",
|
||||
"AZURE_DEVOPS_EXT_PAT",
|
||||
"SYSTEM_ACCESSTOKEN",
|
||||
|
||||
// Secrets managers
|
||||
"VAULT_TOKEN",
|
||||
"CONSUL_HTTP_TOKEN",
|
||||
"NOMAD_TOKEN",
|
||||
"OP_SERVICE_ACCOUNT_TOKEN",
|
||||
"OP_CONNECT_TOKEN",
|
||||
"BW_SESSION",
|
||||
"BWS_ACCESS_TOKEN",
|
||||
"DOPPLER_TOKEN",
|
||||
"INFISICAL_TOKEN",
|
||||
|
||||
// Infrastructure as code
|
||||
"TFE_TOKEN",
|
||||
"TF_API_TOKEN",
|
||||
"PULUMI_ACCESS_TOKEN",
|
||||
|
||||
// Misc high-value
|
||||
"DOCKER_PASSWORD",
|
||||
"DOCKER_AUTH_CONFIG",
|
||||
"SNYK_TOKEN",
|
||||
"CODECOV_TOKEN",
|
||||
"SONAR_TOKEN",
|
||||
"SENTRY_AUTH_TOKEN",
|
||||
"DATADOG_API_KEY",
|
||||
"DD_API_KEY",
|
||||
"DD_APP_KEY",
|
||||
"NEW_RELIC_API_KEY",
|
||||
"SLACK_BOT_TOKEN",
|
||||
"STRIPE_SECRET_KEY",
|
||||
"STRIPE_API_KEY",
|
||||
"TWILIO_AUTH_TOKEN",
|
||||
"SENDGRID_API_KEY",
|
||||
"FIREBASE_TOKEN",
|
||||
"SUPABASE_SERVICE_ROLE_KEY",
|
||||
"SUPABASE_ACCESS_TOKEN",
|
||||
|
||||
// AI providers
|
||||
"OPENAI_API_KEY",
|
||||
"ANTHROPIC_API_KEY",
|
||||
"AZURE_OPENAI_API_KEY",
|
||||
"HUGGING_FACE_HUB_TOKEN",
|
||||
"HF_TOKEN",
|
||||
"GEMINI_API_KEY",
|
||||
"GOOGLE_API_KEY",
|
||||
"COHERE_API_KEY",
|
||||
"MISTRAL_API_KEY",
|
||||
"GROQ_API_KEY",
|
||||
"OPENROUTER_API_KEY",
|
||||
"DEEPSEEK_API_KEY",
|
||||
"XAI_API_KEY",
|
||||
}
|
||||
|
||||
// ProtectedEnvVars are core process variables never scrubbed, regardless of
|
||||
// deny patterns. They are matched case-insensitively as globs (see ScrubEnv),
|
||||
// so "LC_*" covers the whole locale family. This is a safety net so that a
|
||||
// profile opting into a broad deny glob (e.g. "*_TOKEN") cannot break process
|
||||
// startup. The built-in DANGEROUS_ENV_VARS list never touches these names.
|
||||
var ProtectedEnvVars = []string{
|
||||
"PATH",
|
||||
"HOME",
|
||||
"USER",
|
||||
"LOGNAME",
|
||||
"SHELL",
|
||||
"PWD",
|
||||
"OLDPWD",
|
||||
"TERM",
|
||||
"TMPDIR",
|
||||
"TEMP",
|
||||
"TMP",
|
||||
"LANG",
|
||||
"LC_*",
|
||||
"TZ",
|
||||
"DISPLAY",
|
||||
"HOSTNAME",
|
||||
"NODE_ENV",
|
||||
}
|
||||
|
||||
// MandatoryDenyOptions configures GetMandatoryDenyPatterns. AllowRead and
|
||||
// AllowWrite must be already expanded (post-ExpandVariables); the function
|
||||
// does not call ExpandVariables itself.
|
||||
|
||||
Reference in New Issue
Block a user