The orchestrator expects all required JSONs to exist. A missing non-optional input is an error — re-run full-security-audit first.
-
Preflight — verify inputs. Confirm the 4 required findings JSONs exist and are not older than 24 hours:
for f in secrets dependencies audit compliance; do
test -f security/findings/$f.json || { echo "missing $f.json"; exit 1; }
age=$(( $(date +%s) - $(stat -f %m security/findings/$f.json 2>/dev/null || stat -c %Y security/findings/$f.json) ))
(( age < 86400 )) || echo "WARN: $f.json is >24h old"
done
container.json is optional — skipped if absent.
-
Compute the before snapshot. Per findings file, count by severity:
jq '.findings | group_by(.severity) | map({severity: .[0].severity, count: length})' \
security/findings/secrets.json
Persist to security/remediation/.snapshot-before-<date>.json for the delta computation in step 8.
-
Run secret-remediation FIRST and wait. Leaked credentials are the highest-priority remediation — every downstream action risks exposing them further (force-push + re-scan both touch git). If secrets.json has any findings classified as a real leak (not false-positive):
- Invoke
secret-remediation.
- Block until the
secret-remediation report confirms rotation + invalidation + history rewrite for every real leak.
- If rotation fails for any credential (provider 5xx, missing admin access), halt the orchestrator and page on-call. Do not proceed — running dependency upgrades / rebuilds while credentials are still live would compound the leak.
-
Dispatch the remaining remediation skills in parallel. Once secrets are handled, these are independent:
| Skill | Triggered by |
|---|
dependency-remediation | dependencies.json has non-empty findings |
vulnerability-remediation | audit.json has non-empty findings |
container-remediation | container.json exists and has findings; repo has a Dockerfile |
compliance-remediation | compliance.json has non-empty findings |
Each runs in its own branch / PR to keep changes reviewable. Collect the output report path from each.
-
Re-run scanners to verify closure. After each remediation completes, re-invoke the paired scanner and record the delta:
secret-remediation → re-run secret-scanner; expect 0 findings for the original secret values.
dependency-remediation → re-run dependency-audit; expect the original CVE IDs to be absent or explicitly suppressed.
vulnerability-remediation → re-run security-audit; expect original rule+path pairs to return no matches.
container-remediation → re-run container-scan with Trivy on the new image tag; expect 0 CRITICAL/HIGH CVEs.
compliance-remediation → re-run compliance-check; expect originally-open controls marked closed (or carrying documented exceptions).
-
Identify residuals. A residual is a finding that persists after remediation. For each residual, classify as:
- Exception approved — business justification, compensating control, owner, review date ≤ 60 days. Documented in the report.
- Follow-up ticket — cannot remediate now, but owned and deadline-tracked. File the ticket and link it.
- False positive re-evaluated — scanner rule is wrong for our context; document the allowlist with evidence.
-
File follow-up tickets. For every residual that is not an approved exception:
gh issue create \
--title "SEC-RESIDUAL: <CVE or rule> — <short desc>" \
--label "security,sec-residual" \
--body "See security/remediation/full-remediation-<date>.md#<anchor>. Owner: @<handle>. Due: <date>."
-
Write the consolidated report at security/remediation/full-remediation-<date>.md:
Executive summary:
- Audit date (from
full-security-audit run).
- Remediation cycle date.
- Before-counts by severity, after-counts by severity, delta.
- Overall risk level before → after (computed by
pentest-report weighting, reused here).
- PASS / FAIL verdict against release gate.
Per-class detail:
- Secrets: findings handled, rotations completed, history-rewrite scope, prevention controls installed. Link to
secrets-<date>.md.
- Dependencies: CVEs closed, packages changed, exceptions. Link to
dependencies-<date>.md.
- Vulnerabilities: findings closed by category (injection, XSS, authz, …), regression tests added, exceptions. Link to
vulnerabilities-<date>.md.
- Containers: image digests before/after, CVE count delta, Dockerfile hardening summary. Link to
container-<image>-<date>.md.
- Compliance: controls closed by type (Design / Operating / Evidence), policies drafted, evidence pipelines set up. Link to
compliance-<framework>-<date>.md.
Residuals table:
| ID | Class | Severity | Status | Justification | Owner | Review date |
Exceptions register:
| ID | Control / CVE | Compensating control | Owner | Review date |
Follow-up tickets:
| Ticket | Class | Owner | Due |
-
Link from pentest-report. Append a "Remediation Status" section to the most recent pentest-report-<date>.md with a link back to this full-remediation report so future audits have traceability from finding → remediation → verification.