← all scripts

.github/scripts/run-semgrep.sh

14 of 14 statements covered (100.00%).

coveredmissednever traced by Bash (not counted)A line ending in … continues the statement above it and shares its fate.

1#!/bin/sh
2# =============================================================================
3# run-semgrep.sh — run semgrep with repo-wide rule suppressions from a file
4# =============================================================================
5#
6# The list of suppressed rule IDs (each with a justification) lives in
7# .github/config/semgrep-excluded-rules.txt
8# This script expands every non-comment, non-blank line into a repeated
9# `--exclude-rule <id>` argument and then runs `semgrep scan`. Keeping the IDs
10# in a version-controlled data file (the same posture as .trivyignore and
11# .pip-audit-ignore) means a suppression is reviewed as a data change rather
12# than hardwired into pipeline YAML, and every caller invokes this one script
13# instead of duplicating the flag list.
14#
15# Any arguments passed to this script are forwarded to `semgrep scan` ahead of
16# the scan target (the repository root).
17#
18# Usage:
19# sh .github/scripts/run-semgrep.sh
20# SEMGREP_EXCLUDE_RULES_FILE=/path/to/list sh .github/scripts/run-semgrep.sh
21#
22# POSIX sh on purpose: the semgrep container image is not guaranteed to ship
23# bash.
24# =============================================================================
259set -eu
26
27# Make path resolution independent of any inherited CDPATH (which would make
28# `cd` echo the resolved directory into the command substitution).
299unset CDPATH
30
31# Resolve the repository root from this script's own location (.github/scripts).
3236script_dir=$(cd -- "$(dirname -- "$0")" && pwd)
3327repo_root=$(cd -- "$script_dir/../.." && pwd)
349exclude_file="${SEMGREP_EXCLUDE_RULES_FILE:-$repo_root/.github/config/semgrep-excluded-rules.txt}"
35
36# Positional parameters ($@) accumulate any caller-supplied args first, then the
37# --exclude-rule flags read from the static config file. Each rule sits alone on
38# its line; `read` strips surrounding whitespace and the throwaway second field
39# absorbs any trailing inline comment, while the case skips blank/comment lines.
409if [ -f "$exclude_file" ]; then
4160 while read -r rule _ || [ -n "$rule" ]; do
4245 case "$rule" in
4338 '' | '#'*) continue ;;
44 esac
457 set -- "$@" --exclude-rule "$rule"
46 done < "$exclude_file"
477 echo "run-semgrep: applied rule suppressions from $exclude_file"
48else
492 echo "run-semgrep: no suppression file at $exclude_file (no rule excludes)"
50fi
51
529set -x
539exec semgrep scan --config auto --error "$@" --json -o semgrep-report.json .