Security Audit workflow (PatterAI/Patter)
The Security Audit workflow from PatterAI/Patter, explained and optimized by Latchkey.
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.
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
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
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
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:
- Dependency installs
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.