fix(scripts): broaden support bundle secret-key redaction denylist#4242
Open
DaoyuanLi2816 wants to merge 1 commit into
Open
fix(scripts): broaden support bundle secret-key redaction denylist#4242DaoyuanLi2816 wants to merge 1 commit into
DaoyuanLi2816 wants to merge 1 commit into
Conversation
SECRET_KEY_RE only matched a fixed keyword allowlist, so a secret stored under an unanticipated key name inside an open-ended config dict (e.g. guardrails.provider.config, an arbitrary provider-kwargs dict) was emitted verbatim into config-summary.json even though manifest.json claims redacted_secret_fields=true. This gap was flagged on PR bytedance#3886's review before merge but not fully addressed. Broaden the key-name match to mirror env_policy.py's wildcard denylist (*KEY*/*SECRET*/*TOKEN*/*PASS*/*CREDENTIAL*/*DSN*) already used for sandbox env-scrubbing, plus its no-flag credential exact names (GH_PAT/GITHUB_PAT/ REDIS_AUTH/REDISCLI_AUTH/PGSERVICEFILE). The new bare key/pass/dsn alternatives are boundary-guarded so they match only their own delimited token, not an unrelated word that starts with the same letters (routing "keywords", guardrails "passport").
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/support_bundle.pyredacts secret-shaped config keys off a fixed keyword allowlist when walking arbitrary config dicts. This PR broadens that key-name match to mirror the wildcard denylistbackend/packages/harness/deerflow/sandbox/env_policy.pyalready uses for sandbox env-scrubbing, closing a gap that was flagged on PR #3886's review before merge but not fully addressed.Background
PR #3886 (which added the support-bundle generator) received a review from @willem-bd flagging this exact class of gap before merge: #3886 (review)
The PR merged with that review comment unresolved (
COMMENTED, notCHANGES_REQUESTED). The currentmaindoes already blanket-redact MCPenvblocks and*header*dicts by default (covering the concrete example the review used, MCP servers'envblock), but the underlying generic key-name allowlist that gates every other structured config path was never broadened to match.The gap
GuardrailProviderConfig.config(backend/packages/harness/deerflow/config/guardrails_config.py) is a real, documented, open-endeddictof provider-specific kwargs — not anenvor*header*block, so it never gets the blanket treatment. A custom guardrail provider configured with keys likedb_pass,encryption_key,redis_pass, orwebhook_signing_keyhas those values emitted verbatim intoconfig-summary.json, whilemanifest.jsonin the same bundle declares"redacted_secret_fields": true.I confirmed this against the real, unmodified
create_support_bundle()(before writing any fix): aconfig.yamlwith aguardrails.provider.configblock containing those four keys produced aconfig-summary.jsonwith every value present verbatim, whilemanifest.json's privacy block still claimed redaction.The fix
Broaden
SECRET_KEY_REinscripts/support_bundle.pyto add the same wildcard conceptsenv_policy.pyuses for sandbox env-scrubbing —*KEY*/*SECRET*/*TOKEN*/*PASS*/*CREDENTIAL*/*DSN*— plus a small exact-name set mirroring its no-flag credential sources (GH_PAT/GITHUB_PAT/REDIS_AUTH/REDISCLI_AUTH/PGSERVICEFILE).Direct import from the harness package wasn't used:
scripts/is a standalone, dependency-light root tool (it already runs withPyYAMLoptional and has nodeerflow/appimports anywhere in the directory), so growing a runtime dependency on the harness package being installed just to reuse one denylist didn't seem worth it. The breadth is mirrored independently instead.The new bare
key/pass/dsnalternatives are boundary-guarded ((?<![a-zA-Z])key(?![a-zA-Z]), same shape forpass/dsn) so they match only their own delimited token, not an unrelated word that happens to start with the same letters. Two real, non-secret fields in this repo's own schema would otherwise have regressed:extensions_config.json's MCProuting.keywordshint list (a real field inextensions_config.example.json)config.yaml'sguardrails.passportpath/ID fieldBoth are covered by a new regression test and continue to render unredacted after this change.
Connection-string keys (
DATABASE_URL,REDIS_URL, ...) are deliberately left out of the new exact-name set: their embedded credentials are already stripped in place by the existingURL_USERINFO_REpass, which is more useful for a support bundle than blanking the whole field (it keeps host/port/db-name visible for diagnosis, already covered by an existing test). Adding them to a blanket-redact set would have regressed that existing, tested behavior.Tests
test_redact_data_masks_secret_shaped_keys_in_arbitrary_provider_config— theguardrails.provider.configscenario above, including aSUPABASE_SERVICE_ROLE_KEY-shaped key (the concrete example from the feat(scripts): add redacted community support bundle generator #3886 review) and agh_pat-shaped key, both outside anyenv/headerwrapper.test_redact_data_does_not_over_redact_lookalike_non_secret_keys— assertsrouting.keywordsandguardrails.passportstill render unredacted.test_create_support_bundle_masks_provider_config_secret_shaped_keys— end-to-end through the realcreate_support_bundle()zip output, also checks themanifest.jsonprivacy claim.scripts/support_bundle.pyviagit apply -Ron a saved patch (tests untouched) makes the 2 new leak tests fail with the literal secret values present instead of<redacted>; reapplying the patch makes all tests pass again.tests/test_support_bundle.pyfull file: 29 passed (27 pre-existing + 2 new leak tests; the 3rd new test, the over-redaction guard, already passed before this fix since nothing over-redacted yet).tests/backend suite — 57 failed, 7534 passed, 52 skipped. All 57 failures are pre-existing and unrelated to this change (Windows-only symlink-privilege, hostPath-volume, macOS-specific, and POSIX file-permission tests failing on a Windows dev machine, in files this change never touches) — none referencesupport_bundle.ruff checkandruff format --check(line length 240) are clean on both changed files.