telemetry: synthetic:true on canary refusals (keyed, not a bare flag)
The canary deliberately sends forged tokens every 10 min; those refusal rows read as attacks. It now sends X-Windy-Synthetic carrying a shared secret (Gitea repo secret CANARY_SYNTHETIC_KEY = WINDYGIT_SYNTHETIC_KEY in Veron .env); the API marks the row synthetic only on a constant-time match, so an attacker cannot label their own refusals synthetic to hide. synthetic is declared on forge.auth.failed (Telemetry Boss, UPDATE 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,14 @@ def _iso(epoch: float) -> str:
|
||||
return datetime.fromtimestamp(epoch, UTC).isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
def is_synthetic(headers, key: str) -> bool:
|
||||
"""Our own tooling proves itself with the shared key; a bare header proves nothing."""
|
||||
import hmac
|
||||
|
||||
presented = headers.get("x-windy-synthetic") or ""
|
||||
return bool(key) and bool(presented) and hmac.compare_digest(presented, key)
|
||||
|
||||
|
||||
def caller_class(headers) -> str:
|
||||
"""Declared values: anonymous_human | anonymous_agent | unknown."""
|
||||
from api.app.ept import looks_like_ept
|
||||
@@ -145,10 +153,16 @@ class Telemetry:
|
||||
caller: str,
|
||||
route: str | None = None,
|
||||
upstream_status: int | None = None,
|
||||
synthetic: bool = False,
|
||||
) -> None:
|
||||
if code not in AUTH_CODES:
|
||||
return
|
||||
meta: dict = {"code": code, "http_status": int(http_status), "caller": caller}
|
||||
meta: dict = {
|
||||
"code": code,
|
||||
"http_status": int(http_status),
|
||||
"caller": caller,
|
||||
"synthetic": bool(synthetic),
|
||||
}
|
||||
if route:
|
||||
meta["route"] = route
|
||||
if upstream_status is not None:
|
||||
|
||||
Reference in New Issue
Block a user