feat(SIG-107): add OpenGrep and Brakeman runner tools - #30
Conversation
Sigilix OverviewEffort: 4/5 (large) Quality gates
Summary — latest pushAdds OpenGrep and Brakeman as default-on SAST runner tools, with version/SHA-pinned binary and gem fetching, config validation, Rails root discovery with path-traversal protection, and SARIF path normalization for nested monorepo roots. Both tools are wired into scan.yml, registered in the manifest and SARIF contract, and covered by targeted tests that verify workflow wiring, manifest rows, metadata IDs, Brakeman path normalization, and wrapper hardening. Important files
Sequence diagramsequenceDiagram
participant WF as scan.yml
participant OG as run_opengrep.sh
participant BK as run_brakeman.sh
participant NM as brakeman_sarif_paths.py
participant MG as sigilix_sarif_merge.py
participant CT as sigilix_sarif_contract.py
WF->>OG: OPENGREP_ENABLED, OPENGREP_CONFIG
OG->>OG: Download & verify binary
OG->>OG: Scan source
OG->>CT: Normalize opengrep.sarif
WF->>BK: BRAKEMAN_ENABLED
BK->>BK: discover_rails_roots
BK->>BK: Fetch & verify gems
loop For each Rails root
BK->>BK: Run Brakeman scan
BK->>NM: Normalize paths with root prefix
end
alt Multiple roots
BK->>MG: Merge normalized SARIF files
end
BK->>CT: Normalize brakeman.sarif
Confidence: 4/5Both runners use SHA256-verified downloads, non-fatal error handling, and path-traversal protection with targeted tests, though the Brakeman multi-root merge and OpenGrep config parsing edge cases warrant careful review.
Suggested labels: |
📝 WalkthroughWalkthroughThis PR integrates OpenGrep and Brakeman security SAST tools into the scan workflow. It adds tool manifest entries, implements runner scripts with pinned versions and SHA256 verification, configures SARIF normalization and output merging, and extends test coverage to validate workflow wiring and script integrity. ChangesOpenGrep and Brakeman SAST Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Responding to the Sigilix overview notes:
Validation for this commit: full runner Python test/compile gate, |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/scripts/run_opengrep.sh:
- Around line 31-56: The parser in parse_opengrep_configs uses IFS=',' read -r
-a config_items which drops a trailing empty field (so "p/security-audit,"
bypasses the empty-rule check); fix by making the split preserve trailing
empties (for example, change the read to operate on "${OPENGREP_CONFIG}," e.g.
IFS=',' read -r -a config_items <<< "${OPENGREP_CONFIG}," so a terminal comma
produces an empty element to be caught by the existing trimmed empty check),
keep using the same trimming and validation logic on each item (symbols:
parse_opengrep_configs, config_items, trimmed, config_args).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 70f847b3-84c6-4030-a9ef-86205221ff6b
📒 Files selected for processing (10)
.github/config/tool-manifest.json.github/scripts/brakeman_sarif_paths.py.github/scripts/run_brakeman.sh.github/scripts/run_opengrep.sh.github/scripts/security_sast_tools_workflow_test.py.github/scripts/sigilix_sarif_contract.py.github/scripts/sigilix_sarif_test.py.github/workflows/ci.yml.github/workflows/scan.ymlREADME.md
| parse_opengrep_configs() { | ||
| local item | ||
| local trimmed | ||
| IFS=',' read -r -a config_items <<< "$OPENGREP_CONFIG" | ||
| for item in "${config_items[@]}"; do | ||
| trimmed="${item#"${item%%[![:space:]]*}"}" | ||
| trimmed="${trimmed%"${trimmed##*[![:space:]]}"}" | ||
| if [ -z "$trimmed" ]; then | ||
| echo "::warning::OpenGrep config contains an empty ruleset - manifest will record missing output." | ||
| return 1 | ||
| fi | ||
| if [[ "$trimmed" == -* ]]; then | ||
| echo "::warning::OpenGrep config '$trimmed' must not start with '-' - manifest will record missing output." | ||
| return 1 | ||
| fi | ||
| if [[ ! "$trimmed" =~ ^[A-Za-z0-9._/@-]+$ ]]; then | ||
| echo "::warning::OpenGrep config '$trimmed' contains unsupported characters - manifest will record missing output." | ||
| return 1 | ||
| fi | ||
| config_args+=(--config "$trimmed") | ||
| done | ||
| if [ "${#config_args[@]}" -eq 0 ]; then | ||
| echo "::warning::OpenGrep config is empty - manifest will record missing output." | ||
| return 1 | ||
| fi | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
OPENGREP_CONFIG='p/security-audit,'
IFS=',' read -r -a config_items <<< "$OPENGREP_CONFIG"
printf 'items=%s\n' "${`#config_items`[@]}"
for item in "${config_items[@]}"; do
printf '<%s>\n' "$item"
doneRepository: Sigilix/runner
Length of output: 85
Reject trailing empty OpenGrep rulesets too
IFS=',' read -r -a config_items <<< "$OPENGREP_CONFIG" drops a terminal empty field: with OPENGREP_CONFIG='p/security-audit,' the parser sees only one element (<p/security-audit>) and never hits the -z "$trimmed" rejection. This bypasses the “empty ruleset” validation contract for trailing-comma input.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/scripts/run_opengrep.sh around lines 31 - 56, The parser in
parse_opengrep_configs uses IFS=',' read -r -a config_items which drops a
trailing empty field (so "p/security-audit," bypasses the empty-rule check); fix
by making the split preserve trailing empties (for example, change the read to
operate on "${OPENGREP_CONFIG}," e.g. IFS=',' read -r -a config_items <<<
"${OPENGREP_CONFIG}," so a terminal comma produces an empty element to be caught
by the existing trimmed empty check), keep using the same trimming and
validation logic on each item (symbols: parse_opengrep_configs, config_items,
trimmed, config_args).
What
Adds the next SIG-107 runner batch in one PR:
opengrepdefault-on workflow input plusopengrep-configruleset input.brakemandefault-on workflow input for detected Rails apps.scan.ymlunder the 1k-line cap.Why
This makes two more high-signal CodeRabbit-style tools available to Sigilix evidence ingestion today: OpenGrep for broad SAST recall, and Brakeman for Rails-specific security findings.
Hardening
-, and unsupported characters.--norc --clear-sources, SHA256 verified, then installed locally from verified.gemfiles.SOURCE_DIR.Verification
PYTHONPATH=.github/scripts python3 -m unittest security_sast_tools_workflow_test sigilix_sarif_testpython3 .github/scripts/sigilix_sarif_test.pypython3 .github/scripts/eslint_ts_workflow_test.pypython3 .github/scripts/tsc_workflow_test.pypython3 .github/scripts/pylint_workflow_test.pypython3 .github/scripts/trufflehog_converter_test.pypython3 .github/scripts/language_config_tools_workflow_test.pypython3 .github/scripts/knip_workflow_test.pypython3 .github/scripts/biome_workflow_test.pypython3 .github/scripts/docs_config_tools_test.pypython3 .github/scripts/oxlint_workflow_test.pypython3 .github/scripts/ast_grep_workflow_test.pypython3 .github/scripts/policy_iac_tools_workflow_test.pypython3 .github/scripts/security_sast_tools_workflow_test.pypython3 -m py_compile .github/scripts/*.pybash -n .github/scripts/run_opengrep.sh .github/scripts/run_brakeman.shactionlintv1.7.12 macOS binary: clean.git diff --check.github/workflows/scan.ymlat 997 lines.Reviewer sign-off
design-critic: CHANGE-FIRST initially; adjusted design to avoid Brakeman caller config inheritance and reduce default-on install cost via Rails detection.security-auditor: SHIP after final hardening; no concrete exploitable blockers found.code-reviewer: SHIP after final hardening; no true blockers found.Summary by CodeRabbit
New Features
p/security-audit,p/owasp-top-ten)Documentation