Skip to content

autoreview: secret-scanner false positives on identifier and member-expression values (e.g. apiSecret: ctx.cloudinary.apiSecret) #91

Description

@jrans

Summary

secret_text_risk in skills/autoreview/scripts/autoreview (as of 8184e2b) refuses review bundles containing ordinary TypeScript code shapes that reference credentials rather than containing them. Because the refusal is a hard SystemExit with no allowlist or override, a single such line makes --mode branch unusable for the whole PR.

False-positive shapes

All of these are flagged by the assignment analyzer (SECRET_ASSIGNMENT_PATTERN + secret_text_risk):

// 1. Bare identifier value of 12+ characters (a reference, not a literal)
const signingPhrase = "test-signing-phrase"; // test fixture
signCloudinaryUploadParams({ apiSecret: signingPhrase, ... });

// 2. Member expression whose root is outside the hardcoded whitelist
return { apiKey: ctx.cloudinary.apiKey, ... };          // `ctx` not in UNQUOTED_SECRET_REFERENCE_PATTERNS
cloudinary: { apiSecret: environment.cloudinaryApiSecret } // `environment` not whitelisted (though `env` is)

Meanwhile apiKey: env.CLOUDINARY_API_KEY passes, since env is in the whitelist — the same code with a context object named ctx or environment is refused.

Why these can't leak secrets

  • A pure identifier ([A-Za-z_$][A-Za-z0-9_$]*) is a reference; the current rule already accepts identifiers under 12 characters, so the length cutoff only penalizes descriptive names (signingPhrase, sessionToken) without excluding any literal secret material — literals with only identifier characters and no digits/symbols at 12+ chars are overwhelmingly variable names in practice.
  • A dotted member expression (a.b.c) likewise cannot be a secret; the root-whitelist approach means any codebase whose config/context object isn't named one of the ~20 blessed roots gets refused.

Suggestions (either would fix our case)

  1. Treat any pure identifier or member expression ([A-Za-z_$][A-Za-z0-9_$]*(\.[A-Za-z_$][A-Za-z0-9_$]*)*) as a safe reference in the assignment analyzer, regardless of length — keeping the existing checks for quoted strings, URI credentials, and the concrete token-format patterns.
  2. Or: provide an escape hatch (repo-level config or CLI flag) so branch review can proceed with flagged lines redacted from the bundle instead of refusing outright.

Context

Hit in CI on a PR adding Cloudinary upload signing — refusing to include secret-like content in review bundle; clean or redact branch diff before running autoreview with ~30 flagged lines, all of the shapes above. We worked around it by destructuring to shorthand properties and shortening a fixture name under 12 characters, but that's regex-appeasement rather than a sustainable pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:securityThis issue is about security boundaries, credentials, authz, sandboxing, or sensitive data.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions