Which secrets a CLI worker sees — generic secret strip and passthrough (kznbp)
T603 and k8rhz scoped provider credentials only, so every other secret in the launching shell reached an auto-approve CLI worker: GITHUBTOKEN, NPMTOKEN, AWSSECRETACCESSKEY, DATABASEURL,...
T603 and k8rhz scoped provider credentials only, so every other secret in the launching shell reached an auto-approve CLI worker: GITHUB_TOKEN, NPM_TOKEN, AWS_SECRET_ACCESS_KEY, DATABASE_URL, STRIPE_SECRET_KEY and the like, and aider / crush / qwen / goose:litellm / an unknown opencode prefix got the whole environment. T603's narrower scope was a task-level choice, not an operator ruling. buildScopedChildEnv() (src/adapters/CliAgentAdapter.ts) now applies two more rules to every spawned CLI worker:
- Generic secrets are stripped. Any name ending in
_TOKEN,_SECRET,_SECRET_KEY,_SECRET_ACCESS_KEY,_PASSWORD,_PASSWD,_DSNorDATABASE_URL(case-insensitive,isWorkerSecretEnvKey) is removed, except a short keep-list: Cyberine's own callback tokens for every worker (CYBERINE_MCP_AUTH_TOKENfor a worker that calls back intocyberine mcp,CYBERINE_BUS_HUB_TOKENandCYBERINE_API_TOKENfor a team worker's bus client and a remotecyberinecall),ANTHROPIC_AUTH_TOKENfor aclaudeworker (its gateway bearer), andAWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN,BEDROCK_SECRET_ACCESS_KEY,BEDROCK_SESSION_TOKENfor a Bedrock-routed worker (claudewithCLAUDE_CODE_USE_BEDROCKset, abedrock/orbedrock_converse/model foraider/crush,amazon-bedrock/foropencode, provideraws_bedrockforgoose). Names that do not match the pattern are untouched, soSSH_AUTH_SOCK,HTTP_PROXY/HTTPS_PROXY/NO_PROXY(either case),AWS_PROFILE,AWS_ACCESS_KEY_ID,PATHandHOMEstill reach the worker. - A CLI with no allowlist gets only the provider key its model implies.
impliedProviderKeysForCli()reads the model string: a<provider>/<model>prefix through the same map asopencodeplusmoonshotanddashscope(aider:deepseek/deepseek-chatkeepsDEEPSEEK_API_KEYonly), a bare model name by family (gpt-*/o3→OPENAI_API_KEY,claude-*/sonnet→ANTHROPIC_API_KEY,gemini*→GEMINI_API_KEY,deepseek*→DEEPSEEK_API_KEY,grok*→XAI_API_KEY), andqwenkeeps its three overlapping keys (DASHSCOPE_API_KEY,BAILIAN_CODING_PLAN_API_KEY,OPENAI_API_KEY). When the model names nothing recognizable (aider:default,crush:default,goose:litellm, a customopencodegateway prefix) the worker keeps every*_API_KEY/*_TOKEN_KEY, because aider's and crush's default model picks itself from whichever key is present; it still loses every*_OAUTH_TOKENand every generic secret.
Run recipe: nothing to turn on, every spawn applies it. To hand a worker a secret it needs (a gh call inside the worker authenticated by GH_TOKEN, a custom opencode gateway whose key is MYGATEWAY_TOKEN), list the names in the shell or in ~/.cyberine/.env:
export CYBERINE_WORKER_ENV_PASSTHROUGH="GH_TOKEN,MYGATEWAY_TOKEN"
cyberine run "fix the failing release script"Names are separated by commas or whitespace and must match exactly. The list is read once, when Cyberine loads its config, before the current directory's .env is loaded, so a cloned repo's .env cannot widen it; it is not a config.json key either. It widens only the generic-secret rule: a provider key off the worker's allowlist and every *_OAUTH_TOKEN stay stripped even when listed, so the seat scoping above is unchanged.
The scoping is covered with no network call and no spawn by:
npm run selftest:config-perms-env-scoping
npm run selftest:claude-oauth-token-scopingKnown Limitations and Deferred Work. This is still a denylist with a keep-list, not a strict allowlist: a secret whose name matches none of the suffixes (MY_API_CREDS, a URL with a password in it such as REDIS_URL) still reaches the worker; a strict allowlist was rejected for now because it breaks Bedrock, MCP callbacks, git / gh / ssh-agent and proxies. Bedrock routing for claude is read from CLAUDE_CODE_USE_BEDROCK in the environment Cyberine builds, so a Bedrock switch set only in ~/.claude/settings.json is not seen and the AWS secrets are stripped; add them to CYBERINE_WORKER_ENV_PASSTHROUGH in that setup. A worker that uses gh, npm publish or a database through an env token now fails until the name is passed through; one stored in a keychain or a config file (gh auth login, ~/.npmrc, ~/.aws/credentials) is unaffected by env scoping, and the host sandbox's read deny-list is what guards those files. The bare-model family map is a heuristic: a model it does not know falls back to keeping every provider key. The in-process BedrockAdapter reads process.env directly and is not a spawned worker, so none of this applies to it.
Which Claude account a worker bills — oauthToken (k8rhz)
CLAUDECODEOAUTHTOKEN is a long-lived subscription credential that decides WHICH SEAT a claude worker bills. It used to reach every spawned worker by plain inheritance: T603's least-privilege env
Claude session names — cy-<action>-<run8>-<session8>[-<seat>]
Every claude session Cyberine spawns registers under a name that starts with cy-, so claude agents, ListAgents and ~/.claude/sessions/<pid>.json tell a Cyberine child apart from the operator's own...