Skip to content
Merged
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
31 changes: 29 additions & 2 deletions demo/build_demo_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,30 @@
"exploit_sketch": "Diff the 'already registered' vs 'ok' responses to enumerate users."},
]

# The three candidates the verify agent did NOT confirm. The curated summary has always claimed
# "9 candidates, 6 verified, 2 refuted, 1 dropped" while shipping only the 6 — so the report could
# not render the refuted section at all, and the dataset advertised a funnel it could not show.
# These are real-looking false positives of the kind verify actually catches: a sink that is not
# reachable, a "secret" that is a test fixture, and a rate limit that already exists upstream.
REFUTED = [
{"id": "crapi-eval-007", "title": "Remote code execution via eval in report renderer",
"vuln_class": "command_injection", "severity": "critical",
"file": "services/community/render.js", "line": 118,
"description": "A template string reaches eval() in the report renderer.",
"exploit_sketch": "Inject a template expression that closes the string and calls process.exit.",
"snippet": "const out = eval('`' + tpl + '`'); // flagged"},
{"id": "crapi-hardcoded-008", "title": "Hardcoded database password",
"vuln_class": "sensitive_data", "severity": "high",
"file": "services/identity/test/fixtures.js", "line": 9,
"description": "A database password appears as a literal in the source.",
"exploit_sketch": "Read the credential from the repository and connect directly."},
{"id": "crapi-nolimit-009", "title": "No rate limit on password reset",
"vuln_class": "rate_abuse", "severity": "medium",
"file": "services/identity/reset.js", "line": 47,
"description": "The password-reset endpoint has no throttle in application code.",
"exploit_sketch": "Loop reset requests to enumerate accounts or exhaust the mail quota."},
]

