diff --git a/api/bridge.py b/api/bridge.py index ef8b3f6..aebf97d 100644 --- a/api/bridge.py +++ b/api/bridge.py @@ -772,9 +772,8 @@ class BridgeHandlers: details={"status": data.get("status", "completed")}, ) logger.info( - "F46: Worker result accepted for job=%s from=%s", + "F46: Worker result accepted for job=%s", job_id, - _bridge_sensitive_tag(device_id, label="device"), ) return web.json_response(response_data, status=201) diff --git a/services/audit.py b/services/audit.py index ec9e7ac..7edfef3 100644 --- a/services/audit.py +++ b/services/audit.py @@ -271,16 +271,13 @@ def _emit_modern( ) -> Dict[str, Any]: details_dict = _sanitize_audit_details(details or {}) token = token_info or _resolve_request_token_info(request) - token_tag = "token:none" + auth_context = "anonymous" role = "unknown" scopes: list[str] = [] if token is not None: - # IMPORTANT: audit persistence must store only a deterministic tag here, - # never the raw token_id, or the residual CodeQL alert reopens. - token_tag = stable_redaction_tag( - getattr(token, "token_id", "anonymous"), - label="token", - ) + # IMPORTANT: do not persist or log token-derived identifiers here. + # CodeQL still classifies deterministic token tags as sensitive storage/logging. + auth_context = "authenticated" role = _normalize_role(getattr(token, "role", "unknown")) scopes = _normalize_scopes(getattr(token, "scopes", [])) scope = scopes[0] if scopes else "" @@ -290,7 +287,7 @@ def _emit_modern( entry = { "ts": time.time(), "source": source, - "token_tag": token_tag, + "auth_context": auth_context, "role": role, "scope": scope, "scopes": scopes, @@ -303,11 +300,11 @@ def _emit_modern( } _write_audit_entry(entry) logger.info( - "AUDIT action=%s target=%s outcome=%s token=%s", + "AUDIT action=%s target=%s outcome=%s auth=%s", action, target, outcome, - token_tag, + auth_context, ) return entry diff --git a/tests/security/test_audit.py b/tests/security/test_audit.py index 4d0320d..1452e67 100644 --- a/tests/security/test_audit.py +++ b/tests/security/test_audit.py @@ -56,7 +56,7 @@ class TestAudit(unittest.TestCase): for field in ( "ts", "source", - "token_tag", + "auth_context", "scope", "scopes", "trace_id", @@ -69,8 +69,8 @@ class TestAudit(unittest.TestCase): "entry_hash", ): self.assertIn(field, entry) - self.assertTrue(entry["token_tag"].startswith("token:")) - self.assertNotIn("adm-1", entry["token_tag"]) + self.assertEqual(entry["auth_context"], "authenticated") + self.assertNotIn("adm-1", json.dumps(entry)) self.assertEqual(entry["role"], "admin") self.assertEqual(entry["action"], "config.update") self.assertEqual(entry["target"], "settings.json") diff --git a/tests/security/test_s78_redaction.py b/tests/security/test_s78_redaction.py index fd4e022..b333769 100644 --- a/tests/security/test_s78_redaction.py +++ b/tests/security/test_s78_redaction.py @@ -129,7 +129,8 @@ class TestS78BridgeWorkerRedaction(unittest.TestCase): ) output = "\n".join(logs.output) self.assertNotIn("worker-1", output) - self.assertIn("device:", output) + self.assertNotIn("device:", output) + self.assertIn("job=job-1", output) def test_duplicate_result_log_redacts_idempotency_key(self): from api.bridge import BridgeHandlers @@ -192,7 +193,7 @@ class TestS78AuditRedaction(unittest.TestCase): self.assertIn("***REDACTED***", details["error"]) self.assertNotIn("1.2.3.4", json.dumps(entries[0])) - def test_audit_storage_uses_token_tag_not_raw_token_id(self): + def test_audit_storage_omits_token_derived_identifiers(self): class _Token: token_id = "adm-1" role = "admin" @@ -210,9 +211,8 @@ class TestS78AuditRedaction(unittest.TestCase): entries = self._read_entries() entry = entries[0] self.assertNotIn("token_id", entry) - self.assertEqual( - entry["token_tag"], stable_redaction_tag("adm-1", label="token") - ) + self.assertNotIn("token_tag", entry) + self.assertEqual(entry["auth_context"], "authenticated") self.assertNotIn("adm-1", json.dumps(entry)) def test_audit_logger_omits_raw_token_id(self): @@ -233,7 +233,7 @@ class TestS78AuditRedaction(unittest.TestCase): output = "\n".join(logs.output) self.assertNotIn("adm-2", output) - self.assertIn("token:", output) + self.assertIn("auth=authenticated", output) class TestS83StableRedactionTag(unittest.TestCase):