Skip to content

cargo(deps): bump the logging group with 2 updates #48

cargo(deps): bump the logging group with 2 updates

cargo(deps): bump the logging group with 2 updates #48

Workflow file for this run

# Workflow: Security Audit and Maintenance
#
# This workflow runs automated security checks on a schedule to ensure
# the project remains secure over time. It checks for vulnerabilities
# in dependencies, outdated packages, and potential security issues.
name: Security Audit
# Trigger conditions: run on schedule and manual trigger
on:
# Run security audit every Monday at 9 AM UTC
schedule:
- cron: '0 9 * * 1'
# Allow manual triggering from GitHub Actions UI
workflow_dispatch:
# Also run on pushes to main branch for immediate security feedback
push:
branches: [ "main", "master" ]
# Run on pull requests to catch security issues early
pull_request:
branches: [ "main", "master" ]
# Define environment variables
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
# Define the security audit jobs
jobs:
# Job 1: Comprehensive security audit
security-audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Install Rust toolchain with Cargo.lock v4 support
- name: Install Rust toolchain
uses: dtolnay/[email protected]
# Step 3: Setup Rust caching
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
# Step 4: Install cargo-audit for vulnerability scanning
- name: Install cargo-audit
run: cargo install cargo-audit --locked
# Step 5: Run security audit
# This checks the Cargo.lock file against the RustSec Advisory Database
- name: Run cargo audit
run: |
echo "Running security audit..."
# Run audit and capture exit code
if cargo audit --json > audit-results.json 2>&1; then
audit_exit_code=0
else
audit_exit_code=$?
fi
# Display human-readable results
echo "Security audit results:"
cargo audit --ignore RUSTSEC-2023-0071 || true
# Check if the JSON file contains valid data
if [ -f "audit-results.json" ] && [ -s "audit-results.json" ]; then
# Check if vulnerabilities key exists and is an array
if jq -e '.vulnerabilities' audit-results.json >/dev/null 2>&1; then
vulnerabilities=$(jq '.vulnerabilities | length' audit-results.json 2>/dev/null || echo "0")
else
vulnerabilities=0
fi
if [ "$vulnerabilities" -gt 0 ]; then
echo "⚠️ Found $vulnerabilities vulnerabilities!"
# Only try to access advisory fields if they exist
jq -r '.vulnerabilities[]? | select(.advisory?) | {id: .advisory.id, title: .advisory.title, severity: .advisory.severity}' audit-results.json 2>/dev/null || echo "Could not parse vulnerability details"
else
echo "✅ No vulnerabilities found!"
fi
else
echo "⚠️ Audit results file is empty or missing"
echo '{"vulnerabilities": [], "warnings": []}' > audit-results.json
fi
# We ignore RUSTSEC-2023-0071 (RSA timing sidechannel) as it's a transitive dependency
# through sqlx-mysql with no current fix available and minimal risk for educational examples
if [ "$audit_exit_code" -ne 0 ] && [ "$vulnerabilities" -gt 0 ]; then
echo "Security audit found issues, but continuing due to ignored advisories"
fi
# Step 6: Check for yanked crates
# Yanked crates are packages that have been withdrawn by their authors
# Note: For educational examples, we continue even if yanked crates are found
- name: Check for yanked crates
run: |
echo "Checking for yanked crates..."
if cargo audit --deny yanked; then
echo "✅ No yanked crates found!"
else
echo "⚠️ Yanked crates detected (continuing for educational examples)"
echo " In production, consider updating to non-yanked versions"
cargo audit || true
fi
# Step 7: Upload audit results as artifact
- name: Upload audit results
if: always()
uses: actions/upload-artifact@v4
with:
name: security-audit-results
path: audit-results.json
retention-days: 30
# Job 2: Dependency review and analysis
dependency-analysis:
name: Dependency Analysis
runs-on: ubuntu-latest
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Install Rust toolchain
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
# Step 3: Setup Rust caching
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
# Step 4: Install cargo-tree for dependency analysis
- name: Install cargo-tree
run: cargo install cargo-tree --locked
# Step 5: Analyze dependency tree
# This shows the complete dependency graph to identify potential issues
- name: Analyze dependency tree
run: |
echo "Dependency tree analysis:"
cargo tree --format '{p} {l}' > dependency-tree.txt
# Show top-level dependencies
echo "Direct dependencies:"
cargo tree --depth 1
# Check for duplicate dependencies (can indicate version conflicts)
echo "Checking for duplicate dependencies:"
cargo tree --duplicates || echo "No duplicate dependencies found"
# Show dependencies with known security advisories
echo "Dependencies with advisories:"
cargo tree --format '{p}' | sort | uniq | while read dep; do
if cargo audit --json | jq -e ".vulnerabilities[] | select(.package.name == \"$dep\")" > /dev/null 2>&1; then
echo "⚠️ $dep has security advisories"
fi
done
# Step 6: Check for outdated dependencies
- name: Install cargo-outdated
run: cargo install cargo-outdated --locked
- name: Check for outdated dependencies
run: |
echo "Checking for outdated dependencies..."
cargo outdated --root-deps-only || echo "All dependencies are up to date"
# Step 7: Upload dependency analysis results
- name: Upload dependency analysis
if: always()
uses: actions/upload-artifact@v4
with:
name: dependency-analysis
path: dependency-tree.txt
retention-days: 30
# Job 3: License compliance check
license-check:
name: License Compliance
runs-on: ubuntu-latest
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Install Rust toolchain
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
# Step 3: Setup Rust caching
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
# Step 4: Install cargo-license for license checking
- name: Install cargo-license
run: cargo install cargo-license --locked
# Step 5: Check licenses of all dependencies
# This ensures we're compliant with dependency licenses
- name: Check dependency licenses
run: |
echo "Checking dependency licenses..."
cargo license --json > licenses.json
# Display license summary
echo "License summary:"
cargo license
# Check for potentially problematic licenses
echo "Checking for restrictive licenses..."
problematic_licenses=("GPL-3.0" "AGPL-3.0" "SSPL-1.0" "BSL-1.1")
for license in "${problematic_licenses[@]}"; do
if jq -e ".[] | select(.license == \"$license\")" licenses.json > /dev/null; then
echo "⚠️ Found potentially restrictive license: $license"
jq ".[] | select(.license == \"$license\") | {name: .name, license: .license}" licenses.json
fi
done
# Check for unknown licenses
if jq -e '.[] | select(.license == null or .license == "")' licenses.json > /dev/null; then
echo "⚠️ Found dependencies with unknown licenses:"
jq '.[] | select(.license == null or .license == "") | {name: .name, license: .license}' licenses.json
fi
# Step 6: Upload license information
- name: Upload license information
if: always()
uses: actions/upload-artifact@v4
with:
name: license-information
path: licenses.json
retention-days: 90
# Job 4: Code quality and security linting
security-linting:
name: Security Linting
runs-on: ubuntu-latest
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Install Rust toolchain with required components
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
# Step 3: Setup Rust caching
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
# Step 4: Run Clippy with security-focused lints
# These lints catch potential security issues in the code
# Note: Some lints are relaxed for educational examples
- name: Run security-focused Clippy lints
run: |
echo "Running security-focused Clippy lints..."
cargo clippy --all-targets --all-features -- \
-W clippy::arithmetic_side_effects \
-W clippy::panic \
-A clippy::unwrap_used \
-A clippy::expect_used \
-A clippy::indexing_slicing \
-A clippy::cast_possible_truncation \
-W clippy::cast_possible_wrap \
-W clippy::cast_precision_loss \
-W clippy::cast_sign_loss \
-W clippy::float_cmp \
-W clippy::float_cmp_const \
-W clippy::lossy_float_literal \
-W clippy::mem_forget \
-W clippy::mem_replace_with_uninit \
-W clippy::unimplemented \
-W clippy::unreachable \
--cap-lints warn
# Job 5: Supply chain security check
supply-chain:
name: Supply Chain Security
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Run GitHub's dependency review action
# This analyzes changes to dependencies in pull requests
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
# Fail on high severity vulnerabilities
fail-on-severity: high
# Comment on PRs with findings
comment-summary-in-pr: always
# Job 6: Create security report
security-report:
name: Generate Security Report
needs: [security-audit, dependency-analysis, license-check, security-linting]
runs-on: ubuntu-latest
if: always()
steps:
# Step 1: Check out the source code
- name: Checkout source code
uses: actions/checkout@v4
# Step 2: Download all artifacts
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: security-artifacts
# Step 3: Generate comprehensive security report
- name: Generate security report
run: |
echo "# Security Report for $(date)" > security-report.md
echo "" >> security-report.md
echo "## Repository Information" >> security-report.md
echo "- **Repository:** ${{ github.repository }}" >> security-report.md
echo "- **Branch:** ${{ github.ref_name }}" >> security-report.md
echo "- **Commit:** ${{ github.sha }}" >> security-report.md
echo "- **Date:** $(date)" >> security-report.md
echo "" >> security-report.md
echo "## Security Audit Results" >> security-report.md
if [ -f "security-artifacts/security-audit-results/audit-results.json" ]; then
# Check if the JSON file contains valid vulnerability data
if jq -e '.vulnerabilities' security-artifacts/security-audit-results/audit-results.json >/dev/null 2>&1; then
vulnerabilities=$(jq '.vulnerabilities | length' security-artifacts/security-audit-results/audit-results.json 2>/dev/null || echo "0")
echo "- **Vulnerabilities Found:** $vulnerabilities" >> security-report.md
if [ "$vulnerabilities" -gt 0 ]; then
echo "- **Status:** ⚠️ ATTENTION REQUIRED" >> security-report.md
echo "" >> security-report.md
echo "### Vulnerability Details" >> security-report.md
# Safely parse vulnerability details
if jq -e '.vulnerabilities[0].advisory' security-artifacts/security-audit-results/audit-results.json >/dev/null 2>&1; then
jq -r '.vulnerabilities[] | "- **" + .advisory.id + "**: " + .advisory.title + " (Severity: " + .advisory.severity + ")"' security-artifacts/security-audit-results/audit-results.json >> security-report.md 2>/dev/null || echo "- Unable to parse vulnerability details" >> security-report.md
else
echo "- Vulnerabilities found but details could not be parsed" >> security-report.md
fi
else
echo "- **Status:** ✅ CLEAN" >> security-report.md
fi
else
echo "- **Status:** ❓ INVALID AUDIT DATA FORMAT" >> security-report.md
fi
else
echo "- **Status:** ❓ AUDIT DATA NOT AVAILABLE" >> security-report.md
fi
echo "" >> security-report.md
echo "## License Compliance" >> security-report.md
if [ -f "security-artifacts/license-information/licenses.json" ]; then
echo "- **Total Dependencies:** $(jq '. | length' security-artifacts/license-information/licenses.json)" >> security-report.md
echo "- **Unique Licenses:** $(jq -r '.[].license' security-artifacts/license-information/licenses.json | sort | uniq | wc -l)" >> security-report.md
echo "- **Status:** ✅ ANALYZED" >> security-report.md
else
echo "- **Status:** ❓ LICENSE DATA NOT AVAILABLE" >> security-report.md
fi
echo "" >> security-report.md
echo "## Workflow Status Summary" >> security-report.md
echo "- **Security Audit:** ${{ needs.security-audit.result }}" >> security-report.md
echo "- **Dependency Analysis:** ${{ needs.dependency-analysis.result }}" >> security-report.md
echo "- **License Check:** ${{ needs.license-check.result }}" >> security-report.md
echo "- **Security Linting:** ${{ needs.security-linting.result }}" >> security-report.md
echo "" >> security-report.md
echo "---" >> security-report.md
echo "*Report generated by GitHub Actions Security Workflow*" >> security-report.md
# Step 4: Upload security report
- name: Upload security report
uses: actions/upload-artifact@v4
with:
name: security-report
path: security-report.md
retention-days: 90