Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/scripts/generate-audit-summary-npm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/bash
set -e

# Generate Security Audit Summary from npm audit JSON output
# Usage: ./generate-audit-summary-npm.sh <audit-json-file> <project-label>
# Example: ./generate-audit-summary-npm.sh audit-results.json "TanStack App"

# Guard: skip if GITHUB_STEP_SUMMARY is not set
if [ -z "$GITHUB_STEP_SUMMARY" ]; then
echo "Warning: GITHUB_STEP_SUMMARY not set, skipping summary generation"
exit 0
fi

AUDIT_JSON="${1:-}"
PROJECT_LABEL="${2:-npm project}"

if [ ! -f "$AUDIT_JSON" ]; then
echo "⚠️ Audit JSON file not found: $AUDIT_JSON" >> "$GITHUB_STEP_SUMMARY"
exit 1
fi

echo "## 🔒 Security Audit — $PROJECT_LABEL" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"

# Extract vulnerability counts from metadata
info=$(jq -r '.metadata.vulnerabilities.info // 0' "$AUDIT_JSON")
low=$(jq -r '.metadata.vulnerabilities.low // 0' "$AUDIT_JSON")
moderate=$(jq -r '.metadata.vulnerabilities.moderate // 0' "$AUDIT_JSON")
high=$(jq -r '.metadata.vulnerabilities.high // 0' "$AUDIT_JSON")
critical=$(jq -r '.metadata.vulnerabilities.critical // 0' "$AUDIT_JSON")
total=$(jq -r '.metadata.vulnerabilities.total // 0' "$AUDIT_JSON")

# Summary table
echo "### Vulnerability Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Severity | Count |" >> "$GITHUB_STEP_SUMMARY"
echo "|----------|-------|" >> "$GITHUB_STEP_SUMMARY"
[ "$critical" -gt 0 ] && echo "| 🔴 Critical | $critical |" >> "$GITHUB_STEP_SUMMARY"
[ "$high" -gt 0 ] && echo "| 🟠 High | $high |" >> "$GITHUB_STEP_SUMMARY"
[ "$moderate" -gt 0 ] && echo "| 🟡 Moderate | $moderate |" >> "$GITHUB_STEP_SUMMARY"
[ "$low" -gt 0 ] && echo "| 🔵 Low | $low |" >> "$GITHUB_STEP_SUMMARY"
[ "$info" -gt 0 ] && echo "| ℹ️ Info | $info |" >> "$GITHUB_STEP_SUMMARY"
echo "| **Total** | **$total** |" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"

# If there are vulnerabilities, list them
if [ "$total" -gt 0 ]; then
echo "### Vulnerability Details" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Package | Severity | Fix Available | Details |" >> "$GITHUB_STEP_SUMMARY"
echo "|---------|----------|---------------|---------|" >> "$GITHUB_STEP_SUMMARY"

