From 372a85355bb2868daffd62f1ee2b6a607e1a0d47 Mon Sep 17 00:00:00 2001 From: Daniel A Martinez Julio Date: Fri, 19 Jun 2026 10:12:26 -0700 Subject: [PATCH] ast-grep: add eval code-injection rule + stamp ast-grep results to canonical class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our own deterministic eval detector, re-run on the forge-proof-signed HEAD in the runner, gives a guaranteed corroboration source for VERIFIED (independent of semgrep coverage, which returns 0). Maps ast-grep eval rule ids → code-injection. --- .../rule-tests/eval-code-injection-test.yml | 17 ++++++++++++++++ .../rules/js-ts-eval-code-injection.yml | 20 +++++++++++++++++++ .github/scripts/sigilix_sarif_contract.py | 7 +++++++ .github/scripts/sigilix_sarif_test.py | 10 ++++++++++ 4 files changed, 54 insertions(+) create mode 100644 .github/config/ast-grep-sigilix/rule-tests/eval-code-injection-test.yml create mode 100644 .github/config/ast-grep-sigilix/rules/js-ts-eval-code-injection.yml 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"(?