# control per finding (005 is code-cure-only)
BANDAID = {"crapi-sqli-001": "service_policy", "crapi-bola-002": "api_schema", "crapi-mass-003": "waf",
"crapi-bruteforce-004": "rate_limit", "crapi-tokenleak-006": "waf_data_guard"}
Expand Down Expand Up @@ -138,10 +162,13 @@ def main():
# it never passes the pipeline choke point; without this the demo dataset would render as
# "never classified" while a real run of the same findings classified fine.
from vpcopilot.weakness import classify
for _f in FINDINGS:
for _f in FINDINGS + REFUTED:
_g = classify(_f.get("vuln_class", ""))
_f["cwe"], _f["owasp"], _f["cwe_source"] = _g["cwe"], _g["owasp"], _g["cwe_source"]
(OUT / "findings.json").write_text(json.dumps(FINDINGS, indent=2))
# Refuted candidates ship in findings.json but NOT in triage.json — which is exactly how a
# real run represents them, and what makes the report render its "did not confirm"
# section. They carry no band-aid and are excluded from every count.
(OUT / "findings.json").write_text(json.dumps(FINDINGS + REFUTED, indent=2))
(OUT / "triage.json").write_text(json.dumps(TRIAGE, indent=2))
(OUT / "remediations.json").write_text(json.dumps(REMEDIATIONS, indent=2))
(OUT / "policies.json").write_text(json.dumps(POLICIES, indent=2))
Expand Down
26 changes: 13 additions & 13 deletions demo/out/audit.log
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{"ts": "2026-08-05T13:06:09.732288+00:00", "action": "refine_apply", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "namespace": "crapi-demo", "control": "service_policy", "policy": "deny-login-sqli", "lb": "crapi-lab", "passed": true, "attempts": 2, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:06:13.732288+00:00", "action": "apply_timing", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "service_policy", "finding_id": "crapi-sqli-001", "passed": true, "elapsed_s": 48.0, "attempts": 2, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:07:05.732288+00:00", "action": "create_api_definition", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bola-002", "namespace": "crapi-demo", "name": "crapi-lab-apidef", "swagger": "crapi-lab-swagger"}
{"ts": "2026-08-05T13:07:09.732288+00:00", "action": "apply_api_schema", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bola-002", "namespace": "crapi-demo", "apidef": "crapi-lab-apidef", "lb": "crapi-lab", "passed": true, "kept": true, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:07:13.732288+00:00", "action": "apply_timing", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "api_schema", "finding_id": "crapi-bola-002", "passed": true, "elapsed_s": 33.0, "attempts": 1, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:07:50.732288+00:00", "action": "apply_waf", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-mass-003", "namespace": "crapi-demo", "app_firewall": "crapi-lab-waf", "lb": "crapi-lab", "config_enabled": true, "kept": true, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:07:54.732288+00:00", "action": "apply_timing", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "waf", "finding_id": "crapi-mass-003", "passed": true, "elapsed_s": 21.0, "attempts": 1, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T13:08:19.732288+00:00", "action": "apply_rate_limit", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bruteforce-004", "namespace": "crapi-demo", "rate": "5/MINUTE", "lb": "crapi-lab", "passed": true, "kept": true, "behavioral": {"sent": 30, "limited": 25, "passed": 5, "codes": {"200": 5, "429": 25}}}
{"ts": "2026-08-05T13:08:23.732288+00:00", "action": "apply_timing", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "rate_limit", "finding_id": "crapi-bruteforce-004", "passed": true, "elapsed_s": 27.0, "attempts": 1}
{"ts": "2026-08-05T13:08:54.732288+00:00", "action": "apply_data_guard", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-tokenleak-006", "namespace": "crapi-demo", "app_firewall": "crapi-lab-waf", "lb": "crapi-lab", "enabled": true, "kept": true}
{"ts": "2026-08-05T13:08:58.732288+00:00", "action": "apply_timing", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "waf_data_guard", "finding_id": "crapi-tokenleak-006", "passed": true, "elapsed_s": 19.0, "attempts": 1}
{"ts": "2026-08-05T13:09:21.732288+00:00", "action": "open_pr", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "finding": "crapi-sqli-001", "repo": "acme/crapi", "url": "https://github.com/acme/crapi/pull/311", "number": 311}
{"ts": "2026-08-05T13:09:25.732288+00:00", "action": "retire", "run_id": "cfc003c6cfb6", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "namespace": "crapi-demo", "control": "service_policy", "lb": "crapi-lab", "forced": false}
{"ts": "2026-08-05T16:05:09.359184+00:00", "action": "refine_apply", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "namespace": "crapi-demo", "control": "service_policy", "policy": "deny-login-sqli", "lb": "crapi-lab", "passed": true, "attempts": 2, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:05:13.359184+00:00", "action": "apply_timing", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "service_policy", "finding_id": "crapi-sqli-001", "passed": true, "elapsed_s": 48.0, "attempts": 2, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:06:05.359184+00:00", "action": "create_api_definition", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bola-002", "namespace": "crapi-demo", "name": "crapi-lab-apidef", "swagger": "crapi-lab-swagger"}
{"ts": "2026-08-05T16:06:09.359184+00:00", "action": "apply_api_schema", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bola-002", "namespace": "crapi-demo", "apidef": "crapi-lab-apidef", "lb": "crapi-lab", "passed": true, "kept": true, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:06:13.359184+00:00", "action": "apply_timing", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "api_schema", "finding_id": "crapi-bola-002", "passed": true, "elapsed_s": 33.0, "attempts": 1, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:06:50.359184+00:00", "action": "apply_waf", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-mass-003", "namespace": "crapi-demo", "app_firewall": "crapi-lab-waf", "lb": "crapi-lab", "config_enabled": true, "kept": true, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:06:54.359184+00:00", "action": "apply_timing", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "waf", "finding_id": "crapi-mass-003", "passed": true, "elapsed_s": 21.0, "attempts": 1, "before_after": {"before": {"exploit_status": 200, "exploit_blocked": false, "legit_ok": true}, "after": {"exploit_status": 403, "exploit_blocked": true, "legit_ok": true}}}
{"ts": "2026-08-05T16:07:19.359184+00:00", "action": "apply_rate_limit", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-bruteforce-004", "namespace": "crapi-demo", "rate": "5/MINUTE", "lb": "crapi-lab", "passed": true, "kept": true, "behavioral": {"sent": 30, "limited": 25, "passed": 5, "codes": {"200": 5, "429": 25}}}
{"ts": "2026-08-05T16:07:23.359184+00:00", "action": "apply_timing", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "rate_limit", "finding_id": "crapi-bruteforce-004", "passed": true, "elapsed_s": 27.0, "attempts": 1}
{"ts": "2026-08-05T16:07:54.359184+00:00", "action": "apply_data_guard", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-tokenleak-006", "namespace": "crapi-demo", "app_firewall": "crapi-lab-waf", "lb": "crapi-lab", "enabled": true, "kept": true}
{"ts": "2026-08-05T16:07:58.359184+00:00", "action": "apply_timing", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "control": "waf_data_guard", "finding_id": "crapi-tokenleak-006", "passed": true, "elapsed_s": 19.0, "attempts": 1}
{"ts": "2026-08-05T16:08:21.359184+00:00", "action": "open_pr", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "finding": "crapi-sqli-001", "repo": "acme/crapi", "url": "https://github.com/acme/crapi/pull/311", "number": 311}
{"ts": "2026-08-05T16:08:25.359184+00:00", "action": "retire", "run_id": "7bc42a95f23d", "actor": "security-oncall", "host": "vpcopilot-demo", "tool_version": "0.1.0", "finding_id": "crapi-sqli-001", "namespace": "crapi-demo", "control": "service_policy", "lb": "crapi-lab", "forced": false}
40 changes: 40 additions & 0 deletions demo/out/findings.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,45 @@
"cwe": "",
"owasp": "API2:2023",
"cwe_source": ""
},
{
"id": "crapi-eval-007",
"title": "Remote code execution via eval in report renderer",
"vuln_class": "command_injection",
"severity": "critical",
"file": "services/community/render.js",
"line": 118,
"description": "A template string reaches eval() in the report renderer.",
"exploit_sketch": "Inject a template expression that closes the string and calls process.exit.",
"snippet": "const out = eval('`' + tpl + '`'); // flagged",
"cwe": "CWE-77",
"owasp": "",
"cwe_source": "mapped"
},
{
"id": "crapi-hardcoded-008",
"title": "Hardcoded database password",
"vuln_class": "sensitive_data",
"severity": "high",
"file": "services/identity/test/fixtures.js",
"line": 9,
"description": "A database password appears as a literal in the source.",
"exploit_sketch": "Read the credential from the repository and connect directly.",
"cwe": "",
"owasp": "API3:2023",
"cwe_source": ""
},
{
"id": "crapi-nolimit-009",
"title": "No rate limit on password reset",
"vuln_class": "rate_abuse",
"severity": "medium",
"file": "services/identity/reset.js",
"line": 47,
"description": "The password-reset endpoint has no throttle in application code.",
"exploit_sketch": "Loop reset requests to enumerate accounts or exhaust the mail quota.",
"cwe": "CWE-799",
"owasp": "API4:2023",
"cwe_source": "mapped"
}
]
20 changes: 10 additions & 10 deletions demo/out/ledger.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
"no_bandaid": false,
"has_cure": true,
"ttl": {
"applied_at": "2026-08-05T13:15:09.715566+00:00",
"applied_at": "2026-08-05T16:14:09.347397+00:00",
"ttl_hours": 168,
"expires_at": "2026-08-12T13:15:09.715566+00:00"
"expires_at": "2026-08-12T16:14:09.347397+00:00"
}
},
"crapi-bola-002": {
Expand Down Expand Up @@ -54,9 +54,9 @@
"no_bandaid": false,
"has_cure": true,
"ttl": {
"applied_at": "2026-08-05T13:15:09.716815+00:00",
"applied_at": "2026-08-05T16:14:09.348285+00:00",
"ttl_hours": 168,
"expires_at": "2026-08-12T13:15:09.716815+00:00"
"expires_at": "2026-08-12T16:14:09.348285+00:00"
}
},
"crapi-mass-003": {
Expand All @@ -81,9 +81,9 @@
"no_bandaid": false,
"has_cure": true,
"ttl": {
"applied_at": "2026-08-05T13:15:09.717778+00:00",
"applied_at": "2026-08-05T16:14:09.348948+00:00",
"ttl_hours": 168,
"expires_at": "2026-08-12T13:15:09.717778+00:00"
"expires_at": "2026-08-12T16:14:09.348948+00:00"
}
},
"crapi-bruteforce-004": {
Expand All @@ -108,9 +108,9 @@
"no_bandaid": false,
"has_cure": true,
"ttl": {
"applied_at": "2026-08-05T13:15:09.720633+00:00",
"applied_at": "2026-08-05T16:14:09.349658+00:00",
"ttl_hours": 168,
"expires_at": "2026-08-12T13:15:09.720633+00:00"
"expires_at": "2026-08-12T16:14:09.349658+00:00"
}
},
"crapi-tokenleak-006": {
Expand Down Expand Up @@ -138,9 +138,9 @@
"no_bandaid": false,
"has_cure": true,
"ttl": {
"applied_at": "2026-08-05T13:15:09.721386+00:00",
"applied_at": "2026-08-05T16:14:09.350331+00:00",
"ttl_hours": 168,
"expires_at": "2026-08-12T13:15:09.721386+00:00"
"expires_at": "2026-08-12T16:14:09.350331+00:00"
}
},
"crapi-userenum-005": {
Expand Down
Loading
Loading