Deployed Frontend Secret and Debug Endpoint Exposure Gate avatar

Deployed Frontend Secret and Debug Endpoint Exposure Gate

Pricing

from $20.00 / 1,000 run starteds

Go to Apify Store
Deployed Frontend Secret and Debug Endpoint Exposure Gate

Deployed Frontend Secret and Debug Endpoint Exposure Gate

Reads the script bundles that your deployed pages load from their own origin and probes a fixed set of debug and schema paths. Reports each leaked key and each exposed endpoint with a redacted match, and gives one gate_pass verdict for your build step. HT

Pricing

from $20.00 / 1,000 run starteds

Rating

0.0

(0)

Developer

kingii98

kingii98

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

After each deploy, this Actor answers one question: did this build publish a live API key, and did it leave a debug or a schema endpoint open?

It reads each page that you give it, reads the scripts that the page loads from its own origin, searches those scripts for secret patterns, and probes a fixed set of debug and schema paths against the origin. It writes one record for each finding, one record for each page and one summary record with a gatePass boolean for your build step.

It uses HTTP only: GET and HEAD requests plus regular expression matching. It uses no browser, no proxy, no CAPTCHA service, no paid API and no external database. It never sends a discovered key anywhere, and it never calls a discovered endpoint with a discovered key. Only the first four characters of a match reach the dataset.

What it checks

Secrets in script bundles. Private key blocks, Stripe live secret keys, AWS access keys, GitHub tokens, Slack tokens, OpenAI keys, SendGrid keys, npm tokens, Mailgun and Twilio identifiers, signed JSON Web Tokens, and long values that sit next to a secret name.

Exposed endpoints. The default probe set holds 12 paths: /.env, /.env.local, /.git/config, /actuator/env, /debug/vars, /swagger.json, /openapi.json, /api-docs, /swagger-ui.html, /graphql, /graphiql and /server-status.

The false positive rules

A gate that reports a public key is removed from a build step in one week. Three rules keep the report honest:

  1. A publishable key is never a finding. A Stripe publishable key (pk_live_, pk_test_), a Mapbox public token (pk.eyJ), a PostHog project key (phc_) and any value behind a public- or publishable name are dropped before the report.
  2. A key type that is public by design keeps a low severity. A Google or Firebase Web API key (AIza...) is reported as low, so it never fails the gate at the default threshold. Restrict such a key by referrer instead.
  3. A probe needs evidence, not a status code. A single page application answers 200 with its own HTML shell for every path. A probe is a finding only when the body proves the exposure: /.env must look like an environment file, /openapi.json must hold an openapi or swagger key, /graphql must answer like a GraphQL server. An HTML answer is refused unless the rule expects HTML and finds its marker.

A documentation example value, for example AKIAIOSFODNN7EXAMPLE, is dropped as well.

Input

FieldTypeDefaultMeaning
urlsarraytwo public example pages1 to 20 page URLs on domains that you own
ownershipConfirmedbooleantrueConfirm that you own, or may test, every domain
scanBundlesbooleantrueRead the same-origin scripts of each page
maxBundleBytesinteger2000000Stop the read of one script at this size
maxScriptsPerPageinteger10Read at most this many scripts for each page
probePathsarraythe 12 paths aboveMaximum 30 paths
failOnstringhighinfo, low, medium, high, critical or never
timeoutSecondsinteger15Timeout of one request
maxRequestsinteger400Request budget of the run
maxRedirectsinteger2Same-origin redirect hops for a page request
trackBaselinebooleanfalseMark each finding with isNew against the last run
baselineKeystringbaselineKey of the baseline record in the key-value store

Every field has a default, so a run with empty input {} succeeds.

Only same-origin scripts are read. A script on a content delivery network belongs to another party, so the Actor leaves it alone and counts it in scriptsSkippedCrossOrigin.

Output

Finding recordrecordType: "finding", pageUrl, sourceUrl, sourceType (bundle, inline_script, page or probe), findingType (secret_pattern or exposed_schema_endpoint), patternName (for example stripe_live_secret_key or exposed_env_file), redactedMatch (the first four characters plus the length), byteOffset, severity, note, fingerprint, isNew and foundAt.

Page recordrecordType: "page", pageUrl, finalUrl, httpStatus, scriptsRead, bytesRead, inlineScripts, scriptsSkippedCrossOrigin, scriptsSkippedOverLimit, probesRun, findingCount, error and auditedAt.

Summary recordrecordType: "summary", gatePass, failOn, pagesRequested, pagesAudited, pagesSkipped, scriptsRead, bundlesScanned, bytesRead, findingCount, newFindingCount, findingsBySeverity, requestsSent, status, note and finishedAt.

Use it in a build step

Run the Actor after each deploy and read the last record of the dataset:

GATE=$(curl -s "https://api.apify.com/v2/datasets/$DATASET_ID/items?clean=true" \
| jq -r '[.[] | select(.recordType=="summary")][0].gatePass')
[ "$GATE" = "true" ] || exit 1

Set trackBaseline to true to accept a known false positive once. The first run stores the fingerprint of every finding. The next run marks a finding that the store does not hold with isNew: true, so your step can fail on new findings only. A fingerprint holds the origin, the finding type, the pattern name and the redacted value, so it survives a new bundle name after the next build.

A business verdict is never a failed run

A failed gate, a page that does not answer, a target that the Actor refuses and a run with zero findings are all results. Each one is a dataset record plus a run status message, and the run ends SUCCEEDED. A run ends FAILED only when the input itself cannot be parsed.

Safety

The Actor refuses every loopback, private, link-local and reserved address, and refuses a URL that carries credentials. It re-checks the address after each redirect hop, and it does not follow a redirect that leaves the origin. A script read and a probe never follow a redirect.

Set ownershipConfirmed to false and the Actor audits nothing: it probes debug paths, so it must run against your own deployment only.

Pricing (pay per event)

EventUnitPrice
run-startedone Actor runUSD 0.02
page-auditedone page fetched, parsed and probed with the path setUSD 0.03
bundle-scannedone script file read and searchedUSD 0.01
finding-reportedone finding written to the datasetUSD 0.02

run-started is charged once, after the input is accepted. page-audited is charged for each page that the Actor really fetched and probed; a page that was refused or unreachable is not charged. bundle-scanned is charged for each script that was read and searched; an inline script costs nothing extra, because the page body already holds it. finding-reported is charged for each finding record. A single page application with 6 bundles and no findings costs about USD 0.11 for each deploy.

Local development

uv sync
uv run pytest
uv run ruff check .