security.txt Expiry, Encryption-Key Resolvability
Pricing
$5.00 / 1,000 domain checkeds
security.txt Expiry, Encryption-Key Resolvability
Checks security.txt files for expiry, unresolvable OpenPGP keys and unreachable contacts. Keeps a ledger of changes between runs.
Pricing
$5.00 / 1,000 domain checkeds
Rating
0.0
(0)
Developer
kingii98
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
14 hours ago
Last modified
Categories
Share
security.txt Expiry, Encryption-Key Resolvability, and Contact Reachability Ledger
This Actor checks the RFC 9116 security.txt file of each domain you give it. It tells you
before a reporter finds out that a file has expired, that a listed OpenPGP key cannot be
fetched, or that a Contact URL is not reachable. It keeps a ledger between runs, so it also
reports what changed.
What the Actor does for each domain
- It fetches
https://<domain>/.well-known/security.txt. If that fails, it fetches/security.txt. - It reads
Contact,Expires,Encryption, andCanonical. It accepts PGP-signed files. - It finds up to 3
Encryptionkeys. A key is anopenpgp4fpr:fingerprint or a URL. For a URL, the Actor downloads the key and reads its fingerprint and expiry. Then it asks each selected keyserver for that fingerprint. - If
checkContactUrlsis true, it sends a HEAD request to up to 2https:Contact values. It does not checkmailto:ortel:values. A status below 400 means reachable. Some servers refuse HEAD requests. They show as not reachable. - It compares the result with the state from the last run and stores the new state.
Input
| Field | Default | Meaning |
|---|---|---|
domains | ["curl.se", "github.com"] | 1 to 1000 hostnames. |
expiryLeadDays | 30 | Status is due when Expires is less than this number of days away. |
keyservers | keys.openpgp.org, keyserver.ubuntu.com | Keyservers to ask. |
checkContactUrls | true | HEAD check for https: Contact values. |
stateStoreName | stx-key-ledger | Named key-value store for ledger state. |
An empty input {} works. Every field has a default.
Output
One dataset item per domain. Main fields:
servedLocation,httpStatus,contentType,isPgpSignedexpires,daysToExpiry,expiryStatus(ok,due,expired, ormissing)canonicalMatchesServedUrl(nullwhen the file has noCanonical)contacts[]withreachable(nullwhen not checked)encryptionKeys[]withsource(URLorfingerprint),fingerprint,resolvedOn[],keyExpiry,reason(unsupported_schemewhen the value is not anopenpgp4fpr:orhttp(s)://value, for example adns:URI;sourceisURLfor these values and they show as not resolved)resolvedOn[]andkeyExpiryat top level (union of servers, first key expiry found)changeEvents[]:expires_moved,key_added,key_removed,contact_changed,file_removedalerts[]:expiry_due,expiry_expired,expires_missing,file_missing,key_unresolved,key_expired,contact_unreachableerror: a reason code when the check could not finish
The first run for a domain has no changeEvents, because no earlier state exists.
The run also writes a SUMMARY record to the default key-value store. It has counts by
expiryStatus, alert count, change-event count, and charge data.
A failed check is a normal result. A missing file, an expired file, or an unreachable target does not fail the run. The run fails only on a real malfunction.
Pricing event
The pricing model is pay-per-event. The Actor calls Actor.charge once per domain with
this event:
| Event name | Unit | Planned price |
|---|---|---|
domain-checked | One domain: security.txt fetched, keys resolved, and ledger updated. | $0.005 |
The Actor does not charge for an invalid hostname, for a private or reserved target, or for a
domain that does not resolve in DNS. If the charge limit is reached, the Actor stops and
reports the skipped domains in SUMMARY. You set the price in Apify Console. This
repository does not change pricing.
Safety limits
- HTTP only. No browser, proxy, LLM, paid API, or secret.
- Only
https:on port 443. Private, loopback, link-local, and reserved addresses are rejected. The Actor checks every redirect target too. - At most 3 redirects, 64 KB per response, 10 s per request, 30 s per fetch, 5 domains at once.
- Known limit: the Actor resolves a hostname before it connects. It does not pin the address. A hostile DNS server could still change the answer between the two steps.
- Known limit: key downloads stop at 1 MiB. A larger key shows as not resolved.
- Known limit: the OpenPGP reader supports v4 keys only. Other key versions show as not resolved.
Development
uv run pytestuv run ruff check .