Published 2026-04-28 — v1.0
Secret detection methodology
CipherCue scans the public JavaScript served from an organisation's primary website for strings whose structure matches a known credential format. This page specifies the rule set, the scope of what is fetched, the observation-only posture, and how findings are surfaced.
Scope (what is fetched)
For each entity, a single HTTPS GET is issued against the canonical website root. From the returned HTML, CipherCue extracts:
- Inline
<script>blocks longer than 20 characters. - External script URLs from
<script src>and<link rel="modulepreload">, restricted to the same registrable domain as the canonical website (its apex). Cross-origin third-party scripts (CDN-hosted SDKs, analytics vendors) are excluded — a credential observed in those bundles is not the entity's exposure.
Limits: HTML body capped at 1,000,000 bytes; each external script capped at 2,000,000 bytes; up to 20 same-origin external scripts per entity per scan; up to 5 redirects followed. Every outbound request carries the published compliance header set documented at /scanning.
Rule set v1.0
The rule set is published in the open codebase at config/ciphercue/secret_patterns.php. Each rule has an identifier, a title, a severity, a PCRE pattern, and a one-line description. The version string is cited verbatim in every fact CipherCue records, so the methodology page and the underlying observation never disagree.
v1.0 covers 28 patterns across the following categories:
- Cloud and infrastructure providers. AWS access key IDs, AWS secret keys, Azure subscription keys, OpenAI keys.
- Payments and messaging. Stripe live secret and publishable keys, Twilio API keys, SendGrid keys, Mailgun keys.
- Source-code platforms. GitHub classic and fine-grained tokens, GitLab tokens, npm tokens.
- Productivity surfaces. Slack tokens and incoming webhook URLs, Google API keys, Firebase configuration values.
- Generic credentials. JWTs, Bearer/Basic auth headers, credentials embedded in URLs, PEM-encoded private keys, hard-coded password/secret/api-key/token assignments, database connection strings (PostgreSQL, MySQL, MongoDB, MSSQL, Redis, AMQP).
- Environment leakage. Internal/RFC-1918 URLs, staging/dev/sandbox URLs.
Severity
Each rule carries a fixed severity grade — critical, high, medium, or low — published with the rule and stable across the v1.0 lifecycle. Severity reflects the maximum damage an attacker holding a live credential of that class could do, not a probability claim about the specific match.
Why JavaScript bundles
JavaScript shipped to the browser is, by definition, public. Anything embedded in it is observable by any visitor without authentication or special tooling. Several common patterns put credentials there unintentionally:
- Server-side environment variables substituted into the client bundle at build time.
- Credentials hard-coded during prototyping that survive into production deployments.
- Server-only API keys placed alongside publishable keys without distinguishing the two.
- Configuration objects (
apiKey,authDomain,databaseURL) intended to be public — these match Firebase rules but are not necessarily a problem; they are surfaced for completeness.
Observation-only posture
CipherCue does not validate matched strings. We do not call AWS with a candidate access key, post to a Slack webhook URL, or issue any request that would test whether a matched string is live. Validation crosses from observation into testing, which the published disclosure policy precludes outside of a coordinated engagement.
Customers who choose to validate findings themselves do so under their own authority and against their own credentials.
What CipherCue records
For each rule that produces at least one match against an entity's bundles in a given scan, CipherCue writes one EntityFact with:
fact_type = "js_secret_observation";fact_key = "{host}:{rule_id}:{Y-m-d}"— host, rule, and observation date;fact_valuecontaining the rule id, title, severity, host, final URL, count of matches, up to 25 redacted match excerpts (truncated to under 120 characters), authority source string, rule set version, and authority URL;disclosed_at = nullat write time anddisclosure_status = "pending_disclosure".
Pre-disclosure handling
Every new js_secret_observation fact enters the 48-hour silent-disclosure window described in /disclosure-policy. CipherCue resolves a security contact via security.txt, WHOIS abuse, or security@{domain}, and notifies the affected organisation before the observation is exposed in any customer-facing surface. After 48 hours the fact's disclosed_at is set and the observation becomes visible to CipherCue users with access to the entity.
False positives
Pattern matching produces false positives by design. A 40-character base64-shaped string can be a JWT, a hash, or compiled bytecode. Severity is per-rule and not adjusted by structural confidence. The rule set explicitly prefers higher recall over higher precision, with the disclosure window as the safety mechanism — the affected organisation is the first reader, not the customer.
If a finding is spurious (the matched string is a deterministic hash, a compile-time fingerprint, a fixture, etc.), email corrections@ciphercue.com with the entity, rule id, and a short note. We dismiss the fact and, if the pattern routinely produces the same false positive class, document it in a future rule set version's changelog.
Authority references
- OWASP ASVS V14.3 — secrets management requirements for client-deployed code.
- CWE-798 — use of hard-coded credentials.
- NIST SP 800-115 §3 — passive observation as a technical security testing method.
- RFC 9116 — security.txt, used for disclosure-contact resolution.
Correction
Corrections, opt-outs, and disclosure-channel updates are handled per /opt-out and /disclosure-policy. CipherCue never publishes the matched string itself in customer-facing surfaces; the redacted excerpt is shown only to the disclosing organisation and to the customer after the 48-hour window.
Changelog
v1.0 — 2026-04-28 — Initial publication. 28 patterns across cloud/infra, payments, source-code platforms, productivity, generic credentials, and environment leakage. Per-domain scope (canonical website + same-origin external scripts). Observation-only posture; no validation. 48-hour silent disclosure window applied via the published disclosure policy.