Skip to content

Commit 3ea7ca5

Browse files
committed
Add model-agnostic AI analysis layer with frontier-model hooks
Scripts/AIAnalysis/ — a pipeline that correlates findings across Veracode scan types (SAST/DAST/SCA/container), validates them with a panel of Claude models to reduce false positives, and chains related findings into risk paths. Prepared for Mythos and future frontier models: - models.json registry drives all model selection by role (triage/validate/deep-validate/correlate/chain/second-opinion). Enabling Claude Mythos 5 or a later model is a one-line config edit — no code change. - providers.py shapes each request per model family: adaptive thinking for Opus/Sonnet, thinking omitted for Fable/Mythos (always-on), and server-side refusal fallbacks when a fallback_model is set. A not-yet-served model (404) is disabled for the run so the pipeline degrades gracefully. - hooks.py exposes 9 operational hook points (pre_ingest ... report) so external tooling or a frontier model running alongside can observe/transform data at each stage without touching pipeline code. Analysis capabilities: - Deterministic cross-scan correlation (offline, stdlib-only, CI-safe): cross-layer CWE confirmation (SAST+DAST reachable), common flaw sources, shared CVE (SCA+container), dependency-usage links. - Multi-model consensus FP validation (adversarial refute framing + quorum). - Model-assisted risk chaining with combined severity, remediation order, and directed security-training recommendations. - Structured outputs via output_config.format (json_schema) throughout. Tests: 47 new tests (config/findings/correlation/hooks unit + pipeline integration with a MockProvider, no API key needed). Full suite 163 passing. Adds AIAnalysis flake8 job to the QAT workflow and documents the layer in the READMEs. https://claude.ai/code/session_015pBhzcxzBhLcAujgXrwsaz
1 parent e1296a8 commit 3ea7ca5

21 files changed

Lines changed: 1701 additions & 1 deletion

.github/workflows/qat.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,20 @@ jobs:
4646
--count
4747
continue-on-error: true
4848

49+
- name: Run flake8 on AI Analysis layer
50+
run: |
51+
flake8 Scripts/AIAnalysis/ \
52+
--max-line-length=120 \
53+
--extend-ignore=E501,W503,E402 \
54+
--statistics \
55+
--count
56+
continue-on-error: true
57+
4958
- name: Run flake8 on tests
5059
run: |
5160
flake8 tests/ \
5261
--max-line-length=120 \
53-
--extend-ignore=E501,W503 \
62+
--extend-ignore=E501,W503,E402 \
5463
--statistics \
5564
--count
5665

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ It wraps the Veracode REST and XML APIs with helper scripts, automated analysis
4343
| `vdb-purl-lte.sh` | Bash | Veracode vulnerability DB PURL lookup (lite) |
4444
| `veracode-installer.sh` | Bash | Install and configure Veracode CLI tooling |
4545

46+
### Scripts/AIAnalysis — AI Analysis Layer
47+
48+
Model-agnostic pipeline that correlates findings across scan types, uses Claude
49+
models to reduce false positives, and chains related findings into risk paths.
50+
New frontier models (Claude Mythos 5, future releases) are onboarded by editing
51+
`models.json` — no code changes. See [Scripts/AIAnalysis/README.md](Scripts/AIAnalysis/README.md).
52+
53+
| File | Purpose |
54+
|---|---|
55+
| `analyze.py` | CLI entry point (offline correlation or full AI pipeline) |
56+
| `models.json` | Model registry — enable/disable models and assign roles |
57+
| `veracode_ai/` | Package: config, findings normalization, correlation, validation, chaining, hooks |
58+
4659
### Scripts/Dev — In Development
4760

4861
| Directory | Contents |

