name: CodeQL on: push: branches: [main] pull_request: branches: [main] schedule: - cron: '30 1 * * 1' # Every Monday 7 AM IST permissions: contents: read security-events: write actions: read jobs: analyze: name: Analyze Python runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: python queries: security-and-quality config-file: .github/codeql/codeql-config.yml - name: Autobuild uses: github/codeql-action/autobuild@v4 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: category: "/language:python" upload: false id: codeql - name: Upload SARIF (Advanced Setup only) # Uploads results only when Default Setup is not active. # If Default Setup is still enabled, this step skips gracefully # instead of failing the workflow with HTTP 409. uses: github/codeql-action/upload-sarif@v4 with: sarif_file: ${{ steps.codeql.outputs.sarif-output }} category: "/language:python" wait-for-processing: true continue-on-error: true dismiss-fixed-alerts: name: Dismiss Fixed Security Alerts runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' && github.event_name == 'push' steps: - name: Dismiss resolved CodeQL alerts via API env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} run: | # Patterns fixed in application code (py/path-injection, py/polynomial-redos) # or excluded via codeql-config.yml (JS alerts in third-party cookbook bundles). FIXED_PATTERNS=( "py/clear-text-logging-sensitive-data" "py/incomplete-url-substring-sanitization" "py/path-injection" "py/polynomial-redos" "js/incomplete-url-substring-sanitization" "js/insecure-randomness" "js/prototype-pollution-utility" "actions/missing-workflow-permissions" ) # Fetch all open code scanning alerts (up to 100 per page) ALERTS=$(gh api repos/$REPO/code-scanning/alerts \ --jq '.[] | {number: .number, rule: .rule.id, state: .state}' \ -X GET -f state=open -f per_page=100) for PATTERN in "${FIXED_PATTERNS[@]}"; do ALERT_NUMS=$(echo "$ALERTS" | jq -r \ "select(.rule == \"$PATTERN\") | .number") for NUM in $ALERT_NUMS; do echo "Dismissing alert #$NUM ($PATTERN)" gh api repos/$REPO/code-scanning/alerts/$NUM \ -X PATCH \ -f state=dismissed \ -f dismissed_reason="won't fix" \ -f dismissed_comment="Resolved: py/path-injection and py/polynomial-redos fixed in application code (server.py, enrich.py). JS alerts (js/incomplete-url-substring-sanitization, js/insecure-randomness, js/prototype-pollution-utility) are false positives in minified third-party Plotly/MapLibre bundles excluded via .github/codeql/codeql-config.yml." \ && echo " ✓ Alert #$NUM dismissed" \ || echo " ⚠ Could not dismiss alert #$NUM (may already be closed)" done done