Get one script, with its decisions
const url = 'https://api.us.headerhawk.com/v1/sites/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/scripts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.us.headerhawk.com/v1/sites/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/scripts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \ --header 'Authorization: Bearer <token>'One script from the inventory with every decision made about it, oldest first: the record a PCI DSS 6.4.3 assessor asks for. The same plan rule as the list. Reads reported data, so it spends the tenant’s budget too.
Window: the last 31 days by default; at most 31, longer is 400.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The site’s id.
The script’s id.
Query Parameters
Section titled “Query Parameters”Only reports received at or after this instant. Defaults to the start
of your retention window, or where the operation bounds its window, to
that many days before to. Earlier than your retention reaches is
400.
Only reports received before this instant. Defaults to now.
Responses
Section titled “Responses”The script
object
A script with every decision made about it, oldest first.
object
A script’s current decision. unreviewed until someone
authorizes or rejects it.
any_content or pinned_hashes while authorized, otherwise null.
A nullable string rather than the enum, which cannot hold a null
that CloudFormation will import.
Who made a decision, as recorded at the time.
object
When it was last seen with a hash it had not had before
A version of the script. hash is empty for a script loaded
cross-origin without CORS, which browsers report unhashed. The daily
scan of a payment page is not subject to CORS, so the same
script can have an empty browser hash beside a scan hash, and the scan
hash can be pinned.
object
What saw these bytes first: a browser’s 'report-sha256' report,
or HeaderHawk’s daily scan of a payment page, which fetches the
page’s scripts and hashes them itself.
Every source that has seen these bytes, source first. Both
hash the same bytes the same way, so one version seen both ways
lists both.
Whether the current authorization pins it
What published package these exact bytes came from, or null for a hash the fingerprint index does not hold - which is most first-party bundles, and always will be.
Built from jsDelivr’s data API, which publishes a base64 SHA-256
for every file of every npm package version it serves,
byte-identical to what a browser reports under 'report-sha256'.
So the name rests on the hash matching a published file exactly,
not on the URL, the file name or anything the site said.
Written once, on the hash’s first sighting or by the loader’s backlog sweep, and never changed: an identity is a property of the bytes.
object
The npm package name, e.g. jquery
The package version. Where the same bytes appear in more than
one release - a dist/ file unchanged between two patch
versions - this is the earliest release the index holds
containing them, which is a lower bound on the age of the bytes
rather than a claim about which release the script came from.
The file’s path within the package, e.g. dist/jquery.min.js
Where the identification came from; jsdelivr today. A string
rather than an enum, so another catalog does not break a
client.
HeaderHawk’s attempt to keep a verified copy of these bytes, or null when none was made: the hash was first seen before captures existed, on a plan without script authorization or a site without payment pages, or is empty (a script loaded without CORS has no hash to verify against).
When a hash is new to a script on a site that captures, HeaderHawk
fetches the URL once, hashes what it receives and keeps the file
only if the SHA-256 equals this hash. Never retried. A capture
succeeds only while the origin still serves the same bytes, so
mismatched is common for exactly the file that mattered, and is
itself a finding: receivedHash is what the origin served instead.
object
captured: the file is held, and owners and admins can download it in the dashboard.
mismatched: the origin served other bytes; nothing is held.
refused: a guard said no or the fetch produced no file;
reason says which. pending: under way. interrupted: an
attempt that never reported back, which is not retried.
Set on refused, null otherwise. One of daily_cap (the
site’s 100 fetches for the UTC day were spent),
unknown_host (a browser report named a host the site had not
loaded a script from before), not_allowed (an IP address, an
internal name, a port, or a name that resolves to a private
address), unsupported_hash (not a SHA-256), or the fetch’s
own: too_large (over 5 MB), html_response, http_error,
timeout, tls_failure, too_many_redirects,
connection_failed.
Which sighting asked for the capture
The URL fetched, query included
The URL that answered, after redirects
On mismatched, the sha256- hash of what the origin served
Bytes received: the file on captured, the other file on
mismatched
The fetch matched bytes HeaderHawk already held, for this site or another, so the stored copy was reused rather than added. Every capture fetches its own URL either way
Whether a browser is integrity-checking this script, from
the integrity-violation reports
Integrity-Policy-Report-Only: blocked-destinations=(script) asks for.
The inference runs one way. A report proves the script loaded with no
integrity metadata, so unprotected is evidence. An absent report
proves nothing on its own, so protected is only ever claimed for a
site that produced at least one integrity report in the window - see
reporting on SriCoverageSummary - and unknown is the default.
object
What decided the state: reports, the Integrity Policy stream, or
scan, the daily page scan reading the integrity attribute out
of the HTML. Null while the state is unknown. A nullable string
rather than an enum, which cannot hold a null that CloudFormation
will import.
When a browser last reported it loading without integrity
metadata. Null unless the state is unprotected.
report or enforce; enforce means the site’s Integrity Policy
is enforcing, so the browser blocked the script rather than only
reporting it. Null unless the state is unprotected. A nullable
string rather than an enum, for the same reason as source.
What can be said about a script’s contents. Four states, and three of them are not findings:
identified: the latest hash matched a published package file. The library, version and file say which.name_mismatch: it matched, and the script’s own URL claims a different package or version. An observation worded as a question, never an alert: a path containingjquery-3.7.1.min.jsserved from a site’s own CDN may be a legitimately patched build. Only raised where both sides state a version cleanly, and the package name is only compared where the URL names npm itself - a cdnjs library name and an npm package name are different namespaces.unrecognised: no hash matched. A prompt to look, not a verdict; a site’s own build output is in no public registry and will always land here.unhashed: every sighting was unhashed, so there are no bytes to identify. A script loaded cross-origin without CORS. This is the opposite ofunrecognisedand is deliberately not folded into it.
object
Null unless the state is identified or name_mismatch
Where the identification came from, such as jsdelivr; null when there is none.
What the script’s URL claims to be serving. Set only on
name_mismatch, where the question needs both halves.
object
The published advisories against the version a script runs now. Five states, and only one is a finding:
affected: identified as a version at least one advisory names.none_known: identified, and nothing is published against the version as ofcheckedAt. Not a statement that it is safe.pending: identified, and the version has not been checked yet.not_assessed: nobody could identify the script, so there is no version to look up. Most first-party code is here for ever, and it is never shown as clean.not_included: the plan does not include advisories (scripts.authorization).
object
The worst severity among items (critical, high, medium,
low or unknown), or null when there are none. A nullable string
rather than the enum, which cannot hold a null that CloudFormation
will import.
When the version was last checked; null unless checked
Worst first. Empty in every state but affected.
One published advisory against one library version, from OSV (https://osv.dev), which aggregates the GitHub Advisory Database among others. About the version: it does not say the vulnerable code is reachable on the page.
object
The source’s id, e.g. GHSA-gxr4-xjj5-5px2
Other names for it, CVE ids first
The source’s own rating where it has one (GitHub’s, which is what
npm audit shows), otherwise from the CVSS v3 base score.
unknown is a record carrying neither, not low.
The lowest release that fixes it for this version; null when none is published
Where to read it
Where it came from; osv today
When the source last changed the record
The script’s reports in the requested range; null when it was not reported in it.
object
Reports received. Repeat sightings are sampled.
Distinct pages it was reported on
The site’s payment pages among them
object
Every hash reported for it in the range, at most 50, as the browser wrote it (sha256-<base64>). An empty string is a cross-origin load without CORS, which the browser could not hash. Scripts › Integrity offers an integrity= attribute only when this holds exactly one hash.
What HeaderHawk’s daily scan of the site’s payment pages found of it in the requested range: the scan fetched and hashed it on these pages, or found its tag on a page whose latest scan no longer does. Null when no scan in the range did, which is every script on a site whose payment pages are not scanned, and every script a page’s scripts add while it runs.
object
The latest scan in the range that found it
The site’s payment pages whose scans found it
object
The payment pages whose latest scan in the range no longer finds it, with the last scan that did. A script that has left every page it was on is still listed, with these dates, rather than dropped from the inventory. Read from the scan’s list of the page’s scripts, never from browsers going quiet, and only from scans that loaded the page itself (a complete scan answered with a 2xx).
object
The last scan in the range that found it on the page
The page’s latest scan in the range, which did not
Every decision, oldest first: the append-only record a PCI DSS 6.4.3 assessor asks for.
One recorded decision. Decisions are never changed or removed.
object
any_content or pinned_hashes for an authorization, null for a
rejection
Who made a decision, as recorded at the time.
object
The window the scripts were read over.
object
Example
{ "data": { "status": "unreviewed", "hashes": [ { "source": "browser", "sources": [ "browser" ], "capture": { "state": "pending", "source": "browser" } } ], "coverage": { "state": "protected" }, "identification": { "state": "identified" }, "advisories": { "state": "affected", "items": [ { "severity": "critical" } ] }, "decisions": [ { "status": "authorized" } ] }}Headers
Section titled “Headers”The budget nearest to running out, per minute.
What is left of that budget this minute.
Seconds until that budget starts again.
A parameter was refused, or one the operation does not take was sent. The message names it.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}invalid_api_key: no key, or one that is malformed, unknown, revoked
or expired. One answer for all of them.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}plan_upgrade_required: the tenant’s plan does not include API access
(the key works again when it does), or does not include what this
operation reads.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}No such resource in your tenant.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}rate_limited: over a budget. Wait Retry-After seconds.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}Headers
Section titled “Headers”Seconds to wait before trying again.
rate_limit_unavailable or upstream_unavailable: HeaderHawk could
not serve this now. Nothing is wrong with the request; try again after
Retry-After seconds.
object
object
What went wrong. An open enum: treat a code you do not know by its HTTP status.
For people. Branch on code.
Quote it when you write to us about this request.
Example
{ "error": { "code": "bad_request" }}Headers
Section titled “Headers”Seconds to wait before trying again.