fix(executor): re-verify parser.py integrity immediately before exec_module#281
fix(executor): re-verify parser.py integrity immediately before exec_module#281advikdivekar wants to merge 3 commits into
Conversation
…module The executor previously ran parser.py after only verifying it at plugin load time (startup). An attacker who could write to the plugin directory after startup could replace parser.py between the load-time check and the actual execution — a TOCTOU vulnerability leading to arbitrary code execution inside the server process. Changes: - plugins.py: add verify_parser_at_exec_time() — re-computes the plugin digest and compares it against the stored checksum using hmac.compare_digest immediately before exec_module is called; blocks execution if checksum is absent and enforce_plugin_signatures is on - executor.py: call verify_parser_at_exec_time() in _parse_results() before the importlib exec_module block; parser is skipped on failure - test_plugin_parser_rce.py: 7 new tests covering: checksum match allows, tampered parser blocked, no-checksum with enforcement on blocked, digest compute failure returns safe default, executor skips exec_module when check fails, executor calls exec_module when check passes Fixes utksh1#202 (plugin parser.py dynamically executed without runtime signature enforcement — RCE via TOCTOU).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a566dfdc4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if not plugin.checksum: | ||
| if settings.enforce_plugin_signatures: | ||
| logger.error( | ||
| "Refusing to execute parser for plugin %s: no checksum present " | ||
| "and signature enforcement is enabled", | ||
| plugin.id, | ||
| ) | ||
| return False |
There was a problem hiding this comment.
Allow signature-only plugins at parser exec time
verify_parser_at_exec_time() now rejects any plugin without plugin.checksum, but _verify_plugin_integrity() explicitly treats checksum and signature as alternative integrity mechanisms (it only fails enforcement when both are missing). In a deployment with enforce_plugin_signatures=True, a plugin that was validly loaded via signature verification (no checksum, signature present) will always have its custom parser skipped at runtime, creating a regression for hardened signature-based setups. The exec-time check should mirror load-time policy by accepting signature-verified plugins instead of hard-failing on missing checksum alone.
Useful? React with 👍 / 👎.
|
@utksh1 please review it and I have asked to claim few issues, please assign those issues to me under GSSoC 2026 |
|
@utksh1 all test passed now, please review it |
What is the problem
Closes #202
executor._parse_results()executedparser.pyviaimportlib.util.exec_module()after only verifying the file's integrity at plugin load time (server startup). This creates a TOCTOU (Time-of-Check-Time-of-Use) window:Any process or user with write access to the plugin directory (a misconfigured container, another compromised service, a path traversal elsewhere) could exploit this window.
What was changed
backend/secuscan/plugins.pyverify_parser_at_exec_time()— re-computes the plugin digest withcompute_plugin_digest()and compares it againstplugin.checksumusinghmac.compare_digestimmediately before execution. Blocks when checksum is absent andenforce_plugin_signaturesisTrue.backend/secuscan/executor.py_parse_results(), callverify_parser_at_exec_time()before theimportlibblock. If it returnsFalse, log and skip the parser rather than executing it.testing/backend/unit/test_plugin_parser_rce.pyexec_modulewhen check fails, executor callsexec_modulewhen check passesWhy this approach
hmac.compare_digestprevents timing oracle attacks on the checksum comparisonenforce_plugin_signatures=False— only blocked in hardened deployments where the operator has explicitly opted inHow to test
Edge cases covered
enforce_plugin_signatures=False→ allowed with warningenforce_plugin_signatures=True→ blockedparse()function → still blocked by digest mismatchVerification checklist
pytest testing/backend/— 245 passed (1 pre-existing failure intest_route_rejects_task_when_limiter_full)