Skip to content

Fail CI before security.txt expires - #671

Merged
babltiga merged 1 commit into
mainfrom
fix/AF-security-txt-expiry-guard
Aug 3, 2026
Merged

Fail CI before security.txt expires#671
babltiga merged 1 commit into
mainfrom
fix/AF-security-txt-expiry-guard

Conversation

@babltiga

@babltiga babltiga commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #670, which shipped .well-known/security.txt with a caveat I flagged at the time: nothing renews it.

The problem

RFC 9116 makes Expires mandatory, and once that date passes the file is invalid, not merely stale — it keeps returning 200 while scanners and researcher tooling treat it as unusable. website/ has no build step and the repo has no scheduled workflow, so the date would have slipped in complete silence, leaving a worse signal than shipping no security.txt at all.

The guard

frontend/src/config/__tests__/websiteSecurityTxt.test.ts turns the deadline into a CI failure with lead time:

Time to expiry Behaviour
> 90 days passes silently
90 → 30 days passes, prints a renewal warning in CI output
< 30 days fails, naming the file and the fix
already expired fails, reporting how many days ago
set more than 1 year out fails — RFC 9116 §2.5.5 recommends under a year

That last row is deliberate: it blocks "renewing" the file by setting Expires to 2099, which would pass a naive check while still being wrong.

Verified by moving the date through all four future states, not just running it against today.

Renewal is intentionally a human step

The date is a claim that the contact information is still current, so auto-bumping it on deploy would defeat the purpose. Renewing means setting Expires one year out and confirming the Contact URL still accepts reports.

Known gap

The guard only fires when CI runs. That is frequent enough for this repo, but a long-quiet period could still let the date slip. A scheduled workflow opening an issue would close it — deliberately not added here, since it would be the repo's first cron workflow. The trade is documented in website/README.md.

Also

Corrects a caveat from #670: production confirmed Cloudflare Workers assets does upload dot-directories (/.well-known/security.txt returns 200, text/plain), so the "verify it deploys" note is resolved.

Verification

1327 frontend tests, typecheck and lint (0 errors) all pass.

RFC 9116 makes Expires mandatory, and past that date the file is invalid
rather than merely stale — it keeps serving 200 while scanners treat it
as unusable. Nothing renewed it: website/ has no build step and the repo
has no scheduled workflow, so the date would have passed in silence and
left a worse signal than shipping no security.txt at all.

Graduated alarm instead of relying on memory:
  > 90 days   passes silently
  90-30 days  passes, warns in CI output
  < 30 days   fails, naming the file and the fix
  expired     fails, reporting how many days ago
  > 1 year    fails — blocks "renewing" it by setting a date in 2099

Verified against all four future states by moving the date, not just the
current one.

Also corrects the README: production confirmed Cloudflare Workers assets
does upload dot-directories, so the "verify .well-known deploys" caveat
is resolved. Notes the residual gap honestly — the guard only fires when
CI runs, so a long-quiet repo could still let the date slip.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Frontend Test Results

1 327 tests  +5   1 327 ✅ +5   3m 34s ⏱️ - 1m 18s
  173 suites +1       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 2d332fe. ± Comparison against base commit 29fcac5.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Frontend Coverage (frontend)

Status Category Percentage Covered / Total
🟢 Lines 93.83% (🎯 90%) 2087 / 2224
🟢 Statements 91.82% (🎯 90%) 2324 / 2531
🟢 Functions 90.98% (🎯 90%) 636 / 699
🟢 Branches 83.59% (🎯 80%) 1310 / 1567
File CoverageNo changed files found.
Generated in workflow #855 for commit 2d332fe by the Vitest Coverage Report Action

@babltiga
babltiga merged commit c1b158e into main Aug 3, 2026
14 checks passed
@babltiga
babltiga deleted the fix/AF-security-txt-expiry-guard branch August 3, 2026 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant