Skip to content

Commit a9bba0a

Browse files
authored
Add codeql action scaning workflow (#34)
* Add action scaning workflow * comment google * better follow my own rules * Add custom scan list * Exclude file from linting due to conflicting lint rules
1 parent 5a4d22f commit a9bba0a

File tree

3 files changed

+133
-33
lines changed

3 files changed

+133
-33
lines changed
Lines changed: 92 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,98 @@
1-
### Required actions to scan GitHub action workflows for security issues.
2-
name: 'Scan GitHub Action workflows files for security issues'
1+
name: 'Google GitHub Admin: Actions Workflow Security Scan'
2+
33
on:
4-
pull_request: {}
4+
pull_request:
5+
paths:
6+
- '.github/workflows/**/*.yml'
7+
- '.github/workflows/**/*.yaml'
8+
- '.github/actions/**/*.yml'
9+
- '.github/actions/**/*.yaml'
10+
env:
11+
ACTIONS_SUITE_CONTENT: |
12+
- qlpack: codeql/actions-queries
13+
- include:
14+
id: actions/envvar-injection/critical
15+
- include:
16+
id: actions/envpath-injection/critical
17+
- include:
18+
id: actions/cache-poisoning/poisonable-step
19+
- include:
20+
id: actions/artifact-poisoning/critical
21+
- include:
22+
id: actions/untrusted-checkout/critical
23+
- include:
24+
id: actions/untrusted-checkout/high
25+
526
permissions:
627
contents: 'read'
7-
security-events: 'write'
8-
actions: 'read'
28+
actions: 'write' # Upload artifact
29+
930
jobs:
10-
semgrep:
11-
name: 'semgrep-oss/scan'
31+
scan-pr:
32+
permissions:
33+
contents: 'read'
34+
if: "github.event_name == 'pull_request'"
1235
runs-on: 'ubuntu-latest'
13-
container:
14-
image: 'index.docker.io/semgrep/semgrep@sha256:85782eaf09692e6dfb684cd3bad87ef315775814b01f76b4d15582e4ca7c1c89' # ratchet:semgrep/semgrep
15-
# Skip any PR created by dependabot to avoid permission issues:
16-
if: (github.actor != 'dependabot[bot]')
1736
steps:
18-
- name: 'Checkout Code'
19-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
20-
- name: 'Checkout Workflow Config'
21-
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
22-
env:
23-
GH_REPO_OWNER: ${{ github.repository_owner }}
24-
with:
25-
repository: 'google/github-team'
26-
path: action_scanning
27-
- name: 'Run Actions semgrep scan'
28-
run: 'semgrep scan --sarif --config action_scanning/semgrep-rules --config "p/github-actions"
29-
--sarif-output semgrep-results-actions.sarif || true'
30-
- name: 'Save Actions SARIF results as artifact'
31-
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
32-
with:
33-
name: 'semgrep-scan-results-actions'
34-
path: 'semgrep-results-actions.sarif'
35-
- name: 'Upload Actions SARIF result to the GitHub Security Dashboard'
36-
uses: 'github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841' # ratchet:github/codeql-action/upload-sarif@v3
37-
with:
38-
sarif_file: 'semgrep-results-actions.sarif'
39-
if: always()
37+
- name: 'Checkout PR Code'
38+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
39+
40+
- name: 'Check for Workflow Files'
41+
id: 'check_files'
42+
run: |
43+
FOUND_FILES=$(find . -type f -regextype posix-extended -regex '\./\.github/(workflows|actions)/.*\.ya?ml' | head -n 1)
44+
if [ -n "$FOUND_FILES" ]; then
45+
echo "workflow_files_found=true" >> "$GITHUB_OUTPUT"
46+
else
47+
echo "workflow_files_found=false" >> "$GITHUB_OUTPUT"
48+
fi
49+
50+
- name: 'Create CodeQL Query Suite'
51+
if: "steps.check_files.outputs.workflow_files_found == 'true'"
52+
run: 'echo "${{ env.ACTIONS_SUITE_CONTENT }}" > actions-suite.qls'
53+
54+
- name: 'Initialize CodeQL'
55+
if: "steps.check_files.outputs.workflow_files_found == 'true'"
56+
uses: 'google/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db' # ratchet:google/codeql-action/init@v4
57+
with:
58+
languages: 'actions'
59+
config: |
60+
name: 'Custom Action Scan'
61+
disable-default-queries: true
62+
queries:
63+
- uses: ./actions-suite.qls
64+
65+
- name: 'Perform CodeQL Analysis'
66+
if: "steps.check_files.outputs.workflow_files_found == 'true'"
67+
id: 'codeql_analysis'
68+
uses: 'google/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db' # ratchet:google/codeql-action/analyze@v4
69+
with:
70+
upload: 'never'
71+
72+
- name: 'Check for Vulnerabilities and Set Status'
73+
id: 'vuln_check'
74+
if: "steps.check_files.outputs.workflow_files_found == 'true'"
75+
run: |
76+
SARIF_FILE="${{ steps.codeql_analysis.outputs.sarif-output }}/actions.sarif"
77+
if [ ! -f "$SARIF_FILE" ]; then
78+
echo "SARIF file not found at $SARIF_FILE"
79+
exit 1
80+
fi
81+
RESULT_COUNT=$(jq '.runs[0].results | length' "$SARIF_FILE")
82+
if [ "$RESULT_COUNT" -gt 0 ]; then
83+
echo "::error::CodeQL found $RESULT_COUNT potential vulnerabilities."
84+
echo "---"
85+
jq -r '.runs[0].results[] | ("Rule ID: " + .ruleId + "\nMessage: " + .message.text + "\nFile: " + .locations[0].physicalLocation.artifactLocation.uri + "\nLine: " + (.locations[0].physicalLocation.region.startLine | tostring) + "\n---")' "$SARIF_FILE"
86+
exit 1
87+
else
88+
echo "No vulnerabilities found. Check passed."
89+
fi
90+
91+
- name: 'Upload SARIF file on failure'
92+
if: "failure() && steps.vuln_check.conclusion == 'failure'"
93+
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
94+
with:
95+
name: 'sarif-report'
96+
path: '${{ steps.codeql_analysis.outputs.sarif-output }}/actions.sarif'
97+
retention-days: 1
98+
overwrite: 'true'
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
### Required actions to scan GitHub action workflows for security issues.
2+
name: 'Scan GitHub Action workflows files for security issues'
3+
on:
4+
pull_request: {}
5+
permissions:
6+
contents: 'read'
7+
security-events: 'write'
8+
actions: 'read'
9+
jobs:
10+
semgrep:
11+
name: 'semgrep-oss/scan'
12+
runs-on: 'ubuntu-latest'
13+
container:
14+
image: 'index.docker.io/semgrep/semgrep@sha256:85782eaf09692e6dfb684cd3bad87ef315775814b01f76b4d15582e4ca7c1c89' # ratchet:semgrep/semgrep
15+
# Skip any PR created by dependabot to avoid permission issues:
16+
if: (github.actor != 'dependabot[bot]')
17+
steps:
18+
- name: 'Checkout Code'
19+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
20+
- name: 'Checkout Workflow Config'
21+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
22+
env:
23+
GH_REPO_OWNER: ${{ github.repository_owner }}
24+
with:
25+
repository: 'google/github-team'
26+
path: action_scanning
27+
- name: 'Run Actions semgrep scan'
28+
run: 'semgrep scan --sarif --config action_scanning/semgrep-rules --config "p/github-actions"
29+
--sarif-output semgrep-results-actions.sarif || true'
30+
- name: 'Save Actions SARIF results as artifact'
31+
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
32+
with:
33+
name: 'semgrep-scan-results-actions'
34+
path: 'semgrep-results-actions.sarif'
35+
- name: 'Upload Actions SARIF result to the GitHub Security Dashboard'
36+
uses: 'github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841' # ratchet:github/codeql-action/upload-sarif@v3
37+
with:
38+
sarif_file: 'semgrep-results-actions.sarif'
39+
if: always()

.yamlfmt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
formatter:
22
max_line_length: 100
33
trim_trailing_whitespace: true
4+
exclude:
5+
- .github/workflows/action_scanning.yml

0 commit comments

Comments
 (0)