Skip to content

chore: add GitHub-standards CI (SAST, secret scan, tests, PR template) - #20

Merged
gavin09527 merged 2 commits into
mainfrom
chore/ci-sast-secret-test
Jul 20, 2026
Merged

chore: add GitHub-standards CI (SAST, secret scan, tests, PR template)#20
gavin09527 merged 2 commits into
mainfrom
chore/ci-sast-secret-test

Conversation

@gavin09527

Copy link
Copy Markdown
Collaborator

Summary

Bring the repo up to GitHub CI standards with PR-triggered workflows for automated testing, SAST, and secret scanning, plus a PR template. All tooling is free/OSS and token-free.

Changes

  • .github/workflows/test.yml — runs npm ci + npm test (node --test) on a node 20 & 22 matrix, on PRs to main and pushes to main.
  • .github/workflows/sast.yml — Semgrep OSS scan in the official semgrep/semgrep:1.150.0 container: semgrep scan --config auto --error --disable-version-check. No SEMGREP_APP_TOKEN, no semgrep ci (OSS mode only).
  • .github/workflows/secret-scan.yml — Gitleaks CLI via ghcr.io/gitleaks/gitleaks:v8.24.0 docker image with fetch-depth: 0: detect --source=/repo --redact --verbose --exit-code=1. No gitleaks-action, no GITLEAKS_LICENSE.
  • .github/pull_request_template.md — Summary / Changes / Testing / Security checklist / Reviewer sections.

Actions (actions/checkout, actions/setup-node) are pinned to the same full commit SHAs already used in release.yml, keeping the repo's immutable-supply-chain convention. Each workflow sets permissions: contents: read.

Testing

  • npm test passes locally (node --test)
  • CI is green (test matrix on node 20 & 22)

Security checklist

  • No secrets, tokens, or credentials committed — the Gitleaks secret scan is clean
  • Semgrep SAST is clean, OR any findings are false positives justified inline with // nosemgrep: <rule-id> (specific rule id, never a blanket suppression) and signed off by a reviewer

Reviewer

  • Approved by someone other than the last pusher (the repo ruleset requires a non-last-pusher approval)

gavin09527 and others added 2 commits July 20, 2026 15:07
Add PR-triggered GitHub Actions workflows and a PR template to bring the
repo up to standard CI hygiene:

- test.yml: run `npm test` on node 20 & 22 (PRs + pushes to main)
- sast.yml: Semgrep OSS scan (`semgrep scan --config auto --error`),
  free CLI in the official container, no app token / no `semgrep ci`
- secret-scan.yml: Gitleaks CLI via official docker image with full
  history, no gitleaks-action / no license required
- pull_request_template.md: summary, changes, testing, security, reviewer

Actions pinned to the same full commit SHAs already used in release.yml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The SAST gate this PR adds was red on 5 pre-existing findings. Resolve them
so the workflow's exact `semgrep scan --config auto --error` passes — a CI
baseline that ships red isn't a usable gate.

Real fix (2× yaml.github-actions.security.run-shell-injection):
- promote-dist-tag.yml: pass workflow_dispatch inputs via `env:` and reference
  them as shell vars ("$VERSION"/"$DIST_TAG") instead of inline ${{ inputs.* }}
  in `run:`. Inputs now reach the shell as data, never as script text.

Justified false positives (3× detect-non-literal-regexp), suppressed with a
rule-specific `// nosemgrep: <rule-id>` + reason (lead-approved, per policy):
- access-policy.js, mention.js, self-name-hydration.test.js: each builds its
  RegExp from an input already run through the canonical regex-metachar escape
  (`replace(/[.*+?^${}()|[\]\\]/g, '\\$&')`), so the pattern is a literal
  `@name` (+ fixed lookahead) — linear, no ReDoS. No blanket bypass; the whole
  scanner and ruleset stay active.

Verified: `semgrep scan --config auto --error` -> 0 findings; npm test 308/308.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@zylos-luna-coco zylos-luna-coco left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SOC2 CI baseline + expression-injection fix. Clean.

CI workflows:

  • SAST: Semgrep 1.150.0 in official container, OSS mode (no token, no semgrep ci), --error to fail on findings. Correct.
  • Secret scan: Gitleaks v8.24.0 via official docker image, full-history (fetch-depth: 0), --exit-code=1. Correct.
  • Tests: npm test on Node 20+22 matrix, fail-fast: false. Correct.
  • All three: permissions: contents: read, timeout-minutes set, actions pinned to full commit SHAs matching the repo's existing immutable-supply-chain convention.

promote-dist-tag.yml fix:
Moves ${{ inputs.version }} / ${{ inputs.dist_tag }} from inline shell to env: — closes the expression-injection surface I flagged in PR #16 review. Good to see it landed.

Semgrep suppressions (3 sites):
All three are detect-non-literal-regexp on new RegExp('@' + escaped, ...) where escaped is the result of .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') — metachar-escaped, so the pattern is linear (no ReDoS). Justified false positives, each with inline explanation + "Lead-approved" note.

PR template: Security checklist built in, matches hermes-openmax's.

LGTM.

@gavin09527
gavin09527 merged commit e29aa05 into main Jul 20, 2026
4 checks passed
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.

2 participants