redact-secret · Report
Webhook signing secret
Webhook endpoint signing secret, prefixed whsec_.
Research record
3 events in the review history: 2 observed, 1 reviewed. Latest: observed on 2026-09-27 by automation, project maintainer. Project-maintained review is not independent validation. The family record at this release.
Format
What it looks like
- Descriptive pattern
^whsec_[A-Za-z0-9+/]{32,}={0,2}$
Parts are shown as recorded. Evidence classes belong to the facts below; no class is assigned to a part.
Format facts
Provider documented ·
provider-source· current · observed 2026-09-24whsec_ webhook endpoint signing secret: the whsec_ prefix and the per-endpoint configuration context; no body length or alphabet
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports the whsec_ prefix and the per-endpoint configuration context; no body length or alphabet
Provider documented ·
field-prefix· current · observed 2026-09-24prefix: Webhook signing secrets begin with the literal whsec_ (Dashboard, API and CLI; snapshot and thin destinations alike).
- docs.stripe.com/webhooks/signatureprovider-documentation · last read 2026-09-27 · latest outcome read · supports Dashboard and CLI secrets both start with whsec_ but differ.
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Dashboard "Reveal secret": a signing secret beginning with whsec_; v2 event destinations return a value that "starts with whsec_".
Provider documented ·
field-context· current · observed 2026-09-24context: The secret is configured per webhook endpoint (STRIPE_WEBHOOK_SECRET / endpoint_secret / signing_secret) and passed to the SDK signature verifier. (Context-gated: whsec_ is also issued by Svix/Standard Webhooks (base64, 24–64 bytes), so the prefix alone does not attribute a value to Stripe. Every positive carries a same-line Stripe context; non-Stripe whsec_ values are neither positives nor controls here (#224 left that contract decision open).)
- docs.stripe.com/keysprovider-documentation · last read 2026-10-04 · latest outcome read · supports "Webhook signing secrets aren't API keys—they're per-webhook secrets."
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Code samples read the endpoint secret into the constructEvent / construct_event verifier.
Provider documented ·
field-body-alphabet· current · observed 2026-09-24body-alphabet: The body may be alphanumeric or base64 with + / and = padding. (Stripe's own code disagrees with itself. Positives are alphanumeric (satisfying every candidate); the contract pattern admits + / = so no fixture asserts silence on them.)
- stripe/stripe-cli @ master: canary/testutil/sanitize.goprovider-sdk-source · last read 2026-09-24 · latest outcome read · supports The same repo's canary sanitizer uses whsec_[a-zA-Z0-9]{10,} (alphanumeric only).
- stripe/stripe-cli @ master: pkg/reporting/scrub.goprovider-sdk-source · last read 2026-09-24 · latest outcome read · supports Stripe CLI error-report scrubber \bwhsec_[a-zA-Z0-9+/]+=* ("base64 alphabet + optional = padding"); conservative scrubbing, not a generator statement.
Provider documented ·
field-body-length· current · observed 2026-09-24body-length: The body is at least 32 characters; 32 and 64 are the widths sources show. (Not exhaustive (#224): an example is not a grammar. The 32 floor only keeps short documentation placeholders out of the pattern; no twin mutates width, and no zero-filled 64-character placeholder is authored as a control because it would satisfy the pattern.)
- docs.stripe.com/api/webhook_endpoints/objectprovider-documentation · last read 2026-09-27 · latest outcome read · supports The API reference example secret has a 32-character mixed-case alphanumeric body. "Only returned at creation" via the API.
- stripe/stripe-node @ master: examples/webhook-signing/.env.exampleprovider-documentation · last read 2026-09-24 · latest outcome read · supports Provider-code placeholder whsec_ + 64 zeros.
- github.com/trufflesecurity/trufflehog/pull/4973provider-documentation · last read 2026-09-24 · latest outcome read · supports Unmerged: exact 32 or 64 alphanumeric.
- github.com/trufflesecurity/trufflehog/pull/4920provider-documentation · last read 2026-09-24 · latest outcome read · supports Unmerged: 32–64 of [A-Za-z0-9+/].
Provider documented ·
field-mode-marker· current · observed 2026-09-24mode-marker: No live/test marker in the value.
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Test and live endpoints have different secrets; the prefix carries no mode segment.
Unresolved ·
field-checksum· current · observed 2026-09-24checksum: Whether the body has a checksum or embedded id.
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Nothing stated. SDKs HMAC with the whole string as UTF-8 bytes and never decode it (stripe-go/node/python webhook code).
Unresolved ·
listed-references· current · observed 2026-09-24The legacy contract lists 5 references without stating which property each supports.
- docs.stripe.com/webhooks/signatureprovider-documentation · last read 2026-09-27 · latest outcome read · supports Listed as a reference by the legacy contract
- docs.stripe.com/keysprovider-documentation · last read 2026-10-04 · latest outcome read · supports Listed as a reference by the legacy contract
- docs.stripe.com/api/webhook_endpoints/objectprovider-documentation · last read 2026-09-27 · latest outcome read · supports Listed as a reference by the legacy contract
- github.com/redact-secret/redact-secret-benchmarks/issues/224issue-or-discussion · last read 2026-09-24 · latest outcome read · supports Listed as a reference by the legacy contract
- stripe/stripe-cli @ master: pkg/reporting/scrub.goprovider-sdk-source · last read 2026-09-24 · latest outcome read · supports Listed as a reference by the legacy contract
Provider documented ·
dossier-research· current · observed 2026-09-27Legacy dossier research (verdict ready, tier T1) cited 5 sources; the dossier does not attribute sources to individual properties.
- docs.stripe.com/webhooks/signatureprovider-documentation · last read 2026-09-27 · latest outcome read · supports Cited by the legacy dossier research for this family
- docs.stripe.com/keysprovider-documentation · last read 2026-10-04 · latest outcome read · supports Cited by the legacy dossier research for this family
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Cited by the legacy dossier research for this family
- docs.stripe.com/api/webhook_endpoints/objectprovider-documentation · last read 2026-09-27 · latest outcome read · supports Cited by the legacy dossier research for this family
- redact-secret/redact-secret @ 8b6a5fde52ecb4dfce13f09c7a947062d21483c7: docs/audits/evidence/726/README.mdproject-research-note · last read 2026-09-27 · latest outcome read · supports Final research evidence recorded by the legacy dossier
Provider documented ·
taxonomy-sources· current · observed 2026-09-27The legacy taxonomy lists 1 source for this family. The taxonomy records no date; the dossier researchedAt is used as the observed-at date.
- docs.stripe.com/webhooksprovider-documentation · last read 2026-09-27 · latest outcome read · supports Listed as a source for this family in the legacy taxonomy
Open questions
No open question is recorded for this revision.
Benchmark dossier notes
- Shape
- prefix
whsec_followed by a body of at least 32 Base64-alphabet characters, optional trailing=padding. Stripe documents only the prefix (in the Dashboard and v2 event destination flows, and for CLI secrets, which are "different" from Dashboard ones) and calls signing secrets "not API keys". The API object example shows 32 mixed-case alphanumerics; a CLI docs placeholder has 14; an SDK example uses 64 zeros. Stripe's own CLI scrubber admits+,/and=, while a second regex in the same repository accepts letters and digits only. - Basis
- T1 for the prefix and configuration context (provider docs). Body: provider code and example plus scanner rules, contradictory on alphabet. SDKs use the whole string, prefix included, as the HMAC key and never Base64-decode it.
- Issuance
- not attempted. Sandbox Dashboard or
stripe listen --print-secretis free; checklist in benchmarks#224. There is noliveortestsegment. - Contract in core
- detector-families.md (frozen in the #726 record as context-gated for qualification; the #729 implementation detects the prefix bare, as attribution is a benchmark concept).
In this benchmark
- Fixtures
- 29
- Left readable
- 0
- Redacted too much
- 0
- False alarms
- 0
29 fixtures: 3 expect a redaction, 15 must stay quiet, 11 record project policy. See every row
| Evidence level | Fixtures | Left readable | Too much | False alarms |
|---|---|---|---|---|
| T1Provider-documented | 1 | 0 | 0 | 0 |
| T2Tool-corroborated | 9 | 0 | 0 | 0 |
| T3Project policy | 16 | 0 | 0 | 0 |
| T0Pending review | 3 | 0 | 0 | 0 |
Every scanner on the same fixtures
In run order. Counts are what each scanner recorded on this family's fixtures, whichever rules it has; a scanner with no rule for the family has nothing to report on it.
| Scanner | Fixtures | Left readable | Too much | False alarms |
|---|---|---|---|---|
| flare-redactRuntime library · 1.6.1 · Published npm package · secrets-only (pii, generic_assignment disabled) · JavaScript engine1 rule targets it | 29 | 0 | 0 | 0 |
| gitleaksRepository scanner · 8.30.1 · Directory scan · default rulesNo rule maps to it | 29 | 5 | 0 | 1 |
| redact-secretProduct measured here · 0.1.0-beta.14 · Published npm package · default detectors1 detector mapped | 29 | 0 | 0 | 0 |
| trufflehogRepository scanner · 3.97.4 · Filesystem scan · verification disabledNo rule maps to it | 29 | 11 | 0 | 0 |
Benchmark dossier questions
- Open caveat
- T1 on the whsec_ prefix and Stripe context only; body width and alphabet are not provider-stated, and Svix and Standard Webhooks issue whsec_ secrets too.
Looks like it, but isn't
- Collisions
- Svix and Standard Webhooks also use
whsec_(Base64 of 24 to 64 bytes, decoded before use), plus asymmetric siblingswhsk_/whpk_. Public or non-secret values nearby:we_endpoint ids,ed_event destination ids,evt_ids,Stripe-Signaturedigests,pk_keys.
Scanner rules for this family
| Scanner | Rule | What the rule matches |
|---|---|---|
| flare-redact · rules 1.6.1 | stripe_webhook_secret | whsec_ + 32-64 characters |
No rule maps to this family in gitleaks, openredaction, trufflehog.
Fixtures in this family
| Fixture | Kind and evidence | redact-secret |
|---|---|---|
stripe-webhook-signing-secret-actions-envstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-compose-webhook-secretstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-dotenv-webhook-secretstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-endpoint-create-responsestripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-event-destination-create-responsestripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-export-webhook-secretstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-node-construct-event-widestripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-publishable-key-public-idstripe · public-identifier | Must not flagT2 · Tool-corroborated | Quiet |
stripe-webhook-signing-secret-python-construct-eventstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-rails-credentials-rollingstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-stripe-listen-readystripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-webhook-signing-secret-webhook-verifier-logstripe · documented-format-literal | Project policyT3 · Project policy | Redacted |
stripe-token-shape-6-barestripe · unsettled-evidence-input | Pending reviewT0 · Pending | Unscored |
stripe-token-shape-6-quotedstripe · unsettled-evidence-input | Pending reviewT0 · Pending | Unscored |
stripe-token-shape-6-unicode-crlfstripe · unsettled-evidence-input | Pending reviewT0 · Pending | Unscored |
stripe-webhook-signing-secret-docs-sentence-prosestripe · prose-mention | Must not flagT3 · Project policy | Quiet |
stripe-webhook-signing-secret-dotenv-webhook-secret-public-prefix-twinstripe · public-sibling-prefix | Must not flagT1 · Provider-documented · twin | Quiet |
stripe-webhook-signing-secret-ellipsis-placeholderstripe · documentation-placeholder | Must not flagT3 · Project policy | Quiet |
stripe-webhook-signing-secret-endpoint-create-response-boundary-twinstripe · boundary-violation | Must not flagT2 · Tool-corroborated · twin | Quiet |
stripe-webhook-signing-secret-endpoint-object-public-idstripe · public-identifier | Must not flagT2 · Tool-corroborated | Quiet |
stripe-webhook-signing-secret-event-destination-log-public-idstripe · public-identifier | Must not flagT2 · Tool-corroborated | Quiet |
stripe-webhook-signing-secret-export-webhook-secret-case-twinstripe · prefix-near-miss | Must not flagT2 · Tool-corroborated · twin | Quiet |
stripe-webhook-signing-secret-fill-in-placeholderstripe · documentation-placeholder | Must not flagT3 · Project policy | Quiet |
stripe-webhook-signing-secret-masked-placeholderstripe · documentation-placeholder | Must not flagT3 · Project policy | Quiet |
stripe-webhook-signing-secret-prefix-only-near-missstripe · format-near-miss | Must not flagT2 · Tool-corroborated | Quiet |
stripe-webhook-signing-secret-print-secret-substitution-referencestripe · templated-reference | Must not flagT3 · Project policy | Quiet |
stripe-webhook-signing-secret-python-construct-event-separator-twinstripe · prefix-near-miss | Must not flagT2 · Tool-corroborated · twin | Quiet |
stripe-webhook-signing-secret-stripe-signature-header-encoded-valuestripe · benign-encoded-value | Must not flagT2 · Tool-corroborated | Quiet |
stripe-webhook-signing-secret-webhook-verifier-log-alphabet-twinstripe · wrong-alphabet | Must not flagT2 · Tool-corroborated · twin | Quiet |
Sources
Documentation and code
- docs.stripe.com/webhooks
- benchmarks/lib/assessment.ts (classifyFixture variant guard: "Variant support must not be inferred from a related family name.")
- docs.stripe.com/webhooks/signature
- docs.stripe.com/api/webhook_endpoints/object
- docs.stripe.com/keys
Research log
- redact-secret/redact-secret#513Research issue
- redact-secret/redact-secret-benchmarks#224Research issue
- redact-secret/redact-secret-benchmarks#367Research issue
- redact-secret/redact-secret-benchmarks#372Research issue
- redact-secret/redact-secret#726Research issue
- redact-secret/redact-secret#729Research issue
- Final evidence, pinned to a commit/redact-secret/redact-secret/blob/8b6a5fde52ecb4dfce13f09c7a947062d21483c7/docs/audits/evidence/726/README.md