Skip to content
Benchmarks

EVALUATION METHOD

Metamorphic

A transform changes the context around a value (a prefix, indentation, line endings, a JSON, YAML, Markdown or quoted wrapper) and nothing else. The scanner should detect the same thing as it did on the original text.

  • Run 6183a594 · 2026-10-10
  • redact-secret 0.1.0-beta.14 · Published npm package · default detectors
  • Accounting v1.1

1 · How it runs

Does a scanner find the same thing when only the surrounding text changes?

  1. InputA source case, read once as authored and once per transform.
  2. ChangeA context or encoding operator wraps or re-encodes the text. The value is not changed.
  3. CheckThe detection after the transform equals the detection before it (same-detection). The transformed text is also read on its own.
Source cases
4,913
Transformed texts
17,237
Operators
8

2 · Recorded now

Does detection survive a change of context?

One row per transform, then the transformed text read on its own.
Metamorphic: checks that did not hold, per scanner
Transformredact-secret0.1.0-beta.14gitleaks8.30.1trufflehog3.97.4flare-redact1.6.1
Same detection after the transform
context.unicode-prefixPuts a line of non-ASCII text before the value16 of 4,885993 of 4,8851,708 of 4,8851,978 of 4,885
context.indentIndents the text by four spaces16 of 4,885993 of 4,8851,708 of 4,8851,978 of 4,885
encoding.crlfChanges line endings to CRLF10 of 4,041783 of 4,0411,462 of 4,0411,714 of 4,041
context.jsonWraps the value as a JSON string3 of 660113 of 660127 of 660138 of 660
context.quoteWraps the value in double quotes3 of 660113 of 660127 of 660138 of 660
context.single-quoteWraps the value in single quotes3 of 666113 of 666133 of 666144 of 666
context.yamlWraps the value as a YAML scalar3 of 666113 of 666133 of 666144 of 666
context.markdownWraps the value in inline code3 of 663113 of 663130 of 663141 of 663
The transformed text on its own
Value detectedA value that should be detected is, within its expected envelope42 of 8,4053,112 of 8,4055,419 of 8,4056,161 of 8,405
Look-alike left aloneA text that should not be flagged is not15 of 8,721222 of 8,721108 of 8,721214 of 8,721

Transformed texts where the check did not hold, of those scored for that scanner.

A count opens the checks behind it: the ones that did not hold, from this run only. "Needs review" opens the checks that wait for a person. A zero has none to open, and a scanner that did not run has none to list.

Needs review

28 source cases have a side whose expected outcome is unresolved (tier T0). They are counted in no row above.

3 · How to read it

Reading metamorphic

  • A scanner that missed the value on both sides holds the relation, so the second group reads the transformed text on its own. Together they tell the two cases apart.
  • A source with an unresolved expectation (tier T0) is counted apart and in none of these rows.

4 · Exact inputs

Where the cases come from

4,913 source cases read by this method. Synthetic content only.

Suites

Every case comes from a published suite. Open a suite to read its fixtures.