# Extract each vulnerability with a direct advisory (not just transitive references)
jq -r '
.vulnerabilities | to_entries[] |
.value |
select(.via | map(type) | any(. == "object")) |
{
name: .name,
severity: .severity,
fix: (if .fixAvailable == true then "✅ Yes"
elif .fixAvailable == false then "❌ No"
elif .fixAvailable != null then "✅ \(.fixAvailable.name)@\(.fixAvailable.version)"
else "❓ Unknown" end),
title: ([.via[] | select(type == "object") | .title] | first // "N/A")
} |
"| \(.name) | \(.severity) | \(.fix) | \(.title) |"
' "$AUDIT_JSON" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || true

echo "" >> "$GITHUB_STEP_SUMMARY"

# Action items
echo "### 🛠️ What to do" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "1. Run \`npm audit\` locally to see full details" >> "$GITHUB_STEP_SUMMARY"
echo "2. Run \`npm audit fix\` to auto-fix where possible" >> "$GITHUB_STEP_SUMMARY"
echo "3. For breaking fixes: \`npm audit fix --force\` (review changes carefully)" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "❌ **Audit failed — vulnerabilities found!**" >> "$GITHUB_STEP_SUMMARY"
else
echo "✅ **No vulnerabilities found!**" >> "$GITHUB_STEP_SUMMARY"
fi
68 changes: 68 additions & 0 deletions .github/scripts/generate-audit-summary-pip.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash
set -e

# Generate Security Audit Summary from pip-audit JSON output
# Usage: ./generate-audit-summary-pip.sh <audit-json-file> <project-label>
# Example: ./generate-audit-summary-pip.sh audit-results.json "Python FastAPI"

# Guard: skip if GITHUB_STEP_SUMMARY is not set
if [ -z "$GITHUB_STEP_SUMMARY" ]; then
echo "Warning: GITHUB_STEP_SUMMARY not set, skipping summary generation"
exit 0
fi

AUDIT_JSON="${1:-}"
PROJECT_LABEL="${2:-Python project}"

if [ ! -f "$AUDIT_JSON" ]; then
echo "⚠️ Audit JSON file not found: $AUDIT_JSON" >> "$GITHUB_STEP_SUMMARY"
exit 1
fi

echo "## 🔒 Security Audit — $PROJECT_LABEL" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"

# pip-audit JSON structure: { "dependencies": [ { "name": "...", "version": "...", "vulns": [...] } ] }
# Count vulnerable packages (those with non-empty vulns arrays)
total_deps=$(jq '[.dependencies | length] | first // 0' "$AUDIT_JSON")
vuln_packages=$(jq '[.dependencies[] | select(.vulns | length > 0)] | length' "$AUDIT_JSON")
total_vulns=$(jq '[.dependencies[].vulns | length] | add // 0' "$AUDIT_JSON")

# Summary table
echo "### Vulnerability Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Metric | Count |" >> "$GITHUB_STEP_SUMMARY"
echo "|--------|-------|" >> "$GITHUB_STEP_SUMMARY"
echo "| 📦 Total dependencies scanned | $total_deps |" >> "$GITHUB_STEP_SUMMARY"
echo "| ⚠️ Vulnerable packages | $vuln_packages |" >> "$GITHUB_STEP_SUMMARY"
echo "| 🔓 Total vulnerabilities | $total_vulns |" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"

# If there are vulnerabilities, list them
if [ "$total_vulns" -gt 0 ]; then
echo "### Vulnerability Details" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Package | Version | Vulnerability ID | Fix Versions |" >> "$GITHUB_STEP_SUMMARY"
echo "|---------|---------|-----------------|--------------|" >> "$GITHUB_STEP_SUMMARY"

jq -r '
.dependencies[] |
select(.vulns | length > 0) |
. as $dep |
.vulns[] |
"| \($dep.name) | \($dep.version) | \(.id) | \(.fix_versions | join(", ") // "N/A") |"
' "$AUDIT_JSON" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || true

echo "" >> "$GITHUB_STEP_SUMMARY"

# Action items
echo "### 🛠️ What to do" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "1. Update the affected packages in \`requirements.in\`" >> "$GITHUB_STEP_SUMMARY"
echo "2. Run \`pip-compile requirements.in\` to regenerate \`requirements.txt\`" >> "$GITHUB_STEP_SUMMARY"
echo "3. Run \`pip-audit -r requirements.txt\` locally to verify the fix" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "❌ **Audit failed — vulnerabilities found!**" >> "$GITHUB_STEP_SUMMARY"
else
echo "✅ **No vulnerabilities found!**" >> "$GITHUB_STEP_SUMMARY"
fi
46 changes: 46 additions & 0 deletions .github/workflows/audit-python-fastapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Audit Python FastAPI Dependencies

on:
pull_request:
branches:
- development
paths:
- 'mflix/server/python-fastapi/**'

jobs:
audit:
name: pip-audit (Python FastAPI)
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'

- name: Install pip-audit
run: pip install pip-audit

- name: Audit dependencies
working-directory: mflix/server/python-fastapi
run: pip-audit -r requirements.txt --format json -o audit-results.json || true

- name: Generate audit summary
if: always()
run: |
chmod +x .github/scripts/generate-audit-summary-pip.sh
.github/scripts/generate-audit-summary-pip.sh \
mflix/server/python-fastapi/audit-results.json \
"Python FastAPI"

- name: Check for vulnerabilities
run: |
vuln_count=$(jq '[.dependencies[].vulns | length] | add // 0' mflix/server/python-fastapi/audit-results.json)
if [ "$vuln_count" -gt 0 ]; then
echo "❌ Found $vuln_count vulnerabilities"
exit 1
fi
echo "✅ No vulnerabilities found"
66 changes: 66 additions & 0 deletions .github/workflows/audit-tanstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Audit TanStack Dependencies

on:
pull_request:
branches:
- development
- frameworks-tanstack
paths:
- 'frameworks/javascript/tanstack/**'

jobs:
audit:
name: npm audit (TanStack)
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies (app)
working-directory: frameworks/javascript/tanstack/app
run: npm install

- name: Audit app dependencies
working-directory: frameworks/javascript/tanstack/app
run: npm audit --json > audit-results-app.json || true

- name: Install dependencies (bluehawk)
working-directory: frameworks/javascript/tanstack
run: npm install

- name: Audit bluehawk dependencies
working-directory: frameworks/javascript/tanstack
run: npm audit --json > audit-results-bluehawk.json || true

- name: Generate audit summary (app)
if: always()
run: |
chmod +x .github/scripts/generate-audit-summary-npm.sh
.github/scripts/generate-audit-summary-npm.sh \
frameworks/javascript/tanstack/app/audit-results-app.json \
"TanStack App"

- name: Generate audit summary (bluehawk)
if: always()
run: |
chmod +x .github/scripts/generate-audit-summary-npm.sh
.github/scripts/generate-audit-summary-npm.sh \
frameworks/javascript/tanstack/audit-results-bluehawk.json \
"TanStack Bluehawk"

- name: Check for high+ vulnerabilities
run: |
app_high=$(jq -r '[(.metadata.vulnerabilities.high // 0), (.metadata.vulnerabilities.critical // 0)] | add' frameworks/javascript/tanstack/app/audit-results-app.json)
bh_high=$(jq -r '[(.metadata.vulnerabilities.high // 0), (.metadata.vulnerabilities.critical // 0)] | add' frameworks/javascript/tanstack/audit-results-bluehawk.json)
total=$((app_high + bh_high))
if [ "$total" -gt 0 ]; then
echo "❌ Found $total high/critical vulnerabilities"
exit 1
fi
echo "✅ No high/critical vulnerabilities found"
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Thumbs.db
logs/
*.log


# Temporary Files (Global)
*.tmp
*.temp
Expand All @@ -52,3 +53,9 @@ yarn-error.log*
coverage/
*.lcov
.nyc_output

# Security Audit Results (Generated by CI/local testing)
audit-results*.json

# Security Audit Results (Generated by local testing)
audit-results*.json
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,28 @@ Framework examples follow a simpler workflow:

No copier tool is used - snippets are committed directly to this repository.

### Security Audits

Dependency security audits run automatically on PRs to `development`:

- **`audit-tanstack.yml`** — runs `npm audit` on TanStack app and Bluehawk dependencies
- **`audit-python-fastapi.yml`** — runs `pip-audit` on Python FastAPI dependencies

**To test locally:**

```bash
# npm (TanStack)
cd frameworks/javascript/tanstack/app
npm audit --audit-level=high

# pip (Python FastAPI)
cd mflix/server/python-fastapi
pip install pip-audit
pip-audit -r requirements.txt
```

If an audit fails on your PR, check the workflow summary for details on which packages need updating.

### MFlix Release Process

When you merge a release PR from `development` to `main`, the copier tool
Expand Down
Loading
Loading