{"record":{"id":"c81cf82cc6836974","repo":"JuliusBrussee/caveman","slug":"cave-sandbox-credential-env-not-allowlisted","errorCode":"cave_sandbox_credential_env_not_allowlisted","errorMessage":"cave_sandbox_credential_env_not_allowlisted","messagePattern":"cave_sandbox_credential_env_not_allowlisted","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":601,"sourceCode":"  \"PATH\",\n  \"PWD\",\n  \"SHELL\",\n  \"DYLD_INSERT_LIBRARIES\",\n]);\n\nexport function validateSandboxCredentialEnv(names: readonly string[]): void {\n  const capabilities = new Set<SandboxCredentialCapability>();\n  for (const name of names) {\n    const denied = typeof name === \"string\" &&\n      (SANDBOX_CREDENTIAL_DENY_NAMES.has(name) ||\n        SANDBOX_CREDENTIAL_DENY_PREFIXES.some((prefix) => name.startsWith(prefix)));\n    const capability = denied || typeof name !== \"string\"\n      ? undefined\n      : SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY.get(name);\n    if (capability === undefined) {\n      // Keep profile-controlled names out of errors. This is a policy result,\n      // not a diagnostic surface, and the name may itself identify a secret.\n      throw new Error(\"cave_sandbox_credential_env_not_allowlisted\");\n    }\n    capabilities.add(capability);\n  }\n  if (capabilities.size > 1) {\n    throw new Error(\"cave_sandbox_credential_capability_ambiguous\");\n  }\n}\n\n/** Build the complete environment for an isolated tool child. No spread of\n * `process.env`: only deterministic runtime baseline plus an exact provider\n * capability selected by the validated live profile. */\nexport function buildSandboxToolEnv(names: readonly string[] = []): NodeJS.ProcessEnv {\n  validateSandboxCredentialEnv(names);\n  const env: NodeJS.ProcessEnv = {\n    LANG: process.env.LANG ?? \"C\",\n    LC_ALL: process.env.LC_ALL ?? \"C\",\n    PATH: process.env.PATH ?? \"\",\n    TZ: process.env.TZ ?? \"UTC\",","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/runtime.ts#L583-L619","documentation":"validateSandboxCredentialEnv rejects any environment variable name requested for sandbox credential injection that is not on the sandbox credential allowlist (SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY). The name is deliberately omitted from the error to avoid leaking secret-identifying names.","triggerScenarios":"A sandbox/eval profile (loadEvalSandboxProfile) or buildSandboxToolEnv requests a credential env var name not present in SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY; a typo'd or profile-controlled name is passed to the credential-env validation.","commonSituations":"Typo in an env var name in a sandbox profile config; renaming a provider credential env var after a library update; custom profiles referencing vendor-specific secret names that are not allowlisted.","solutions":["Use only allowlisted sandbox credential env names (e.g. standard provider API key vars).","Fix typos in the profile's credential env names.","Check library docs/changelog for the current set of supported credential env vars.","Extend via the library's official mechanism if a new credential must be supported, not by bypassing validation."],"exampleFix":"// before\nprofile.credentialEnv = [\"MY_OPENAI_KEY\"];\n// after\nprofile.credentialEnv = [\"OPENAI_API_KEY\"]; // allowlisted name","handlingStrategy":"validation","validationCode":"const ALLOWED = [...SANDBOX_CREDENTIAL_ENV_ALLOWLIST];\nconst bad = profile.credentialEnv.filter((n: string) => !ALLOWED.includes(n));\nif (bad.length) console.error(\"not allowlisted:\", bad); // before loading profile","typeGuard":"const isAllowlistedCredentialEnv =\n  (name: string): boolean => SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY.has(name);","tryCatchPattern":"try {\n  const profile = loadEvalSandboxProfile(p);\n} catch (e) {\n  if (e.message === \"cave_sandbox_credential_env_not_allowlisted\") {\n    console.error(\"Profile uses a non-allowlisted credential env name (name withheld by design)\");\n  } else throw e;\n}","preventionTips":["Use only documented, allowlisted credential env names in profiles.","Lint/sanitize profile credential lists against the allowlist at config load time.","Re-validate profiles after upgrading the library (allowlist may change)."],"tags":["sandbox","env","security","allowlist"],"backgroundTag":"missing-env-var","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}