Skip to content

Add Semgrep SAST to CI alongside CodeQL#210

Merged
Vishnu2707 merged 4 commits into
devfrom
feat/semgrep-sast-ci
Jul 18, 2026
Merged

Add Semgrep SAST to CI alongside CodeQL#210
Vishnu2707 merged 4 commits into
devfrom
feat/semgrep-sast-ci

Conversation

@ritiksah141

Copy link
Copy Markdown
Collaborator

Summary

Adds Semgrep as a second, open-source SAST layer in CI, running alongside the existing CodeQL workflow, which stays unchanged.

What changed

CI (Semgrep)

  • New sast-semgrep job in ci.yml: pure semgrep scan CLI (not semgrep ci, which is semgrep.dev integrated), public Registry rulesets (p/security-audit, p/owasp-top-ten, p/python, p/javascript), no account, no login, --metrics=off disables telemetry.
  • SARIF output uploaded to GitHub code scanning via the same pinned github/codeql-action/upload-sarif release already used by codeql.yml, so findings appear in Security → Code scanning alongside CodeQL's.
  • Wired into ci-summary the same way every other job is: needs array, env block, checks table, fail-gate condition.

Dockerfile

  • Semgrep's dockerfile.security.missing-user rule flagged the image running as root. Added a non-root openshield system user and switched USER before CMD. Required to make the new gate pass, not part of the original CI-wiring scope but necessary.

Docs

  • docs/ci-pipeline.md: new SAST (Semgrep) row in the jobs table, a new local-repro subsection, a tooling-decisions bullet explaining the account-free choice, and a fixing-common-failures row for nosemgrep suppression.
  • CHANGELOG.md: one-line entry under Unreleased/Added.

Why

GitHub's Code Quality preview product moves to paid general availability on July 20, 2026. It is a separate, admin-only Settings toggle, distinct from this repo's existing codeql.yml workflow, and disabling it needs org-admin access outside the scope of a PR (raised with the maintainer separately). Independent of that billing technicality, the maintainer's direction is to shift security tooling toward open source, so this adds Semgrep as a fully self-hosted, account-free SAST layer rather than touching CodeQL, which stays as is.

Notes for reviewers

  • p/secrets ruleset deliberately excluded. Gitleaks already owns secret detection in the secret-scan job, and adding a second, differently-tuned secrets ruleset on day one risks duplicate noise. Can be added later as its own decision.
  • No .semgrepignore added. Semgrep's built-in default ignores already cover node_modules/, dist/, build/, .venv/, test(s)/, and it auto-respects this repo's .gitignore (venv/ already excluded). The --exclude flags in the CI command are kept only for in-workflow visibility.
  • Two existing nosemgrep suppressions in scanner/nvd_client.py and scripts/render_deploy.py (added in a prior one-off Semgrep pass) still resolve correctly under the new ruleset combination, confirmed locally. They show up in the uploaded SARIF as suppressed findings, since the SARIF spec keeps suppressed results visible for audit trail, but they do not block the gate.

Local verification (all green)

Ran the exact CI command locally: semgrep scan --config p/security-audit --config p/owasp-top-ten --config p/python --config p/javascript --exclude venv --exclude frontend/node_modules --exclude frontend/dist --metrics=off --sarif --output semgrep.sarif --error .. Exit code 0 after the Dockerfile fix, with only the two pre-suppressed findings remaining. Dockerfile also checked with hadolint, no issues. Workflow YAML confirmed to parse with python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))".

Related issue

Closes #209


Files to review

File Why
.github/workflows/ci.yml New sast-semgrep job plus the three ci-summary wiring points
Dockerfile Non-root USER added to satisfy the new Semgrep gate
docs/ci-pipeline.md New job documented across five sections
CHANGELOG.md One-line entry

@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/github/codeql-action/upload-sarif 411c4c9a36b3fca4d674f06b6396b2c6d23522c6 UnknownUnknown

Scanned Files

  • .github/workflows/ci.yml

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@ritiksah141
ritiksah141 requested review from m-khan-97 and removed request for parthrohit22 July 17, 2026 17:21
m-khan-97
m-khan-97 previously approved these changes Jul 17, 2026

@m-khan-97 m-khan-97 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Clean addition and the job wiring is complete — sast-semgrep is added to the needs array, the env block, the summary table, and the final failure-gate condition, so a Semgrep finding will actually fail CI rather than being cosmetic. The continue-on-error: true + if: always() SARIF upload + explicit if: steps.semgrep.outcome == 'failure' gate is the correct pattern (upload happens even on findings; outcome reflects the pre-continue-on-error result). Pinning the registry rulesets explicitly (p/security-audit etc.) instead of --config auto to avoid the semgrep.dev account dependency is the right call, and --metrics=off is good hygiene.

Two notes, neither blocking:

  • This PR also adds a non-root USER openshield to the Dockerfile — a genuine improvement (and it partially addresses the container-hardening gap I raised on #185), but it's unrelated to "add Semgrep to CI." Fine to keep, just flagging that it's riding along so it's a conscious inclusion. pip install runs before the USER switch and /app is chowned, so it won't break the build.
  • Semgrep pulls the p/... rulesets from the registry at run time, so a registry outage fails the job. Acceptable for a SAST gate; worth knowing it's a network dependency if you ever see a spurious red.

Approving.

@ritiksah141

Copy link
Copy Markdown
Collaborator Author

Addressed both notes in 4adb350:

  • Added a one-line comment above the USER block in the Dockerfile pointing at fix(security): resolve Semgrep SAST findings #185, so the inclusion reads as conscious rather than incidental.
  • Added a tooling-decisions bullet in docs/ci-pipeline.md documenting that the p/... rulesets are pulled from the Semgrep Registry at run time, so a registry outage is the expected cause of a spurious red on that job.

No functional change, docs and a comment only.

@m-khan-97 m-khan-97 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving after the two follow-up commits (my earlier approval was auto-dismissed by the new pushes). The two new commits are documentation only — they add the Dockerfile hardening rationale and the Semgrep registry-dependency note, which addresses both non-blocking points from my first review. The functional diff (the sast-semgrep job wiring + the non-root USER openshield Dockerfile change) is byte-identical to what I already reviewed and what previously passed CI.

CI is re-running from the new commits (pending as I write this); merge is gated on it anyway. Approving on the code — good to merge once checks go green.

@Vishnu2707
Vishnu2707 merged commit 9d1dd96 into dev Jul 18, 2026
21 checks passed
@Vishnu2707
Vishnu2707 deleted the feat/semgrep-sast-ci branch July 18, 2026 00:30
@Vishnu2707

Vishnu2707 commented Jul 18, 2026

Copy link
Copy Markdown
Member

Merging this on priority, as the CODEQL has been disabled, thanks for the review @m-khan-97. Thanks to @ritiksah141 for quickly spinning this up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add Semgrep SAST to CI alongside CodeQL

4 participants