name: Security
on:
schedule:
- cron: '0 2 * * 1' push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ubuntu-latest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Run security audit
run: cargo audit --json > audit-results.json || true
- name: Display audit results
run: |
if [ -f audit-results.json ]; then
echo "Security audit results:"
cat audit-results.json | jq -r '.vulnerabilities[] | "\(.advisory.id): \(.advisory.title) (\(.advisory.severity))"' || echo "No vulnerabilities found"
fi
- name: Upload audit results
uses: actions/upload-artifact@v6
if: always()
with:
name: security-audit-results
path: audit-results.json
dependency-check:
name: Dependency Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ubuntu-latest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install cargo-deny
run: cargo install cargo-deny
- name: Create deny.toml if not exists
run: |
if [ ! -f deny.toml ]; then
cat > deny.toml << 'EOF'
[bans]
multiple-versions = "warn"
wildcards = "deny"
[licenses]
copyleft = "deny"
allow-osi-fsf-free = "neither"
default = "deny"
allow = [
"Apache-2.0",
"MIT",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
]
[advisories]
vulnerability = "deny"
unmaintained = "warn"
yanked = "warn"
notice = "warn"
[sources]
unknown-registry = "warn"
unknown-git = "warn"
EOF
fi
- name: Run cargo deny
run: cargo deny check --hide-inclusion-graph
- name: Check for unused dependencies
run: |
cargo install cargo-machete
cargo machete --with-metadata || true
supply-chain:
name: Supply Chain Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ubuntu-latest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check for suspicious dependencies
run: |
echo "Checking for suspicious dependencies..."
cargo tree --duplicates || true
echo "Checking for potential typosquatting..."
cargo tree --format "{p}" | grep -E "(reqwest|serde|tokio|clap)" | sort | uniq -c | sort -nr
- name: Verify Cargo.lock is up to date
run: |
cargo generate-lockfile
if ! git diff --exit-code Cargo.lock; then
echo "Cargo.lock is not up to date!"
exit 1
fi
- name: Check for overly broad feature flags
run: |
echo "Checking for overly broad feature flags..."
grep -n "features.*=.*\[.*\]" Cargo.toml || true