Skip to content

fix(frontend): remediate frontend + extension audit findings #5066

fix(frontend): remediate frontend + extension audit findings

fix(frontend): remediate frontend + extension audit findings #5066

name: security-required
on:
pull_request:
branches:
- main
- dev
workflow_dispatch:
permissions:
contents: read
security-events: read
concurrency:
group: security-required-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
changes:
name: Detect Gate Changes
runs-on: ubuntu-latest
outputs:
backend_changed: ${{ steps.detect.outputs.backend_changed }}
frontend_changed: ${{ steps.detect.outputs.frontend_changed }}
e2e_changed: ${{ steps.detect.outputs.e2e_changed }}
security_relevant_changed: ${{ steps.detect.outputs.security_relevant_changed }}
coverage_required: ${{ steps.detect.outputs.coverage_required }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- id: detect
name: Classify changed files
uses: ./.github/actions/detect-required-gate-changes
security-required:
name: security-required
runs-on: ubuntu-latest
needs: [changes]
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install security tooling
run: |
python -m pip install --upgrade pip
pip install bandit pyyaml
- name: No-op pass (security irrelevant change set)
if: needs.changes.outputs.security_relevant_changed != 'true'
run: echo "No security-relevant paths changed; bandit scan skipped by policy."
- name: Dependency review (high/critical)
if: github.event_name == 'pull_request'
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48
with:
fail-on-severity: high
- name: Run Bandit scan
if: needs.changes.outputs.security_relevant_changed == 'true'
run: |
python -m bandit -r tldw_Server_API/app -f json -o /tmp/bandit_security_required.json --exit-zero
- name: Enforce high/critical threshold with allowlist
if: needs.changes.outputs.security_relevant_changed == 'true'
run: |
python - <<'PY'
import datetime
import json
from pathlib import Path
import yaml
allowlist_path = Path(".github/security/ci-allowlist.yml")
allowlist_doc = yaml.safe_load(allowlist_path.read_text(encoding="utf-8")) or {}
allow_entries = allowlist_doc.get("allowlist", [])
today = datetime.date.today()
allowed_ids = set()
for entry in allow_entries:
vuln_id = (entry or {}).get("id")
expires = (entry or {}).get("expires")
if not vuln_id or not expires:
continue
try:
expiry_date = datetime.date.fromisoformat(str(expires))
except ValueError:
continue
if expiry_date >= today:
allowed_ids.add(vuln_id)
report = json.loads(Path("/tmp/bandit_security_required.json").read_text(encoding="utf-8"))
violations = []
for finding in report.get("results", []):
severity = str(finding.get("issue_severity", "")).upper()
test_id = finding.get("test_id")
if severity in {"HIGH", "CRITICAL"} and test_id not in allowed_ids:
violations.append(
{
"test_id": test_id,
"severity": severity,
"filename": finding.get("filename"),
"line_number": finding.get("line_number"),
"issue_text": finding.get("issue_text"),
}
)
if violations:
print("Security threshold violations detected:")
for violation in violations:
print(violation)
raise SystemExit(1)
print("No unallowlisted HIGH/CRITICAL findings detected.")
PY