# security.txt -- RFC 9116. The machine-readable half of /security. # # WHY THIS FILE EXISTS # A researcher who finds something in our estate should not have to guess where to send it, # and the guess they make when there is no file is "the address on the marketing page, if I # can find one, or nowhere". This is the one location a scanner, a disclosure platform and a # researcher all already look. # # --------------------------------------------------------------------------------------- # THIS FILE IS DELIBERATELY PURE ASCII # --------------------------------------------------------------------------------------- # RFC 9116 section 3 requires text/plain, and recommends charset=utf-8. Cloudflare Pages # serves .txt as text/plain; charset=utf-8 by default, so no rule is added to public/_headers # for it -- robots.txt and llms.txt already rely on the same default. But `astro preview` # serves it as bare `text/plain` with NO charset [measured 2026-08-31: curl -i against # astro preview on :4341 returned `Content-Type: text/plain`], and X-Content-Type-Options: # nosniff is inherited from /* in _headers, so a client that falls back to ISO-8859-1 would # render a smart quote or an em dash as mojibake in the middle of a disclosure address. # # public/_headers already carries this exact argument for install.ps1, which is pure ASCII # for the same reason: the file's correctness must not depend on a default we do not control. # So this file uses no character above U+007F. Keep it that way -- it is cheaper than owning # a _headers rule, and it cannot regress. # # --------------------------------------------------------------------------------------- # ONE ADDRESS, BECAUSE ONE MAILBOX EXISTS # --------------------------------------------------------------------------------------- # Contact below is hello@tokentriage.com, which is what src/consts.ts LEGAL_CONTACT.security # resolves to and what /security has always published. It is deliberately NOT security@: # that alias routes nowhere today, and an unrouted address in this file is strictly worse # than a general one, because the person who uses it is by definition holding an unpatched # vulnerability, and their report goes nowhere while the file tells them it arrived. # If the alias is ever created, src/consts.ts, /security and this file change in ONE commit. # # --------------------------------------------------------------------------------------- # EXPIRES: THE REASONING, AT THE SITE # --------------------------------------------------------------------------------------- # RFC 9116 section 2.5.5 makes Expires mandatory and recommends less than a year. The date # below is ~10 months out rather than the full 12, and the margin is not arbitrary: # # - An EXPIRED security.txt is worse than no security.txt. A missing file reads as "they # never got to it"; an expired one reads as "this disclosure route was abandoned", and a # researcher who concludes that may not send the report at all. The failure mode of this # file is silence -- which is also the failure mode we would never observe. # - The contact posture is expected to CHANGE inside that window. The hosted service opens # in it, and the single-mailbox decision above is explicitly staged to be revisited once # a real security@ mailbox exists. Expiring while that change is still recent puts the # renewal in front of someone who remembers why the address is what it is. # - Ten months lands the renewal mid-2027, clear of the debut itself, so the review is not # competing with launch work for attention. # # THE OBLIGATION THIS CREATES, STATED PLAINLY: before 2027-06-30 somebody must (1) confirm # hello@tokentriage.com still reaches a human who reads it, (2) reconcile Contact against # src/consts.ts LEGAL_CONTACT.security and the /security page, and (3) reissue with a new # Expires date. # # NOTHING IN CI CHECKS ANY OF THAT TODAY. No gate fails a build on an expired or # near-expiry security.txt, so this file's correctness rests on a human remembering, which # is the weakest mechanism in this repository and is named here rather than left implicit. # A scripts/check-security-txt.mjs in the prebuild chain -- parse Expires, fail under 30 # days remaining, and reconcile Contact against LEGAL_CONTACT.security -- would close it, # and is recommended to whoever owns the next pass over this directory. Contact: mailto:hello@tokentriage.com Expires: 2027-06-30T23:59:59.000Z Policy: https://tokentriage.com/security/ Preferred-Languages: en Canonical: https://tokentriage.com/.well-known/security.txt