CIPHERCUE

Published 2026-05-08 — v1.3

JS bundle observation methodology

CipherCue scans the public JavaScript served from an organisation's primary website for three classes of observation: credential-shaped strings, configuration values that are public by design, and environment leakage (internal hostnames, staging URLs, connection strings). This page specifies the rule set, the scope of what is fetched, the observation-only posture, and how findings are surfaced.

A pattern match is not a verification. It records that a string matching a published format was observed in JavaScript an organisation publishes to the open web. CipherCue does not call the matched value or otherwise attempt to verify it is live.

Scope (what is fetched)

For each entity, a single HTTPS GET is issued against the canonical website root. From the returned HTML, CipherCue extracts:

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.3

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 category, 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.

Four categories of observation

The category field on every rule drives how a finding is handled — only the credential category is subject to the silent-disclosure window.

v1.3 covers 33 rules across the following surfaces:

Severity

Each rule carries a fixed severity grade — critical, high, medium, or low — published with the rule and stable across the v1.2 lifecycle. For credential rules, severity reflects the maximum damage an attacker holding a live credential of that class could do, not a probability claim about the specific match. For public_config and environment_leakage rules, severity reflects the operational sensitivity of the disclosed information.

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:

  1. Server-side environment variables substituted into the client bundle at build time.
  2. Credentials hard-coded during prototyping that survive into production deployments.
  3. Server-only API keys placed alongside publishable keys without distinguishing the two.
  4. 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:

Disclosure handling by category

Disclosure handling depends on the rule's category.

In customer-facing surfaces, the matched string is always shown via the match_redacted field — the first four and last four characters of the value with the middle replaced by bullets. The full match is retained in the fact for the disclosing organisation's own reference but is never republished outside coordinated disclosure.

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

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.2 — 2026-04-30 — Recategorised aws-access-key from credential (critical) to environment_leakage (low). An AWS access key ID alone identifies the AWS account and IAM principal but cannot authenticate without the paired secret access key; the calibration matches the realistic operational impact.
v1.1 — 2026-04-29 — Added category field on every rule (credential | public_config | environment_leakage). 48-hour silent-disclosure window now applies to credential only; public_config and environment_leakage facts are written as public_observation and surfaced immediately. Renamed the recorded fact_type from js_secret_observation to js_bundle_observation to reflect the broader observation set.
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.