Security and Dependencies #783
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security and Dependencies | |
| on: | |
| schedule: | |
| # Run at 2 AM UTC every day | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| push: | |
| paths: | |
| - '**/Cargo.toml' | |
| - '**/Cargo.lock' | |
| - '**/*.csproj' | |
| - 'sdks/typescript/package-lock.json' | |
| - 'sdks/python/pyproject.toml' | |
| - '.cargo/audit.toml' | |
| - '.github/workflows/security.yml' | |
| permissions: | |
| contents: read | |
| issues: write | |
| jobs: | |
| rust-security: | |
| name: Rust Security Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| key: ${{ runner.os }}-cargo-audit-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-audit- | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit --locked --force | |
| - name: Run security audit | |
| run: cargo audit | |
| - name: Create issue for vulnerabilities | |
| if: failure() | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const title = '🚨 Security vulnerabilities found in Rust dependencies'; | |
| const body = `Security audit failed. Please check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. | |
| Run \`cargo audit\` locally to see the vulnerabilities.`; | |
| // Check if issue already exists | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| labels: ['security', 'dependencies'], | |
| state: 'open' | |
| }); | |
| const existingIssue = issues.data.find(issue => issue.title === title); | |
| if (!existingIssue) { | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['security', 'dependencies', 'rust'] | |
| }); | |
| } | |
| rust-outdated: | |
| name: Check Outdated Rust Dependencies | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install cargo-outdated | |
| run: | | |
| cargo install cargo-outdated --locked || true | |
| - name: Check outdated dependencies | |
| id: outdated | |
| run: | | |
| echo "## Outdated Rust Dependencies" >> outdated.md | |
| echo '```' >> outdated.md | |
| cargo outdated --root-deps-only >> outdated.md || true | |
| echo '```' >> outdated.md | |
| # Also check workspace members | |
| echo "## Workspace Members" >> outdated.md | |
| echo '```' >> outdated.md | |
| cargo outdated --workspace >> outdated.md || true | |
| echo '```' >> outdated.md | |
| - name: Upload outdated report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rust-outdated-report | |
| path: outdated.md | |
| retention-days: 3 | |
| dotnet-security: | |
| name: .NET Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Restore dependencies | |
| working-directory: sdks/csharp | |
| run: dotnet restore | |
| - name: Run .NET security scan | |
| working-directory: sdks/csharp | |
| run: | | |
| dotnet list package --vulnerable --include-transitive > vulnerable.txt | |
| if grep -q "has the following vulnerable packages" vulnerable.txt; then | |
| echo "Vulnerable packages found!" | |
| cat vulnerable.txt | |
| exit 1 | |
| else | |
| echo "No vulnerable packages found." | |
| fi | |
| - name: Check for outdated packages | |
| working-directory: sdks/csharp | |
| run: | | |
| echo "## Outdated .NET Packages" >> $GITHUB_STEP_SUMMARY | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| dotnet list package --outdated >> $GITHUB_STEP_SUMMARY || true | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| npm-security: | |
| name: npm Security Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: sdks/typescript/package-lock.json | |
| - name: Install dependencies | |
| working-directory: sdks/typescript | |
| run: npm ci | |
| - name: Run npm audit | |
| working-directory: sdks/typescript | |
| run: npm audit --audit-level=moderate | |
| - name: Check outdated packages | |
| working-directory: sdks/typescript | |
| run: | | |
| echo "## Outdated npm Packages" >> $GITHUB_STEP_SUMMARY | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| npm outdated >> $GITHUB_STEP_SUMMARY || true | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| python-security: | |
| name: Python SDK Security Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Install pip-audit | |
| run: pip install pip-audit | |
| - name: Verify Python SDK is dependency-free | |
| run: | | |
| if [ -f sdks/python/requirements.txt ]; then | |
| echo "Checking requirements.txt for vulnerabilities..." | |
| pip-audit -r sdks/python/requirements.txt | |
| else | |
| echo "No requirements.txt — Python SDK has no external dependencies (expected)." | |
| fi | |
| - name: Check pyproject.toml for dependencies | |
| run: | | |
| python3 -c " | |
| import tomllib, sys | |
| with open('sdks/python/pyproject.toml', 'rb') as f: | |
| data = tomllib.load(f) | |
| deps = data.get('project', {}).get('dependencies', []) | |
| if deps: | |
| print(f'WARNING: Python SDK has {len(deps)} dependencies: {deps}') | |
| print('The Python SDK should remain dependency-free (ctypes only).') | |
| sys.exit(1) | |
| else: | |
| print('Python SDK is dependency-free (as expected).') | |
| " | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@v5 | |
| with: | |
| fail-on-severity: moderate | |
| deny-licenses: GPL-3.0, AGPL-3.0 | |
| create-summary: | |
| name: Create Security Summary | |
| needs: [rust-security, rust-outdated, dotnet-security, npm-security, python-security] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Download outdated report | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: rust-outdated-report | |
| path: . | |
| continue-on-error: true | |
| - name: Create summary | |
| run: | | |
| echo "# Security and Dependency Check Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "## Status" >> $GITHUB_STEP_SUMMARY | |
| echo "- Rust Security: ${{ needs.rust-security.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Rust Outdated: ${{ needs.rust-outdated.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- .NET Security: ${{ needs.dotnet-security.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- npm Security: ${{ needs.npm-security.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Python Security: ${{ needs.python-security.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ -f outdated.md ]; then | |
| cat outdated.md >> $GITHUB_STEP_SUMMARY | |
| fi |