Skip to content
Latchkey

Security Audit workflow (PatterAI/Patter)

The Security Audit workflow from PatterAI/Patter, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: PatterAI/Patter.github/workflows/audit.ymlLicense MITView source

What it does

This is the Security Audit workflow from the PatterAI/Patter repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Security Audit

# Dependency + static-analysis audit. Runs weekly as a safety net and on
# every PR that touches dependency manifests so supply-chain regressions
# surface immediately. Findings are reported but do not block merge - the
# goal is visibility, not false-positive theatre.

on:
  push:
    branches: [main]
    paths:
      - 'libraries/python/pyproject.toml'
      - 'libraries/typescript/package.json'
      - 'libraries/typescript/package-lock.json'
      - '.github/workflows/audit.yml'
  pull_request:
    paths:
      - 'libraries/python/pyproject.toml'
      - 'libraries/typescript/package.json'
      - 'libraries/typescript/package-lock.json'
      - '.github/workflows/audit.yml'
  schedule:
    # Monday 06:00 UTC - catch CVEs that land over the weekend.
    - cron: '0 6 * * 1'
  workflow_dispatch:

jobs:
  pip-audit:
    name: Python dependency audit (pip-audit)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'
          cache: 'pip'
          cache-dependency-path: libraries/python/pyproject.toml
      - name: Install pip-audit
        run: pip install pip-audit
      - name: Install SDK runtime deps
        run: |
          cd libraries/python
          pip install -e ".[local]"
      - name: Run pip-audit (warn-only)
        run: |
          cd libraries/python
          # --strict would fail the job on any finding; we keep it
          # advisory for now because telephony SDKs often depend on
          # httpx/cryptography versions that get CVEs patched weeks
          # after release. Review weekly.
          pip-audit --progress-spinner off --desc on || true

  npm-audit:
    name: TypeScript dependency audit (npm audit)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set up Node.js 20
        uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: libraries/typescript/package-lock.json
      - name: Install dependencies (no scripts)
        run: |
          cd libraries/typescript
          npm ci --ignore-scripts
      - name: Run npm audit
        run: |
          cd libraries/typescript
          # `--audit-level=high` keeps low/moderate noise out of the
          # CI log - the scheduled run still catches them via --json.
          npm audit --omit=dev --audit-level=high || true
      - name: Upload full JSON report
        if: always()
        run: |
          cd libraries/typescript
          npm audit --json --omit=dev > ../npm-audit.json || true
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: npm-audit-report
          path: npm-audit.json
          if-no-files-found: ignore

  bandit:
    name: Python static analysis (bandit)
    runs-on: ubuntu-latest
    # `security-events: write` is required by `codeql-action/upload-sarif`
    # to push findings into the GitHub Security tab. Without it the upload
    # step fails with "Resource not accessible by integration". `contents:
    # read` is the minimum the checkout step needs.
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'
          cache: 'pip'
      - name: Install bandit (+ SARIF formatter)
        # ``bandit-sarif-formatter`` registers a ``sarif`` output mode so the
        # result lands in the GitHub Security tab. Stock ``bandit`` only
        # supports csv/custom/html/json/screen/txt/xml/yaml.
        run: pip install 'bandit[toml]' bandit-sarif-formatter
      - name: Run bandit on Python SDK
        run: |
          # Skip the tests dir (they intentionally exercise suspicious
          # patterns) and assertions (B101 noise inside tests & assert-
          # heavy typing helpers).
          bandit -r libraries/python/getpatter -ll -iii \
            --exclude libraries/python/getpatter/dashboard/ui.py \
            -f txt || true
      - name: Generate SARIF for Security tab
        run: |
          bandit -r libraries/python/getpatter -ll -iii \
            --exclude libraries/python/getpatter/dashboard/ui.py \
            -f sarif -o bandit.sarif || true
      - uses: github/codeql-action/upload-sarif@v4
        # Only upload when the SARIF file was actually produced - if the
        # formatter install fails on a future bandit version the step
        # shouldn't fail the job, it just skips the Security-tab upload.
        if: always() && hashFiles('bandit.sarif') != ''
        with:
          sarif_file: bandit.sarif
          category: bandit

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: Security Audit
 
