Skip to content

Stop the ak-/as- key pattern matching kebab-case English - #823

Closed
aviggiano wants to merge 1 commit into
mainfrom
fix/ak-as-vendor-pattern-matches-kebab-case-prose
Closed

aviggiano wants to merge 1 commit into
mainfrom
fix/ak-as-vendor-pattern-matches-kebab-case-prose

Conversation

@aviggiano

@aviggiano aviggiano commented Aug 24, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #822.

Change

- /\b(?:ak|as)-[A-Za-z0-9_-]{16,}\b/gu,
+ /\b(?:ak|as)-[A-Za-z0-9_]{16,}\b/gu,

One character. The suffix class permitted -, so the pattern matched any hyphenated prose containing the fragment as- or ak- followed by 16+ characters.

Why it matters more than it looks

This is a vendor pattern, not one of the speculative heuristics from #819, so it fires even under a "positive-only" publication scan. And the failure it causes is quiet.

In a real campaign it killed verify:goal-plan. That node is continueOnFail, so the run did not stop — it carried on and kept reporting healthy node counts. But two dynamic groups are sourced from that verifier:

class-goals  <- verify:goal-plan
threat-goals <- verify:goal-plan

Neither can expand once it has failed. The goal-directed portion of the audit was silently skipped while the run continued toward a "successful" finish. Nothing in the progress output indicates the loss.

Verification

Prose that must publish (all three fail on main, all clean after):

  • policy.record-treated-as-private-to-the-service
  • classified-as-internal-only-configuration-value
  • resources-marked-ak-restricted-to-the-owner-role

Opaque tokens that must stay detected (all still detected):

  • ak-AbCdEf1234567890XyZwVuTs
  • as-9f2b7c1d4e6a8b0c3d5e7f90
  • ak-AbCdEf_1234567890_XyZwVu — underscores still allowed

The existing modal ak-… / modal as-… fixtures are unaffected, since neither contains a hyphen in the suffix. A regression test covers both directions.

snake_case prose (treated_as_private_to_the_protocol_value) never matched and still doesn't — _ is a word character, so the leading \b cannot fire. Only the hyphenated form was affected.

19/19 security tests; lint and format:check clean.

Note on the artifacts suite

a runtime document read rejects an atomic path replacement during its snapshot fails on this branch, as it does on main — it is a pre-existing ~50% flaky test, unrelated to this change. #820 fixes it (it turns out to be a real TOCTOU gap, not a slow test). Independent of this PR.

Greptile Summary

This PR narrows the Modal-style ak-/as- credential pattern so kebab-case prose no longer triggers secret detection while documented opaque token forms remain protected.

  • Removes hyphens from the credential suffix character class.
  • Adds regression coverage for false-positive prose, redaction behavior, and supported tokens containing alphanumerics or underscores.

Confidence Score: 5/5

The PR appears safe to merge, with focused tests covering both the corrected false-positive behavior and retained credential detection.

The narrower character class matches the established ak-/as- token forms while preventing long hyphenated prose from being rejected as secret-bearing output, and no supported credential form was found to regress.

Important Files Changed

Filename Overview
packages/security/src/sensitive-redaction.ts Narrows the ak-/as- suffix pattern to avoid matching kebab-case prose without excluding any established valid credential format.
packages/security/test/sensitive-redaction.test.ts Adds focused bidirectional regression tests for prose false positives and supported opaque credential forms.

Reviews (1): Last reviewed commit: "fix(security): stop the ak-/as- key patt..." | Re-trigger Greptile

Closes #822.

The suffix class permitted '-', so the pattern matched any hyphenated prose
containing the fragment 'as-' or 'ak-' followed by 16 or more characters --
'record-treated-as-private-to-the-service', 'classified-as-internal-only-...'.
Agent-generated goal identifiers are exactly that shape.

This is a vendor pattern rather than one of the speculative heuristics, so it
fires even under a positive-only publication scan, and it fails artifact
publication on clean output. The failure is quiet: the node it killed in a real
campaign is continueOnFail, so the run continued and reported healthy progress
while both dynamic groups sourced from that verifier -- class-goals and
threat-goals -- could no longer expand. The goal-directed portion of the audit
was skipped and the run still finished.

Credentials in this family are opaque tokens and carry no hyphens, so dropping
'-' from the suffix separates them cleanly. Verified: three prose shapes become
clean, and ak-AbCdEf1234567890XyZwVuTs, as-9f2b7c1d4e6a8b0c3d5e7f90 and
ak-AbCdEf_1234567890_XyZwVu are all still detected. snake_case prose never
matched -- '_' is a word character, so the leading \b cannot fire.

19/19 security tests pass.

@aviggiano aviggiano left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sensitive redaction is giving us too much headache, we want preferably to use a 3rd party library instead of reinventing the wheel

aviggiano added a commit that referenced this pull request Aug 25, 2026
…tlint (#865)

Maintainer instruction from the review comments on #820 ("We want to avoid
manually scanning secrets, we should use a third party library") and #823
("This sensitive redaction is giving us too much headache, we want preferably
to use a 3rd party library instead of reinventing the wheel"). This PR
supersedes both.

Root cause across #819 and #822: a hand-rolled pattern set has to be
recalibrated shape by shape every time credential text collides with ordinary
technical prose, and each recalibration (entropy exemptions, Bearer token
shape, the ak-/as- suffix class) only unblocked one run before the next prose
shape failed the fail-closed publication gate.

Detection now has three tiers:

- Exact configured credential values stay matched byte-for-byte; the library
  cannot know the run's configuration, so that tier remains app knowledge.
- Vendor-format detection is delegated to secretlint 13.0.4 (@secretlint/core
  plus @secretlint/secretlint-rule-preset-recommend, MIT, pure JS), run fully
  in-process on a dedicated worker thread behind a synchronous shared-memory
  bridge so every existing sync caller, including the generated Smithers
  verifier, keeps its API. A documented supplemental pattern remains only for
  each concrete true positive the preset cannot see (short/truncated PEM
  blocks, non-canonical sk-ant-/sk- prefixes, AKIA/ASIA IDs, AIza keys, Modal
  ak-/as- keys with the #822 hyphen fix, ya29 tokens, JWTs, Alchemy/Infura
  URLs, Bearer tokens with the #820 token-shape fix), plus the BIP39 mnemonic
  and context-labeled private-key checks, which no secretlint rule covers.
- The speculative heuristics (high entropy, unlabeled 40-hex, key-name
  assignment) are retired from the publication gate, which now scans
  positive-only; they remain for default display-redaction callers, where
  over-redaction is cheap.

The preset's filter-comments rule is excluded: scanned content is
agent-controlled, and in-content secretlint-disable comments must not be able
to suppress the gate's findings (covered by a regression test).

The gate keeps failing closed: a hit still rejects publication without
rewriting bytes, exact values plus every positively identified format from
the #819/#820/#822/#823 examples are still rejected (asserted one by one in
the artifacts suite), and the five prose shapes that each killed a campaign
run are asserted publishable.

Closes #819
Closes #822

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@aviggiano

Copy link
Copy Markdown
Collaborator Author

Superseded by #865: the ak-/as- vendor pattern (including this PR's no-hyphen suffix fix) now lives as a documented supplemental pattern alongside secretlint 13.0.4, with the kebab-case-prose regression ported as a test.

@aviggiano aviggiano closed this Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ak-/as- vendor pattern matches kebab-case English, silently skipping goal-directed audit lanes

1 participant