From c96d1d3102f7821e1d4212c41ed7a3baa46ba677 Mon Sep 17 00:00:00 2001 From: Grant Whitmer Date: Thu, 13 Aug 2026 23:13:44 -0400 Subject: [PATCH] canary: guard both forgery shapes now that real verification is live MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EPT-shaped forgery is the one that matters after G3.2 — it is what signature verification actually guards. The JWT-shaped one still exercises the human gate. Both must_refuse; a 2xx on either pages. Verified live: forged EPT -> 401 ept_invalid, forged JWT -> 503, genuine EPT -> 200. Co-Authored-By: Claude (Fable 5) --- scripts/canary.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/scripts/canary.py b/scripts/canary.py index 40b8b5d..8d9f616 100755 --- a/scripts/canary.py +++ b/scripts/canary.py @@ -144,19 +144,32 @@ def build_checks() -> list[Check]: # SECURITY REGRESSION GUARD. A forged, unsigned token naming a real passport # must be refused. On 2026-08-13 this returned HTTP 200 (full agent # impersonation). If it ever returns 2xx again, the bypass is back. - _forged = ( - "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0" - ".eyJwYXNzcG9ydCI6IkVUMjYtMUVGOS1WSkFOIn0.x" - ) - checks.append( - Check( - "security.forged_agent_token", - "https://api.windygit.com/api/v1/repos", - "an unsigned token cannot impersonate an agent", - headers={"Authorization": f"Bearer {_forged}"}, - must_refuse=True, + import base64 as _b64 + import json as _j + + def _seg(d: dict) -> str: + return _b64.urlsafe_b64encode(_j.dumps(d).encode()).rstrip(b"=").decode() + + # Two shapes, because they exercise two different gates. The EPT-shaped one + # is the important one now: it is what real signature verification guards. + for _label, _hdr in ( + ("security.forged_agent_token", {"alg": "none", "typ": "JWT"}), + ("security.forged_ept", {"alg": "none", "typ": "EPT"}), + ): + _tok = ( + f"{_seg(_hdr)}." + f"{_seg({'sub': 'ET26-1EF9-VJAN', 'passport': 'ET26-1EF9-VJAN', 'iss': 'eternitas.ai', 'exp': 9999999999})}" + ".not-a-real-signature" + ) + checks.append( + Check( + _label, + "https://api.windygit.com/api/v1/repos", + "an unsigned token cannot impersonate an agent", + headers={"Authorization": f"Bearer {_tok}"}, + must_refuse=True, + ) ) - ) # THE important one. /health was 200 for the entire 2026-08-12 outage while # this was timing out. A canary that skips it is decorative.