Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/workflows/action-security-scan.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Runs the same CodeQL `actions` security query suite as Alphabet's Enterprise
# `Google GitHub Admin: Actions Workflow Security Scan` workflow on stacked PRs
# and backport PRs (`base != default_branch`), which the Enterprise ruleset
# does not trigger on unless the PR targets `main` (or belongs to a native
# GitHub Stack targeting `main`).

name: Actions Workflow Security Scan
on:
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
scan-pr:
name: Scan workflow files (stacked & backport PRs)
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.base_ref != github.event.repository.default_branch
steps:
- name: Checkout .github directory
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
sparse-checkout: .github
persist-credentials: false

- name: Create CodeQL query suite
run: |
cat <<'EOF' > actions-suite.qls
- qlpack: codeql/actions-queries
- include:
id: actions/envvar-injection/critical
- include:
id: actions/envpath-injection/critical
- include:
id: actions/cache-poisoning/poisonable-step
- include:
id: actions/artifact-poisoning/critical
- include:
id: actions/untrusted-checkout/critical
- include:
id: actions/untrusted-checkout/high
EOF

- name: Initialize CodeQL
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: actions
config: |
name: "Custom Action Scan"
disable-default-queries: true
queries:
- uses: ./actions-suite.qls

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
output: ../results
upload: never

- name: Check for vulnerabilities
run: |
SARIF_FILE="${RUNNER_WORKSPACE}/results/actions.sarif"
if [[ ! -f "$SARIF_FILE" ]]; then
echo "::error::SARIF file not found at ${SARIF_FILE}"
exit 1
fi
RESULT_COUNT=$(jq '.runs[0].results | length' "$SARIF_FILE")
if [[ "$RESULT_COUNT" -gt 0 ]]; then
echo "::error::CodeQL found ${RESULT_COUNT} potential workflow security vulnerabilities."
echo "---"
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"
exit 1
fi
echo "No vulnerabilities found. Check passed."
Loading