Scripts/AIAnalysis/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Veracode AI Analysis Layer
2+
3+
A model-agnostic pipeline that sits on top of the Veracode scripts and adds
4+
**cross-scan correlation**, **AI-assisted false-positive reduction**, and
5+
**risk chaining** using one or more Claude models.
6+
7+
It is built so that **Claude Mythos 5 and future frontier models can be
8+
switched on with a config edit** — no code changes — to validate and feed
9+
into the results, reduce false positives, and surface a deeper breadth of
10+
chained findings.
11+
12+
---
13+
14+
## What it does
15+
16+
```
17+
Veracode scans AI Analysis Layer Output
18+
┌──────────────┐ normalize ┌────────────────────────────┐ ┌──────────────┐
19+
│ SAST (STATIC)│──────────────▶│ 1. Correlate (deterministic)│ │ risk chains │
20+
│ DAST │ │ 2. Validate (model panel) │──▶│ FP verdicts │
21+
│ SCA │ │ 3. Chain (model) │ │ correlations │
22+
│ Container │ └────────────────────────────┘ └──────────────┘
23+
└──────────────┘ driven entirely by models.json
24+
```
25+
26+
1. **Normalize** every scan type into one `UnifiedFinding` shape.
27+
2. **Correlate** (offline, rule-based — runs in CI with no API key):
28+
- **cross-layer confirmation** — same CWE found by SAST *and* DAST (present in code *and* reachable at runtime)
29+
- **common flaw source** — static findings sharing a data-path source (fix once, remediate many)
30+
- **shared CVE** — the same CVE in both SCA and container scans (confirmed in the deployed artifact)
31+
- **dependency usage** — a vulnerable SCA component referenced by first-party flawed code
32+
3. **Validate** — every enabled validator model independently tries to *refute*
33+
each finding; a consensus quorum decides confirmed vs. likely-false-positive.
34+
4. **Chain** — a chain-role model composes correlated findings into ordered
35+
attack paths with combined severity, remediation order, and a recommended
36+
security-training topic.
37+
38+
---
39+
40+
## Onboarding a new frontier model (Mythos / next model)
41+
42+
Edit [`models.json`](models.json) — set `"enabled": true`. That's the whole change.
43+
44+
```jsonc
45+
"mythos": {
46+
"id": "claude-mythos-5",
47+
"enabled": true, // ← flip this on
48+
"thinking": "omit", // Fable/Mythos: thinking always on, send no config
49+
"effort": "xhigh",
50+
"max_tokens": 16000,
51+
"fallback_model": "claude-opus-4-8", // refusal fallback via server-side beta
52+
"roles": ["deep-validate", "chain", "second-opinion"]
53+
}
54+
```
55+
56+
The new model immediately:
57+
- joins the **validator panel** (a `deep-validate` vote runs alongside the existing votes),
58+
- runs in the **chain stage** (its chains are tagged with its model id so you can compare),
59+
- and requests are shaped correctly for its family (adaptive thinking vs. omit,
60+
effort level, server-side refusal fallback).
61+
62+
A model that isn't served yet (404) is disabled for that run and the pipeline
63+
degrades gracefully — so you can enable a registry entry ahead of GA without
64+
breaking CI.
65+
66+
**Roles**: `triage`, `validate`, `deep-validate`, `correlate`, `chain`, `second-opinion`.
67+
68+
---
69+
70+
## Operational hooks
71+
72+
Every stage fires a hook so external tooling — including a future frontier
73+
model running *alongside* the pipeline — can observe or transform the data
74+
without editing pipeline code:
75+
76+
```python
77+
from veracode_ai.hooks import hooks
78+
79+
@hooks.register("post_validate")
80+
def route_low_confidence(payload):
81+
# payload = {"finding": ..., "verdict": ..., "votes": [...]}
82+
# e.g. send split-vote findings to a frontier model for a second opinion
83+
return payload
84+
```
85+
86+
Hook points, in order: `pre_ingest`, `post_normalize`, `pre_correlate`,
87+
`post_correlate`, `pre_validate`, `post_validate`, `pre_chain`, `post_chain`,
88+
`report`.
89+
90+
---
91+
92+
## Usage
93+
94+
```bash
95+
# Offline correlation only — no API key, CI-safe
96+
python analyze.py --rest findings.json --offline -o report.json
97+
98+
# Full pipeline: correlate + FP-reduce + risk-chain
99+
export ANTHROPIC_API_KEY=...
100+
python analyze.py \
101+
--rest findings.json \
102+
--container image-scan.json \
103+
-o report.json
104+
105+
# Show the enabled model roster
106+
python analyze.py --print-models
107+
```
108+
109+
`--rest` takes a Veracode REST Findings API response
110+
(`GET /appsec/v2/applications/{guid}/findings`, any scan type). `--container`
111+
takes Veracode CLI container scan JSON.
112+
113+
### As a library
114+
115+
```python
116+
from veracode_ai import load_registry
117+
from veracode_ai.pipeline import Pipeline
118+
from veracode_ai.providers import Provider
119+
120+
pipeline = Pipeline(registry=load_registry(), provider=Provider())
121+
report = pipeline.analyze({"rest": "findings.json", "container": "image.json"})
122+
```
123+
124+
---
125+
126+
## Design notes
127+
128+
- **Model-agnostic**: no model id is hard-coded in the pipeline; everything
129+
comes from `models.json` via the registry.
130+
- **Structured outputs**: every model call uses `output_config.format`
131+
(`json_schema`), so responses are guaranteed-parseable — no fragile text scraping.
132+
- **Family-aware requests**: `providers.py` sends `thinking={"type":"adaptive"}`
133+
for Opus/Sonnet, omits `thinking` entirely for Fable/Mythos (where it's always
134+
on), and attaches server-side refusal fallbacks when a `fallback_model` is set.
135+
- **Adversarial validation**: validators are prompted to *refute* findings, and
136+
a finding only becomes a likely-FP on a quorum — biased toward not silently
137+
dropping real bugs.
138+
- **Offline-first**: correlation needs only the standard library, so it runs in
139+
every CI job; the model stages are additive.
140+
141+
Requirements: `pip install -r requirements.txt` (only needed for the
142+
validate/chain stages; correlation is stdlib-only).

