diff --git a/.github/config/ast-grep-sigilix/rule-tests/eval-code-injection-test.yml b/.github/config/ast-grep-sigilix/rule-tests/eval-code-injection-test.yml
new file mode 100644
index 0000000..208361c
--- /dev/null
+++ b/.github/config/ast-grep-sigilix/rule-tests/eval-code-injection-test.yml
@@ -0,0 +1,17 @@
+id: js-eval-code-injection
+valid:
+ - const x = JSON.parse(input);
+invalid:
+ - function run(userInput) { return eval(userInput); }
+---
+id: ts-eval-code-injection
+valid:
+ - "const x: unknown = JSON.parse(input);"
+invalid:
+ - "function run(userInput: string): unknown { return eval(userInput); }"
+---
+id: tsx-eval-code-injection
+valid:
+ - "function R({input}: Props) { return
{JSON.parse(input)}
; }"
+invalid:
+ - "function R({userInput}: Props) { return {eval(userInput)}
; }"
diff --git a/.github/config/ast-grep-sigilix/rules/js-ts-eval-code-injection.yml b/.github/config/ast-grep-sigilix/rules/js-ts-eval-code-injection.yml
new file mode 100644
index 0000000..54629a2
--- /dev/null
+++ b/.github/config/ast-grep-sigilix/rules/js-ts-eval-code-injection.yml
@@ -0,0 +1,20 @@
+id: js-eval-code-injection
+language: JavaScript
+severity: error
+message: "Direct eval() call — runtime code execution from a value (code injection, CWE-94)."
+rule:
+ pattern: eval($$$ARGS)
+---
+id: ts-eval-code-injection
+language: TypeScript
+severity: error
+message: "Direct eval() call — runtime code execution from a value (code injection, CWE-94)."
+rule:
+ pattern: eval($$$ARGS)
+---
+id: tsx-eval-code-injection
+language: Tsx
+severity: error
+message: "Direct eval() call — runtime code execution from a value (code injection, CWE-94)."
+rule:
+ pattern: eval($$$ARGS)
diff --git a/.github/scripts/sigilix_sarif_contract.py b/.github/scripts/sigilix_sarif_contract.py
index 83205c7..6b10bb4 100644
--- a/.github/scripts/sigilix_sarif_contract.py
+++ b/.github/scripts/sigilix_sarif_contract.py
@@ -288,6 +288,13 @@ def _sanitize_run_results(run):
# guard keeps this collision-safe.
_RULE_CLASS_PATTERNS["gitleaks"] = [(re.compile(r".+"), "hardcoded-secret")]
_RULE_CLASS_PATTERNS["trufflehog"] = [(re.compile(r".+"), "hardcoded-secret")]
+# Sigilix-owned ast-grep rules (deterministic floors re-run on the signed HEAD).
+# Rule ids embed the class token, e.g. `ts-eval-code-injection`. Logic rules
+# (await-for-each, async-array-predicate) match nothing → left unset.
+_RULE_CLASS_PATTERNS["ast-grep"] = [
+ (re.compile(r"(?