{"record":{"id":"d0f1b68d13a3432b","repo":"Hmbown/CodeWhale","slug":"portable-export-refused-credential-bearing-config-paths","errorCode":null,"errorMessage":"portable export refused credential-bearing config paths: {}","messagePattern":"portable export refused credential-bearing config paths: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/cli/src/config_bundles.rs","lineNumber":905,"sourceCode":"                }\n                ExportSection::Drop => {}\n            }\n        }\n    }\n\n    let bundle = PortableBundle {\n        schema_version: BUNDLE_SCHEMA_VERSION,\n        kind: BUNDLE_KIND.to_string(),\n        metadata,\n        preferences,\n        profiles,\n        plugins: BundleTable::default(),\n        project,\n        global,\n    };\n    let rejected = find_rejected_entries(&bundle);\n    if !rejected.is_empty() {\n        bail!(\n            \"portable export refused credential-bearing config paths: {}\",\n            rejected\n                .iter()\n                .map(|entry| entry.key.as_str())\n                .collect::<Vec<_>>()\n                .join(\", \")\n        );\n    }\n    Ok(bundle)\n}\n\n/// Serialize a bundle deterministically (sorted keys, TOML).\npub fn serialize_bundle(bundle: &PortableBundle) -> Result<String> {\n    toml::to_string_pretty(bundle).context(\"serializing portable bundle\")\n}\n\n/// Config keys that name a machine-local location and must never be exported.\nconst MACHINE_SPECIFIC_KEYS: [&str; 14] = [","sourceCodeStart":887,"sourceCodeEnd":923,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/config_bundles.rs#L887-L923","documentation":"export_bundle refuses to produce a portable bundle when find_rejected_entries detects credential-bearing config paths (API keys, tokens, secrets) in the current configuration. Portable bundles are meant to be shared, so secret-shaped entries are stripped out of the allowed schema and their presence blocks the export, listing the offending keys.","triggerScenarios":"Running the bundle export command (run_export) while the live config contains secret-shaped values — e.g. an API key stored under a provider entry, or leftover redaction placeholders — that find_rejected_entries flags.","commonSituations":"A user stored an API key directly in config.toml and now tries to share the bundle; exporting after importing a bundle that itself carried credentials; CI configs with tokens inline in provider settings.","solutions":["Move the listed credentials out of the config paths named in the error (e.g. use environment variables or a secret store) and re-export.","Remove the credential-shaped entries entirely if they are not needed on the target machine.","Check which keys are flagged: the error lists them comma-separated; edit config.toml to clear or restructure them.","Re-export and inspect the bundle for the sensitive keys before sharing."],"exampleFix":"// before (config.toml)\n[providers.openai]\napi_key = \"sk-...\"\n// after\n[providers.openai]\n# api_key read from CODEWHALE_OPENAI_API_KEY env var; not stored in config\nexport -> succeeds","handlingStrategy":"validation","validationCode":"// Before exporting, scan your config for secret-shaped values:\n// grep -nEi '(api[_-]?key|token|secret|password)[[:space:]]*=' ~/.config/codewhale/config.toml\n// Move any hits to environment variables or a secret store.","typeGuard":null,"tryCatchPattern":"match export_bundle(&store, &target) {\n    Ok(receipt) => println!(\"exported {}\", receipt.path),\n    Err(e) if e.to_string().contains(\"credential-bearing config paths\") => {\n        eprintln!(\"remove the listed keys from config, then re-export: {e:#}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep API keys in environment variables, never in config.toml.","Run a pre-export grep for key/token/secret patterns in config.","After any manual config edit, re-export and inspect the bundle before sharing."],"tags":["security","secrets","export","config-bundles"],"backgroundTag":"missing-credentials","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}