Scripts/AIAnalysis/analyze.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python3
2+
"""Veracode AI Analysis — CLI entry point.
3+
4+
Correlate and validate findings across Veracode scan types with one or more
5+
Claude models. Model selection is driven entirely by models.json.
6+
7+
Examples:
8+
# Offline correlation only (no API key needed) — CI-safe
9+
python analyze.py --rest findings.json --offline -o report.json
10+
11+
# Full pipeline: correlate + FP-reduce + risk-chain
12+
export ANTHROPIC_API_KEY=...
13+
python analyze.py --rest findings.json --container image.json -o report.json
14+
15+
Onboarding a new frontier model (e.g. Claude Mythos 5): set its
16+
"enabled": true in models.json. No code change, no CLI flag.
17+
"""
18+
19+
import argparse
20+
import json
21+
import sys
22+
23+
sys.path.insert(0, __file__.rsplit("/", 1)[0])
24+
25+
from veracode_ai.config import load_registry
26+
from veracode_ai.pipeline import Pipeline
27+
28+
29+
def main():
30+
parser = argparse.ArgumentParser(description="Veracode AI cross-scan analysis")
31+
parser.add_argument("--rest", help="Veracode REST Findings API JSON (any scan type)")
32+
parser.add_argument("--container", help="Container scan JSON (Veracode CLI)")
33+
parser.add_argument("--config", help="Path to models.json (default: bundled)")
34+
parser.add_argument("-o", "--output", default="ai-analysis-report.json")
35+
parser.add_argument("--offline", action="store_true",
36+
help="Correlation only; no model calls (no API key needed)")
37+
parser.add_argument("--print-models", action="store_true",
38+
help="Print the enabled model roster and exit")
39+
args = parser.parse_args()
40+
41+
registry = load_registry(args.config)
42+
43+
if args.print_models:
44+
for m in registry.enabled_models():
45+
print(f"{m.key:8} {m.id:20} roles={','.join(m.roles)}")
46+
return 0
47+
48+
scan_payloads = {}
49+
if args.rest:
50+
scan_payloads["rest"] = args.rest
51+
if args.container:
52+
scan_payloads["container"] = args.container
53+
if not scan_payloads:
54+
parser.error("provide at least one of --rest / --container")
55+
56+
provider = None
57+
if not args.offline:
58+
try:
59+
from veracode_ai.providers import Provider
60+
provider = Provider()
61+
except RuntimeError as exc:
62+
print(f"[WARN] {exc}\n[WARN] Falling back to --offline mode.", file=sys.stderr)
63+
64+
pipeline = Pipeline(registry=registry, provider=provider)
65+
report = pipeline.analyze(scan_payloads, offline=args.offline or provider is None)
66+
67+
with open(args.output, "w") as f:
68+
json.dump(report, f, indent=2)
69+
70+
print(f"[INFO] mode={report['mode']} findings={report['total_findings']} "
71+
f"correlations={len(report['correlations'])} "
72+
f"chains={len(report.get('risk_chains', []))}")
73+
print(f"[INFO] wrote {args.output}")
74+
return 0
75+
76+
77+
if __name__ == "__main__":
78+
sys.exit(main())

