cc-audit 3.11.6

Security auditor for Claude Code skills, hooks, and MCP servers
Documentation
name: Security

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    # Run weekly on Monday at 00:00 UTC
    - cron: '0 0 * * 1'

permissions:
  contents: read
  checks: write
  pull-requests: write

env:
  CARGO_TERM_COLOR: always

jobs:
  changes:
    name: Detect Changes
    runs-on: ubuntu-latest
    outputs:
      rust: ${{ steps.filter.outputs.rust }}
      should_run: ${{ github.event_name == 'schedule' || steps.filter.outputs.rust == 'true' }}
    steps:
      - uses: actions/checkout@v7
      - uses: dorny/paths-filter@v4
        id: filter
        if: github.event_name != 'schedule'
        with:
          filters: |
            rust:
              - 'src/**'
              - 'Cargo.toml'
              - 'Cargo.lock'
              - 'deny.toml'
              - 'supply-chain/**'

  audit:
    name: Security Audit
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - name: Install cargo-audit
        run: cargo install cargo-audit --locked

      - name: Run cargo-audit
        run: cargo audit

  deny:
    name: Dependency Check
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - uses: EmbarkStudios/cargo-deny-action@v2
        with:
          command: check all

  supply-chain:
    name: Supply Chain Security
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - uses: dtolnay/rust-toolchain@stable

      - name: Install cargo-vet
        run: cargo install cargo-vet --locked

      - name: Check supply chain
        run: cargo vet --locked || echo "::warning::Supply chain audit incomplete - run 'cargo vet' locally to complete"

  advisory-db:
    name: Advisory Database
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - uses: rustsec/audit-check@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

  outdated:
    name: Outdated Dependencies
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - uses: dtolnay/rust-toolchain@stable

      - name: Install cargo-outdated
        run: cargo install cargo-outdated --locked

      - name: Check outdated dependencies
        run: |
          echo "## Outdated Dependencies" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
          cargo outdated --root-deps-only 2>&1 | tee -a $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY

  security-result:
    name: Security Result
    needs: [changes, audit, deny, supply-chain, advisory-db, outdated]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Check results
        run: |
          if [[ "${{ needs.changes.outputs.should_run }}" != "true" ]]; then
            echo "No relevant changes detected, skipping security checks"
            exit 0
          fi
          if [[ "${{ needs.audit.result }}" == "failure" || \
                "${{ needs.deny.result }}" == "failure" || \
                "${{ needs.supply-chain.result }}" == "failure" || \
                "${{ needs.advisory-db.result }}" == "failure" || \
                "${{ needs.outdated.result }}" == "failure" ]]; then
            echo "One or more security jobs failed"
            exit 1
          fi
          echo "All security checks passed"