Repository Tree Publication Leak Gate for Static Hosts avatar

Repository Tree Publication Leak Gate for Static Hosts

Pricing

from $10.00 / 1,000 repository snapshot loadeds

Go to Apify Store
Repository Tree Publication Leak Gate for Static Hosts

Repository Tree Publication Leak Gate for Static Hosts

Find repository files outside the publish directory that your live static site serves.

Pricing

from $10.00 / 1,000 repository snapshot loadeds

Rating

0.0

(0)

Developer

kingii98

kingii98

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 hours ago

Last modified

Categories

Share

This Actor finds repository files that your live static site serves but should not. It takes the file list of your repository. It sends requests to your origin for each file outside the publish directory. Where possible, it proves that the served file is the repository file. It compares the git blob SHA-1 hash.

Input

FieldMeaning
originHTTPS URL of the deployed site. Private and reserved addresses are rejected.
ownershipAttestedYou must tick this box to confirm that you own the origin. Default is false. Without it, the Actor sends no request to the origin.
githubRepoOptional. owner/name@ref of a public repository. The Actor loads the file list with one call to the GitHub git trees API (recursive=1). It ignores pathList when you set this field.
githubTokenOptional secret. A read-only token. It raises the GitHub rate limit.
pathListOptional. Repository-relative paths, for example from git ls-files.
publishDirPaths inside this directory are expected to be public.
allowPublicPathsGlob patterns for paths that are public on purpose, for example CNAME. A pattern without / also matches the file name at any depth.
maxPathsDefault 2000. Hard cap 10000.

Empty input {} succeeds. Because ownershipAttested defaults to false, an empty-input run sends no request to the origin. It writes a summary with gate = fail and a reason. It does not end FAILED.

How a path is checked

  1. Paths inside publishDir or that match allowPublicPaths get the verdict expected_public. The Actor does not request them.
  2. For each other path, the Actor sends one HEAD request. It uses GET if the origin answers 405 or 501.
  3. If the status is 200, the Actor downloads at most 1 MB with GET.
  4. If the repository snapshot gives a blob SHA, the Actor compares it with the SHA-1 of the served bytes (blob <size>\0<bytes>).
    • Match: servedBlobShaMatches = true, verdict exposed.
    • No match: servedBlobShaMatches = false, verdict not_served. The origin probably returns a catch-all page.
    • No SHA (pathList) or body larger than 1 MB: servedBlobShaMatches = unknown, verdict exposed.
  5. Other results give the verdict not_served.

The Actor follows at most 3 redirects. It follows only redirects to the same HTTPS host.

Output

The dataset has one item per path (recordType = path) with: repoPath, probedUrl, httpStatus, contentType, bytes, servedBlobShaMatches, riskClass, verdict. The last dataset item is the summary (recordType = summary). The same record is in the key-value store under SUMMARY. The summary has gate (pass or fail), reason, exposedCount, exposedByRiskClass, and firstExposedPaths (first 20).

A failed gate, an unreachable target, a bad input, and zero findings are results. The run still ends SUCCEEDED. The gate is fail when a path is exposed or when the Actor could not finish the check (see reason).

Pricing events (pay per event)

EventWhen the Actor charges
repository-snapshot-loadedOnce, after the GitHub tree loads and parses. Not charged for pathList.
path-probedOnce for each path that the Actor probes on the origin. Paths with the verdict expected_public are not probed and not charged.

If the charge limit is reached, the Actor stops. It sets gate = fail with a reason.

Limits

  • The Actor does not detect a catch-all origin (single-page app) when no blob SHA is available. Use githubRepo for hash proof.
  • The check of the origin address happens before the requests. It does not stop DNS rebinding.
  • GitHub unauthenticated limit is 60 requests per hour per IP. Use githubToken or pathList.
  • If GitHub marks the tree as truncated, the summary notes it.
  • The Actor uses HTTP only. It uses no browser, proxy, or LLM.

Development

uv run pytest
uv run ruff check .