Triage, prioritize, and remediate security findings from automated security reviews, dependency audits, and manual assessments. Ensure all findings are tracked to resolution and that critical vulnerabilities are escalated immediately.
Applies to all services in the ADLC pipeline. Covers security agent review reports, dependency CVEs, authentication/authorization issues, rate limiting bypasses, and data exposure risks.
~/dev/ops/reviews/{service}/security-report.jsonsource ~/.env.adlcpython3 -c "
import json
r = json.load(open('$HOME/dev/ops/reviews/{service}/security-report.json'))
print(f'Status: {r[\"status\"]}')
print(f'Severity: {r[\"severity\"]}')
for c in r.get('checks', []):
if c.get('status') not in ('PASS', 'pass', 'OK'):
print(f' FINDING: {c[\"id\"]} -- {c[\"description\"]} [{c.get(\"severity\",\"?\")}]')
"| Severity | Definition | SLA |
|---|---|---|
| CRITICAL | Active exploit possible, data breach imminent | Block pipeline, fix NOW |
| HIGH | Vulnerability exploitable with moderate effort | Fix before staging promotion |
| MEDIUM | Defense-in-depth gap, no immediate exploit | Fix before production |
| LOW | Best practice deviation, informational | Track, fix when convenient |
Missing tenant_id filter (CRITICAL): Every database
query MUST include tenant_id. Cross-tenant data access is
the highest severity finding.
# Check for queries without tenant_id
grep -rn "SELECT\|INSERT\|UPDATE\|DELETE" ~/dev/projects/{service}/src/ | grep -v "tenant_id" | grep -v "migration"JWT validation gaps: - Missing signature
verification - Missing expiry check - Missing tenant_id extraction from
claims - Hardcoded secrets (check .env files for actual
keys in repo)
Open redirect via callbackUrl (lesson from
2026-03-23): Any login form accepting
callbackUrl/returnTo/next must
validate it is a relative path:
if (!callbackUrl.startsWith('/') || callbackUrl.startsWith('//')) use fallback
x-forwarded-for bypass (lesson from 2026-03-23):
Rate limiters MUST NOT use x-forwarded-for first value as
the IP source. Behind Cloudflare, use cf-connecting-ip:
request.headers.get('cf-connecting-ip') ?? request.headers.get('x-forwarded-for')?.split(',')[0].trim()
# For Rust services (if cargo-audit is installed)
cd ~/dev/projects/{service} && cargo audit 2>/dev/null || echo "cargo-audit not installed -- check Cargo.toml manually"
# For Node services
cd ~/dev/projects/{service} && npm audit --production 2>/dev/nullNote: cargo audit may not be installed (lesson from
2026-03-22). Fall back to manual Cargo.toml review. Do not
block the entire report for this.
Active CVE: CVE-2026-2005 (PostgreSQL pgcrypto HIGH) – upgrade to PostgreSQL 17.9 required.
.env files must NOT be committed to git.env.example uses correct variable names (lesson:
AUTH_SECRET not NEXTAUTH_SECRET for next-auth
v5)NODE_ENV must be production on staging
(lesson from 2026-03-23)signOut requires POST, not GET (lesson from
2026-03-23)wc -c), not just existence.For CRITICAL findings, post immediately to Slack DM:
source ~/.env.adlc
curl -sf -X POST "https://slack.com/api/chat.postMessage" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$(python3 -c "
import json
print(json.dumps({
'channel': 'D0AGRAVEC1K',
'text': ':rotating_light: SECURITY CRITICAL -- {service}\nFinding: {finding_id} -- {description}\nRisk: {risk_description}\nRemediation: {proposed_fix}'
}))
")"For CRITICAL findings, also generate a human review report:
cat << 'EOF' | bash ~/dev/ops/adlc-v2/scripts/cli/write-human-review.sh {service} security
{
"title": "{finding_id}: {short_title}",
"summary": "{description of the security finding and its impact}",
"timeline": [...],
"blocker": {
"description": "{what is at risk}",
"rootCause": "{why the vulnerability exists}",
"impact": "{potential damage}",
"severity": "CRITICAL"
},
"options": [
{"label": "Fix now", "description": "Block pipeline, remediate immediately", "slackReply": "approved fix {finding_id}"},
{"label": "Accept risk", "description": "Document and proceed to staging", "slackReply": "accepted risk {finding_id}"}
]
}
EOFSpawn dev agent for fix:
/agent dev "SERVICE: {service}. PROJECT: {project}. SECURITY FIX: {finding_id} -- {description}. Fix: {remediation_steps}. Spec: ~/dev/specs/{project}/specs/{service}/spec.md"
Spawn ONLY the security agent (not all 4 reviews):
/agent security "SERVICE: {service}. PROJECT: {project}. RE-AUDIT after fix for {finding_id}. Write JSON report to ~/dev/ops/reviews/{service}/security-report.json"
Track retry count. After 3 retries, mark BLOCKED.
CLI="$HOME/dev/ops/adlc-v2/scripts/cli"
echo '{"id":"{finding_id}","severity":"{severity}","description":"{desc}","status":"OPEN","service":"{service}"}' | bash $CLI/write-finding.sh {service}clean or concerns
with no HIGH/CRITICAL:
cat ~/dev/ops/reviews/{service}/security-report.jsongit log --all -p -- '*.env' '*.key' '*.pem'Security fixes should not be rolled back. If a fix introduces a regression: 1. Keep the security fix 2. Fix the regression separately 3. Re-run both security audit and functional tests
If a finding is a false positive: 1. Document why in the security
report 2. Add to an exceptions list:
~/dev/ops/reviews/{service}/security-exceptions.json 3.
Re-run audit to confirm it passes with the exception noted
~/dev/ops/reviews/{service}/security-report.json~/dev/ops/adlc-v2/scripts/cli/write-finding.sh~/dev/ops/adlc-v2/scripts/cli/write-human-review.sh