Skip to content

feat: publish security.txt (RFC 9116) at /.well-known/security.txt - #40

Merged
git-cgallagher merged 1 commit into
mainfrom
feat/security-txt
Sep 3, 2026
Merged

git-cgallagher merged 1 commit into
mainfrom
feat/security-txt

Conversation

@git-cgallagher

Copy link
Copy Markdown
Owner

Publishes a machine-readable security contact for edulab.appalachiancloud.co. One of three PRs in an estate-wide rollout (the domain matrix lives in mountain-infra/AGENTS.md).

Assumption to confirm: Contact: is mailto:cgallagher@keengeek.com — the address that already receives the estate's security alerts, chosen because it is known to deliver. If you'd rather use a security@ alias, all three content apexes have Google Workspace MX; swapping it in is a one-line change per copy.

Why this isn't just "add a file"

GET /.well-known/security.txt already returned HTTP 200 on this site before this PR — CloudFront's custom_error_response maps 403/404 to /index.html with status 200, so a scanner hunting for a security contact got a "success" that was really HTML. Verification therefore has to assert content-type and body, not status alone. That trap is now written into AGENTS.md and DEPLOY.md.

The deploy step needs care

The sync stamps everything immutable, max-age=31536000. security.txt carries an RFC 9116 Expires date that must be refreshed before it lapses (an elapsed file is invalid, not merely stale), so a one-year immutable cache would outlive the fix. It is therefore --excluded from the sync and copied separately with text/plain; charset=utf-8 and max-age=3600 — the same shape as the existing index.html/contact.html special-case, which also means the sync's --delete leaves it alone.

Renewal

Expires: 2027-08-31T00:00:00.000Z, duplicated across four copies in three repos. Treat them as one set; matrix and deadline are in mountain-infra/AGENTS.md.

Verify after merge

curl -sS -D - https://edulab.appalachiancloud.co/.well-known/security.txt

Expect 200, content-type: text/plain; charset=utf-8, and a Contact: line.

🤖 Generated with Claude Code

https://claude.ai/code/session_012Y7PCTaciw6HtEC1eLL185

Adds a machine-readable security contact for edulab.appalachiancloud.co.

Before this, GET /.well-known/security.txt returned HTTP 200 with
index.html (CloudFront's SPA error mapping), so a scanner saw a
"success" that was actually HTML. Publishing a real object fixes that.

The file is excluded from the immutable `aws s3 sync` and uploaded by its
own `aws s3 cp` with `text/plain; charset=utf-8` and `max-age=3600`: it
carries an RFC 9116 `Expires` date (2027-08-31) that must be refreshed
before it lapses, and a one-year immutable cache would outlive the fix.
Being excluded also keeps it safe from the sync's `--delete`, the same
way index.html/contact.html already are.

Part of an estate-wide rollout; the domain matrix and shared renewal
date live in mountain-infra/AGENTS.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Y7PCTaciw6HtEC1eLL185
@git-cgallagher
git-cgallagher merged commit 9099239 into main Sep 3, 2026
4 checks passed
@git-cgallagher
git-cgallagher deleted the feat/security-txt branch September 3, 2026 20:43
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