Scripts/AIAnalysis/models.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"_comment": "Model registry for the Veracode AI analysis layer. To onboard a new frontier model (e.g. Claude Mythos 5) set enabled=true — no code changes required. Roles: triage | validate | deep-validate | correlate | chain | second-opinion",
3+
4+
"models": {
5+
"opus": {
6+
"id": "claude-opus-4-8",
7+
"enabled": true,
8+
"thinking": "adaptive",
9+
"effort": "high",
10+
"max_tokens": 16000,
11+
"roles": ["triage", "validate", "correlate", "chain"]
12+
},
13+
"sonnet": {
14+
"id": "claude-sonnet-5",
15+
"enabled": true,
16+
"thinking": "adaptive",
17+
"effort": "medium",
18+
"max_tokens": 8000,
19+
"roles": ["validate"]
20+
},
21+
"fable": {
22+
"id": "claude-fable-5",
23+
"enabled": false,
24+
"thinking": "omit",
25+
"effort": "high",
26+
"max_tokens": 16000,
27+
"fallback_model": "claude-opus-4-8",
28+
"roles": ["deep-validate", "chain", "second-opinion"]
29+
},
30+
"mythos": {
31+
"id": "claude-mythos-5",
32+
"enabled": false,
33+
"thinking": "omit",
34+
"effort": "xhigh",
35+
"max_tokens": 16000,
36+
"fallback_model": "claude-opus-4-8",
37+
"roles": ["deep-validate", "chain", "second-opinion"]
38+
}
39+
},
40+
41+
"strategies": {
42+
"fp_reduction": {
43+
"mode": "consensus",
44+
"validator_roles": ["validate", "deep-validate"],
45+
"quorum_fraction": 0.5,
46+
"batch_size": 10
47+
},
48+
"risk_chaining": {
49+
"chain_roles": ["chain"],
50+
"max_findings_per_request": 60
51+
},
52+
"second_opinion": {
53+
"roles": ["second-opinion"]
54+
}
55+
}
56+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Veracode AI analysis layer
2+
# Offline correlation needs no dependencies (stdlib only).
3+
# The validate/chain stages require the Anthropic SDK:
4+
anthropic>=0.69.0
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Veracode AI analysis layer.
2+
3+
Model-agnostic pipeline that correlates findings across Veracode scan types
4+
(SAST, DAST, SCA, container), validates them with one or more Claude models
5+
to reduce false positives, and chains related findings into risk paths.
6+
7+
New frontier models (Claude Mythos 5, future releases) are onboarded by
8+
editing models.json — no code changes required.
9+
"""
10+
11+
from .config import ModelConfig, Registry, load_registry
12+
from .findings import UnifiedFinding, normalize_findings
13+
from .hooks import HookRegistry, hooks
14+
15+
__all__ = [
16+
"ModelConfig",
17+
"Registry",
18+
"load_registry",
19+
"UnifiedFinding",
20+
"normalize_findings",
21+
"HookRegistry",
22+
"hooks",
23+
]

0 commit comments

Comments
 (0)