From 64005945e3480d327bdccbf22c1dda415273bbc0 Mon Sep 17 00:00:00 2001 From: Sarah Lacard Date: Fri, 1 May 2026 12:43:23 -0600 Subject: [PATCH 1/2] fix(detector): detect object.__setattr__ module mutation --- kernelguard.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/kernelguard.py b/kernelguard.py index f086847..8847344 100644 --- a/kernelguard.py +++ b/kernelguard.py @@ -1604,6 +1604,22 @@ def detect_module_mutation(code: str | SubmissionFacts) -> list[dict]: f"(bytecode replacement on '{mod}')" ), }) + # Check for object.__setattr__(module, attr, value) pattern + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + if isinstance(node.func, ast.Attribute) and node.func.attr == "__setattr__": + if isinstance(node.func.value, ast.Name) and node.func.value.id == "object": + if len(node.args) >= 2 and isinstance(node.args[0], ast.Name) and isinstance(node.args[1], ast.Constant): + mod_name = node.args[0].id + attr_name = str(node.args[1].value) if isinstance(node.args[1].value, str) else "" + if mod_name in aliases: + sev = "critical" if attr_name in TRUSTED_FUNCTIONS else "high" + matches.append({ + "pattern": "MODULE_MUTATION", + "severity": sev, + "evidence": f"object.__setattr__({mod_name}, '{attr_name}', ...) — evades direct assignment check", + }) return matches From c26e7d90d89a17f6ab4cdcebe97853a419a2bb99 Mon Sep 17 00:00:00 2001 From: Sarah Lacard Date: Fri, 1 May 2026 22:20:53 -0600 Subject: [PATCH 2/2] chore: trigger blue-pr-sync re-evaluation