Show the 75 suites
Suites the cases come from
SuiteSource cases
Reviewed credential formatscommon-formats58
Detection accuracyaccuracy10
GitHub token contextstoken-contexts6
Credential formatscredential-formats27
Context & boundariescontext-edges116
Negative controlsnegative-controls24
SendGrid regressionssendgrid-regressions38
Reference syntaxreference-syntax26
Beta.3 regressionsmilestone-6-closed92
Detector coveragedetector-coverage1,182
Untargeted real-world shapesreal-world-shapes120
Beta.8 low-coverage hardening (#207)beta8-207249
Beta.8 documented-stable hardening (#209)beta8-20948
Beta.8 AI inference arrival evidence (#208)beta8-20872
Beta.8 · LangSmith and Langfuse arrival evidencebeta8-21038
Beta.8 developer credential arrival evidence (#211)beta8-211104
Beta.8 second-wave arrival evidence (#212)beta8-212132
Beta.8 legacy-stable profile restoration (#213, set a)beta8-213a33
Beta.8 stable restoration evidence (#213, 213c)beta8-213c98
Beta.8 documented-stable restoration, batch b (#213)beta8-213b59
Beta.8 empirical-route fixture debt (#213, 213d)beta8-213d140
Beta.8 context-twin debt for the legacy Datadog application key (#213, 213e)beta8-213e4
Beta.8 replacement fixtures for provider-undecided properties (#213, 213f)beta8-213f7
Beta.8 evidence for Travis CI, Neon, Postman collection access keys and the Mailgun key triplet (#259)beta8-25993
Beta.8 empirical fixture-floor raise for ten T2 families (#263)beta8-26373
Beta.10 evidence for the Anthropic api01/admin01 prefixes and the OpenAI admin key (#384, slice a)beta8-384a62
Beta.10 evidence for the Amazon Bedrock long-term and short-term API keys (#384, slice b)beta8-384b41
Beta.10 evidence for the ElevenLabs API key (#384, slice c)beta8-384c20
Beta.10 evidence for the Together AI and Tavily API keys (#384, slice d)beta8-384d58
Beta.10 evidence for keyword-gated Mistral, Cohere, Deepgram, AI21 and Exa keys (#384, slice e)beta8-384e185
Beta.11 independent family evidence for fifteen selected credential families (#379)beta8-379164
Beta.11 evidence for Convex deployment and admin keys with a hex body (#436, slice a)beta8-436a23
Beta.11 evidence for the 1Password service-account token (#436, slice b)beta8-436b22
Beta.11 evidence for the Inngest signing key (#436, slice c)beta8-436c23
Beta.11 evidence for the Resend API key (#436, slice d)beta8-436d23
Beta.11 evidence for the Apify API token (#436, slice e)beta8-436e23
Beta.11 evidence for the Weights & Biases wandb_v1_ API key (#436, slice f)beta8-436f21
Beta.11 evidence for Doppler tokens (#434, slice a)beta8-434a172
Beta.11 evidence for the Trigger.dev secret key and PAT (#434, slice b)beta8-434b46
Beta.11 evidence for the E2B API key (#434, slice c)beta8-434c24
Beta.11 evidence for the PostHog personal and project secret API keys (#434, slice d)beta8-434d50
Beta.11 evidence for the Helicone read-write and write-only keys (#434, slice e)beta8-434e45
Beta.11 evidence for the Firecrawl API key (#434, slice f)beta8-434f26
Beta.11 evidence for the Composio project, org and user API keys (#434, slice g)beta8-434g78
Beta.11 replacement near-miss controls for the redact-secret#948 relabel (948)beta8-9489
Beta.12 evidence for the Daytona API key (#464, slice a)beta8-464a28
Beta.12 evidence for the ClickHouse Cloud API key secret (#464, slice b)beta8-464b27
Beta.12 evidence for the NVIDIA API key (#464, slice c)beta8-464c25
Beta.12 evidence for the Browserbase API key (bb_live_) (#464, slice d)beta8-464d24
Beta.12 evidence for the Cerebras inference API key (#464, slice e)beta8-464e32
Beta.12 evidence for the RunPod API key (#464, slice f)beta8-464f23
Beta.12 evidence for the Bitwarden Secrets Manager access token (#528, slice a)beta8-528a24
Beta.12 evidence for Polar organization access tokens and API credentials (#528, slice b)beta8-528b44
Beta.12 evidence for SonarQube user and analysis tokens (#528, slice c)beta8-528c44
Beta.12 evidence for the RubyGems.org API key (#528, slice d)beta8-528d22
Beta.12 evidence for the Clojars deploy token (#528, slice e)beta8-528e21
Beta.12 evidence for crates.io API and trusted-publishing tokens (#528, slice f)beta8-528f43
Beta.12 evidence for Dynatrace access and platform tokens (#528, slice g)beta8-528g22
Beta.12 evidence for the Paddle Billing API key (#528, slice h)beta8-528h21
Beta.12 evidence for Honeycomb ingest keys (#528, slice i)beta8-528i22
Beta.12 evidence for Axiom API and personal tokens (#528, slice j)beta8-528j40
Beta.12 evidence for the AWS IAM user secret access key (#528, #1012 slice a)beta8-1012a34
Beta.12 evidence for the Google OAuth client secret (#528, #1012 slice b)beta8-1012b24
Beta.12 evidence for the routable GitLab personal access token (#528, #1012 slice c)beta8-1012c23
Beta.12 evidence for the AWS STS temporary access key id (#528, #1012 slice d)beta8-1012d23
Beta.12 evidence for Vercel personal, app access and app refresh tokens (#528, #1012 slice e)beta8-1012e96
Beta.14 evidence for the Square access token and OAuth application secret (#583, slice a)beta8-583a50
Beta.14 evidence for the Xata API key (#583, slice b)beta8-583b33
Beta.14 evidence for the Sourcegraph access token (#583, slice c)beta8-583c25
Beta.14 evidence for the Unkey root key (#583, slice d)beta8-583d31
Beta.14 evidence for the Buildkite token (#583, slice e)beta8-583e44
Beta.14 evidence for the Pydantic Logfire token (#583, slice f)beta8-583f30
Beta.14 evidence for the Mapbox secret access token (#583, slice g)beta8-583g27
Beta.14 evidence for the Fly.io access token (#583, slice h)beta8-583h32
Public policy qualification controls for bounded T3 credentials (#365)policy-qualified-credentials15

Operators

Generated counts exclude the unaltered source. Not applicable means the operator could not be applied to that source.

Operators and what they generated
OperatorWhat it changesGeneratedNot applicable
context.unicode-prefixPuts a line of non-ASCII text before the value4,9130
context.indentIndents the text by four spaces4,9130
encoding.crlfChanges line endings to CRLF4,051862
context.jsonWraps the value as a JSON string6694,244
context.quoteWraps the value in double quotes6694,244
context.single-quoteWraps the value in single quotes6754,238
context.yamlWraps the value as a YAML scalar6754,238
context.markdownWraps the value in inline code6724,241