# Dependency + static-analysis audit. Runs weekly as a safety net and on
# every PR that touches dependency manifests so supply-chain regressions
# surface immediately. Findings are reported but do not block merge - the
# goal is visibility, not false-positive theatre.
 
on:
  push:
    branches: [main]
    paths:
      - 'libraries/python/pyproject.toml'
      - 'libraries/typescript/package.json'
      - 'libraries/typescript/package-lock.json'
      - '.github/workflows/audit.yml'
  pull_request:
    paths:
      - 'libraries/python/pyproject.toml'
      - 'libraries/typescript/package.json'
      - 'libraries/typescript/package-lock.json'
      - '.github/workflows/audit.yml'
  schedule:
    # Monday 06:00 UTC - catch CVEs that land over the weekend.
    - cron: '0 6 * * 1'
  workflow_dispatch:
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  pip-audit:
    timeout-minutes: 30
    name: Python dependency audit (pip-audit)
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'
          cache: 'pip'
          cache-dependency-path: libraries/python/pyproject.toml
      - name: Install pip-audit
        run: pip install pip-audit
      - name: Install SDK runtime deps
        run: |
          cd libraries/python
          pip install -e ".[local]"
      - name: Run pip-audit (warn-only)
        run: |
          cd libraries/python
          # --strict would fail the job on any finding; we keep it
          # advisory for now because telephony SDKs often depend on
          # httpx/cryptography versions that get CVEs patched weeks
          # after release. Review weekly.
          pip-audit --progress-spinner off --desc on || true
 
  npm-audit:
    timeout-minutes: 30
    name: TypeScript dependency audit (npm audit)
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - name: Set up Node.js 20
        uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: libraries/typescript/package-lock.json
      - name: Install dependencies (no scripts)
        run: |
          cd libraries/typescript
          npm ci --ignore-scripts
      - name: Run npm audit
        run: |
          cd libraries/typescript
          # `--audit-level=high` keeps low/moderate noise out of the
          # CI log - the scheduled run still catches them via --json.
          npm audit --omit=dev --audit-level=high || true
      - name: Upload full JSON report
        if: always()
        run: |
          cd libraries/typescript
          npm audit --json --omit=dev > ../npm-audit.json || true
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: npm-audit-report
          path: npm-audit.json
          if-no-files-found: ignore
 
  bandit:
    timeout-minutes: 30
    name: Python static analysis (bandit)
    runs-on: latchkey-small
    # `security-events: write` is required by `codeql-action/upload-sarif`
    # to push findings into the GitHub Security tab. Without it the upload
    # step fails with "Resource not accessible by integration". `contents:
    # read` is the minimum the checkout step needs.
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'
          cache: 'pip'
      - name: Install bandit (+ SARIF formatter)
        # ``bandit-sarif-formatter`` registers a ``sarif`` output mode so the
        # result lands in the GitHub Security tab. Stock ``bandit`` only
        # supports csv/custom/html/json/screen/txt/xml/yaml.
        run: pip install 'bandit[toml]' bandit-sarif-formatter
      - name: Run bandit on Python SDK
        run: |
          # Skip the tests dir (they intentionally exercise suspicious
          # patterns) and assertions (B101 noise inside tests & assert-
          # heavy typing helpers).
          bandit -r libraries/python/getpatter -ll -iii \
            --exclude libraries/python/getpatter/dashboard/ui.py \
            -f txt || true
      - name: Generate SARIF for Security tab
        run: |
          bandit -r libraries/python/getpatter -ll -iii \
            --exclude libraries/python/getpatter/dashboard/ui.py \
            -f sarif -o bandit.sarif || true
      - uses: github/codeql-action/upload-sarif@v4
        # Only upload when the SARIF file was actually produced - if the
        # formatter install fails on a future bandit version the step
        # shouldn't fail the job, it just skips the Security-tab upload.
        if: always() && hashFiles('bandit.sarif') != ''
        with:
          sarif_file: bandit.sarif
          category: bandit
 

What changed

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow