chore: release v0.7.0 #304
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
| # security.yml — Security scanning pipeline for langgraph-agent-stack | |
| # | |
| # Jobs: | |
| # secrets-scan — gitleaks: detect secrets and credentials committed to the repo | |
| # dependency-audit — pip-audit: identify known CVEs in Python dependencies | |
| # sast — bandit: static application security testing for Python code | |
| # image-scan — syft SBOM + trivy container vulnerability scan | |
| # | |
| # Triggers: | |
| # push / pull_request — on every change to the main branch | |
| # schedule — weekly full scan every Monday at 06:00 UTC | |
| # | |
| # All scan results are uploaded as artifacts and retained for 30 days. | |
| # The dependency-audit and sast jobs produce SARIF output when available so | |
| # results can be reviewed in the GitHub Security tab. | |
| name: Security Scanning | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| schedule: | |
| # Every Monday at 06:00 UTC — catches newly disclosed CVEs between PRs | |
| - cron: "0 6 * * 1" | |
| permissions: | |
| contents: read | |
| security-events: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| PYTHON_VERSION: "3.12" | |
| UV_VERSION: "0.11.18" | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| # --------------------------------------------------------------------------- | |
| # Job 1 — Secrets scanning with gitleaks | |
| # --------------------------------------------------------------------------- | |
| jobs: | |
| secrets-scan: | |
| name: Secrets Scan (gitleaks) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout source (full history for gitleaks) | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| # Fetch the complete git history so gitleaks can scan all commits, | |
| # not just the files present in the working tree. | |
| fetch-depth: 0 | |
| - name: Run gitleaks | |
| uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # GITLEAKS_LICENSE is required for use in private repositories. | |
| # For public repos this environment variable can be omitted. | |
| # GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| # gitleaks-action writes a SARIF report when findings exist. | |
| # Upload it so the results surface in the GitHub Security tab. | |
| - name: Upload gitleaks SARIF report | |
| uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 | |
| if: always() | |
| with: | |
| sarif_file: results.sarif | |
| continue-on-error: true # File may not exist when there are no findings | |
| - name: Upload gitleaks report artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: gitleaks-report | |
| path: results.sarif | |
| retention-days: 30 | |
| if-no-files-found: ignore | |
| # --------------------------------------------------------------------------- | |
| # Job 2 — Dependency audit with pip-audit | |
| # --------------------------------------------------------------------------- | |
| dependency-audit: | |
| name: Dependency Audit (pip-audit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 (SHA verified) | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| run: uv python install ${{ env.PYTHON_VERSION }} | |
| - name: Cache uv dependencies | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/uv | |
| key: uv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('pyproject.toml', 'uv.lock') }} | |
| restore-keys: | | |
| uv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install production dependencies | |
| # Install only production deps to audit what actually ships in the image. | |
| # pip-audit is added as a temporary tool install, not a project dependency. | |
| run: uv sync --frozen --no-dev --extra anthropic | |
| - name: Install pip-audit | |
| run: uv tool install pip-audit | |
| - name: Run pip-audit (JSON output) | |
| # --require-hashes is skipped because uv lockfiles handle integrity. | |
| # Fail the job on any found vulnerability (exit code != 0). | |
| run: | | |
| uv tool run pip-audit \ | |
| --format json \ | |
| --output pip-audit-report.json \ | |
| --progress-spinner off \ | |
| --ignore-vuln PYSEC-2024-278 | |
| continue-on-error: true # Always upload the report even on findings | |
| - name: Run pip-audit (human-readable summary) | |
| run: | | |
| uv tool run pip-audit \ | |
| --format columns \ | |
| --progress-spinner off \ | |
| --ignore-vuln PYSEC-2024-278 | |
| continue-on-error: true | |
| - name: Upload pip-audit report | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: pip-audit-report | |
| path: pip-audit-report.json | |
| retention-days: 30 | |
| if-no-files-found: ignore | |
| - name: Fail on vulnerabilities | |
| # Re-run in strict mode after uploading the artifact so the job | |
| # status reflects real findings. The artifact is preserved regardless. | |
| run: | | |
| uv tool run pip-audit \ | |
| --format columns \ | |
| --progress-spinner off \ | |
| --ignore-vuln PYSEC-2024-278 | |
| # --------------------------------------------------------------------------- | |
| # Job 3 — Python SAST with bandit | |
| # --------------------------------------------------------------------------- | |
| sast: | |
| name: SAST (bandit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 (SHA verified) | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| run: uv python install ${{ env.PYTHON_VERSION }} | |
| - name: Install bandit | |
| run: uv tool install "bandit[sarif]" | |
| - name: Run bandit (SARIF output for GitHub Security tab) | |
| run: | | |
| uv tool run bandit \ | |
| --recursive \ | |
| --format sarif \ | |
| --output bandit-results.sarif \ | |
| --severity-level medium \ | |
| --confidence-level medium \ | |
| --exclude ".venv,tests" \ | |
| api/ core/ agents/ pack_kernel/ domain_packs/ connectors/ control_plane/ | |
| continue-on-error: true # Always upload results even when findings exist | |
| - name: Run bandit (human-readable summary for log output) | |
| run: | | |
| uv tool run bandit \ | |
| --recursive \ | |
| --format screen \ | |
| --severity-level medium \ | |
| --confidence-level medium \ | |
| --exclude ".venv,tests" \ | |
| api/ core/ agents/ pack_kernel/ domain_packs/ connectors/ control_plane/ | |
| continue-on-error: true | |
| - name: Upload bandit SARIF to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 | |
| if: always() | |
| with: | |
| sarif_file: bandit-results.sarif | |
| continue-on-error: true # Requires Advanced Security on private repos | |
| - name: Upload bandit SARIF artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: bandit-sarif-report | |
| path: bandit-results.sarif | |
| retention-days: 30 | |
| if-no-files-found: ignore | |
| - name: Fail on high/critical findings | |
| # Re-run at HIGH severity to gate the job. Medium findings are | |
| # surfaced in the artifact but do not block merging. | |
| run: | | |
| uv tool run bandit \ | |
| --recursive \ | |
| --format screen \ | |
| --severity-level high \ | |
| --confidence-level high \ | |
| --exclude ".venv,tests" \ | |
| api/ core/ agents/ pack_kernel/ domain_packs/ connectors/ control_plane/ | |
| # --------------------------------------------------------------------------- | |
| # Job 4 — SBOM generation (Syft) + container vulnerability scan (Trivy) | |
| # --------------------------------------------------------------------------- | |
| image-scan: | |
| name: Container SBOM & scan (Syft + Trivy) | |
| runs-on: ubuntu-latest | |
| env: | |
| ANTHROPIC_API_KEY: test-key-not-real | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Build Docker image | |
| run: docker build -f infra/Dockerfile -t langgraph-agent-stack:scan . | |
| - name: Generate SBOM (Syft / SPDX) | |
| uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 | |
| with: | |
| image: langgraph-agent-stack:scan | |
| format: spdx-json | |
| output-file: sbom.spdx.json | |
| - name: Upload container SBOM | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: container-sbom-spdx | |
| path: sbom.spdx.json | |
| retention-days: 30 | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| image-ref: langgraph-agent-stack:scan | |
| format: table | |
| exit-code: "1" | |
| ignore-unfixed: true | |
| severity: "HIGH,CRITICAL" | |
| - name: Run Trivy (SARIF for GitHub Security tab) | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| if: always() | |
| with: | |
| image-ref: langgraph-agent-stack:scan | |
| format: sarif | |
| output: trivy-results.sarif | |
| ignore-unfixed: true | |
| severity: "HIGH,CRITICAL" | |
| continue-on-error: true | |
| - name: Upload Trivy SARIF to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 | |
| if: always() | |
| with: | |
| sarif_file: trivy-results.sarif | |
| continue-on-error: true | |
| - name: Upload Trivy SARIF artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: trivy-sarif-report | |
| path: trivy-results.sarif | |
| retention-days: 30 | |
| if-no-files-found: ignore |