name: "Security Audit" on: push: branches: ["master", "main"] pull_request: branches: ["master", "main"] schedule: # Run every Monday at 08:00 UTC to catch newly disclosed CVEs - cron: "0 8 * * 1" jobs: # ── Rust dependency audit (cargo-audit) ────────────────────────────────────── # Skipped automatically when no Cargo.toml is present at repo root. rust-audit: name: Rust Security Audit runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout repository uses: actions/checkout@v4 - name: Check for Cargo.toml id: has_cargo run: | if [ -f Cargo.toml ]; then echo "present=true" >> "$GITHUB_OUTPUT" else echo "present=false" >> "$GITHUB_OUTPUT" echo "No Cargo.toml found — skipping Rust audit" fi - name: Install Rust stable if: steps.has_cargo.outputs.present == 'true' uses: dtolnay/rust-toolchain@stable - name: Cache cargo registry if: steps.has_cargo.outputs.present == 'true' uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git key: ${{ runner.os }}-cargo-audit-${{ hashFiles('**/Cargo.lock') }} - name: Install and run cargo-audit if: steps.has_cargo.outputs.present == 'true' run: | cargo install cargo-audit --locked cargo audit --deny warnings # ── Shell script security lint (ShellCheck) ─────────────────────────────────── # Fails only on errors (SC severity ≥ error). Warnings are reported but # do not block the build — keeping CI signal meaningful. shellcheck: name: ShellCheck runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run ShellCheck uses: ludeeus/action-shellcheck@2.0.0 with: severity: error scandir: "." ignore_paths: ".git"