feat(security): implement FW-N5, FW-N6, FW-N7 (HMAC-SHA256 protocol docs, auto-generate token, replay attack defense)

This commit is contained in:
2026-06-21 10:39:29 +00:00
parent 8a4067ca91
commit 6a88f10a74
7 changed files with 28 additions and 26 deletions
@@ -63,6 +63,7 @@ class _Watcher:
self.events: "queue.Queue[Tuple[str, Dict[str, Any]]]" = queue.Queue()
self.expected = set(expected_job_ids)
self.tokens = expected_tokens # job_id -> expected auth_token (or None)
self.last_seq: Dict[str, int] = {jid: 0 for jid in expected_job_ids}
def on_message(self, _client, _userdata, msg) -> None:
# --- defensive parsing -------------------------------------------
@@ -87,6 +88,16 @@ class _Watcher:
if not mqtt_common.verify_hmac(payload, expected_token):
logger.warning("drop event for job %s: HMAC verify failed", jid)
return
# --- replay attack defense: check monotonic sequence ---
seq = payload.get("seq")
if seq is None or not isinstance(seq, int):
logger.warning("drop event for job %s: missing or invalid seq", jid)
return
if seq <= self.last_seq.get(jid, 0):
logger.warning("drop event for job %s: seq %d is not monotonically increasing (last %d)",
jid, seq, self.last_seq.get(jid, 0))
return
self.last_seq[jid] = seq
# Persistent audit log from the *subscriber's* vantage point: every event
# that survives defensive parsing is recorded here, including ones a
# different host published. This is the external-observer record that