Repository navigation
chore(deps): bump github/codeql-action #299
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow is managed by gh actions-lock. | |
| # SPDX-License-Identifier: MPL-2.0 | |
| # This workflow is managed by gh actions-lock. | |
| # workflow-linter.yml - Validates GitHub workflows against RSR security standards | |
| # This workflow can be copied to other repos for consistent enforcement | |
| name: Workflow Security Linter | |
| on: | |
| push: | |
| paths: | |
| - '.github/workflows/**' | |
| pull_request: | |
| paths: | |
| - '.github/workflows/**' | |
| workflow_dispatch: | |
| permissions: | |
| actions: read | |
| contents: read | |
| jobs: | |
| lint-workflows: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7.0.1 | |
| - name: Check SPDX Headers | |
| run: | | |
| echo "=== Checking SPDX License Headers ===" | |
| failed=0 | |
| for file in .github/workflows/*.yml .github/workflows/*.yaml; do | |
| [ -f "$file" ] || continue | |
| # actions-lock may prepend its own comment. Require the licence | |
| # in the leading comment block, before the workflow body. | |
| if ! awk '/^# SPDX-License-Identifier:/ { found=1 } /^[^#[:space:]]/ { exit } END { exit !found }' "$file"; then | |
| echo "ERROR: $file missing SPDX header" | |
| failed=1 | |
| fi | |
| done | |
| if [ $failed -eq 1 ]; then | |
| echo "Add '# SPDX-License-Identifier: MPL-2.0' to the leading comment block" | |
| exit 1 | |
| fi | |
| echo "All workflows have SPDX headers" | |
| - name: Check Permissions Declaration | |
| run: | | |
| echo "=== Checking Permissions ===" | |
| failed=0 | |
| for file in .github/workflows/*.yml .github/workflows/*.yaml; do | |
| [ -f "$file" ] || continue | |
| if ! grep -q "^permissions:" "$file"; then | |
| echo "ERROR: $file missing top-level 'permissions:' declaration" | |
| failed=1 | |
| fi | |
| done | |
| if [ $failed -eq 1 ]; then | |
| echo "Add 'permissions: | |
| contents: read' at workflow level" | |
| exit 1 | |
| fi | |
| echo "All workflows have permissions declared" | |
| # actions.lock is verified by governance's lockfile check (standards | |
| # scripts/update-actions-lock.sh): one tested implementation, one | |
| # gh-actions-lock pin, and it accepts reusable-workflow coverage. The step | |
| # that stood here pinned its own v0.1.6 binary, which cannot read | |
| # lockfile v0.0.3, so it failed whenever a current tool wrote the lock. | |
| - name: Check for Duplicate Workflows | |
| run: | | |
| echo "=== Checking for Duplicates ===" | |
| # Known duplicate patterns | |
| if [ -f .github/workflows/codeql.yml ] && [ -f .github/workflows/codeql-analysis.yml ]; then | |
| echo "ERROR: Duplicate CodeQL workflows found" | |
| echo "Delete codeql-analysis.yml (keep codeql.yml)" | |
| exit 1 | |
| fi | |
| if [ -f .github/workflows/rust.yml ] && [ -f .github/workflows/rust-ci.yml ]; then | |
| echo "WARNING: Potential duplicate Rust workflows" | |
| echo "Consider consolidating rust.yml and rust-ci.yml" | |
| fi | |
| echo "No critical duplicates found" | |
| - name: Check CodeQL Language Matrix | |
| run: | | |
| echo "=== Checking CodeQL Configuration ===" | |
| if [ ! -f .github/workflows/codeql.yml ]; then | |
| echo "No CodeQL workflow found (optional)" | |
| exit 0 | |
| fi | |
| # Detect repo languages | |
| has_js=$(find . -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" -path "*/src/*" -o -path "*/lib/*" 2>/dev/null | head -1) | |
| has_py=$(find . -name "*.py" -path "*/src/*" -o -path "*/lib/*" 2>/dev/null | head -1) | |
| has_go=$(find . -name "*.go" -path "*/src/*" -o -path "*/cmd/*" -o -path "*/pkg/*" 2>/dev/null | head -1) | |
| has_rs=$(find . -name "*.rs" -path "*/src/*" 2>/dev/null | head -1) | |
| has_java=$(find . -name "*.java" -path "*/src/*" 2>/dev/null | head -1) | |
| has_rb=$(find . -name "*.rb" -path "*/lib/*" -o -path "*/app/*" 2>/dev/null | head -1) | |
| echo "Detected languages:" | |
| [ -n "$has_js" ] && echo " - javascript-typescript" | |
| [ -n "$has_py" ] && echo " - python" | |
| [ -n "$has_go" ] && echo " - go" | |
| [ -n "$has_rs" ] && echo " - rust (note: CodeQL rust is limited)" | |
| [ -n "$has_java" ] && echo " - java-kotlin" | |
| [ -n "$has_rb" ] && echo " - ruby" | |
| # Check for over-reach | |
| if grep -q "language:.*'go'" .github/workflows/codeql.yml && [ -z "$has_go" ]; then | |
| echo "WARNING: CodeQL configured for Go but no Go files found" | |
| fi | |
| if grep -q "language:.*'python'" .github/workflows/codeql.yml && [ -z "$has_py" ]; then | |
| echo "WARNING: CodeQL configured for Python but no Python files found" | |
| fi | |
| if grep -q "language:.*'java'" .github/workflows/codeql.yml && [ -z "$has_java" ]; then | |
| echo "WARNING: CodeQL configured for Java but no Java files found" | |
| fi | |
| if grep -q "language:.*'ruby'" .github/workflows/codeql.yml && [ -z "$has_rb" ]; then | |
| echo "WARNING: CodeQL configured for Ruby but no Ruby files found" | |
| fi | |
| echo "CodeQL check complete" | |
| - name: Check Secrets Guards | |
| run: | | |
| echo "=== Checking Secrets Usage ===" | |
| # Look for secrets without conditional guards in mirror workflows | |
| if [ -f .github/workflows/mirror.yml ]; then | |
| if grep -q "secrets\." .github/workflows/mirror.yml; then | |
| if ! grep -q "if:.*vars\." .github/workflows/mirror.yml; then | |
| echo "WARNING: mirror.yml uses secrets without vars guard" | |
| echo "Add 'if: vars.FEATURE_ENABLED == true' to jobs" | |
| fi | |
| fi | |
| fi | |
| echo "Secrets check complete" | |
| - name: Summary | |
| run: | | |
| echo "" | |
| echo "=== Workflow Linter Summary ===" | |
| echo "All critical checks passed." | |
| echo "" | |
| echo "For more info, see: robot-repo-bot/ERROR-CATALOG.scm" |