The Code Security & Risk Intelligence Agent is an advanced, production-grade security analysis CLI tool designed to bridge the gap between static code scanning and actual exploitability.
Traditional dependency scanners flood development teams with CVE alerts, most of which are unreachable from the application code. This agent addresses that problem by combining deterministic AST-based reachability analysis with LLM risk reasoning to calculate the real-world impact and likelihood of exploitation for each dependency vulnerability.
The agent is built using Clean Architecture patterns, routing execution through a sequential pipeline orchestrator starting from the CLI request.
graph TD
User([User CLI Scan request]) --> Scan[scan.py CLI Entrypoint]
Scan --> Orch[Pipeline Orchestrator]
subgraph Services & Parsers
Orch --> RM[Repository Manager]
Orch --> MP[Manifest Parser]
Orch --> AP[AST Code Parser]
end
subgraph Pipelines & Agents
Orch --> DepA[Dependency Intel Agent OSV.dev]
Orch --> ScanA[Security Scanner Agent Bandit + pip-audit]
Orch --> ReachA[Reachability Analysis Agent AST Caller Graph]
Orch --> ReasonA[Risk Reasoning LLM Agent]
Orch --> ReportA[Report Generator Agent Markdown + JSON]
end
ReportA --> Output[/Markdown + JSON Reports/]
- Core Engine: Python 3.12
- Deterministic Checkers: Bandit (AST SAST), pip-audit (manifest vulnerability auditor)
- Vulnerability Data: OSV.dev REST API
- Git Provider: GitPython
- LLM Reasoning Engine: Gemini 1.5 Flash / Gemini 3.1 Flash-Lite (REST API v1beta JSON schema execution, configurable in
.env) - Data Schemas: Pydantic v2
- Testing Suite: pytest
- Python 3.12+
- Git (installed on system PATH)
- Clone or copy the project directory to your local environment.
- Initialize virtual environment and install dependencies:
python -m venv venv venv\Scripts\activate.bat # On Linux/macOS use: source venv/bin/activate pip install -r requirements.txt
- Configure environment variables in a
.envfile at the root of the project:GEMINI_API_KEY=your_gemini_api_key_here LLM_MODEL=gemini-flash-lite-latest LOG_LEVEL=INFO
To scan a public GitHub repository directly from the command line:
python scan.py https://github.com/bottlepy/bottleTo target a specific branch or release tag (recommended for analyzing older, vulnerable versions of codebases):
python scan.py https://github.com/psf/requests --branch v2.25.0The resulting markdown report and raw JSON data will be written directly to the reports/ folder.
The agent calculates the final threat level using a structured formula prioritizing deterministic evidence first:
- CVSS: Vulnerability base rating (0.0 to 10.0). Defaults to 5.0 if missing.
- Reachability: Checked programmatically via AST caller chains:
Possibly Reachable= 0.8 (Confirmed direct or transitive call chain to package boundary)Possibly Reachable (No Active Chain)= 0.6 (Package is imported and used, but no active entry points map to it)Not Reachable= 0.1 (Package is not imported anywhere in the codebase)
- Exposure:
Possibly Reachable= 0.5Not Reachable= 0.1
- Business Impact: Exploit impact rated by the Gemini Reasoning Agent (0.0 to 1.0) depending on exploit context (e.g. Remote Code Execution vs. simple Denial of Service).
- Reachability Tracing: For each vulnerable dependency, the agent locates its imports via AST parsing, finds every function referencing them, and statically traces whether any call chain reaches a public entry point — an application/test entry function, route, or CLI command.
The agent's capabilities were validated against 15 public Python repositories to measure vulnerability detection accuracy. Below are the actual vulnerability counts discovered for each repository:
| Repository Name | Scan Target / Version | Dependency Vulnerabilities Discovered | Report File Link |
|---|---|---|---|
| requests | Tag v2.25.0 |
17 | View Report |
| Pillow | Tag 8.0.0 |
15 | View Report |
| cookiecutter | Tag v1.7.2 |
15 | View Report |
| paramiko | Tag v2.4.0 |
14 | View Report |
| flask | Tag 1.1.2 |
10 | View Report |
| urllib3 | Tag 1.26.4 |
1 | View Report |
| bottle | Tag 0.12.19 |
1 | View Report |
| oyaml | Latest master branch |
0 | View Report |
| werkzeug | Latest main branch |
0 | View Report |
| click | Latest main branch |
0 | View Report |
| starlette | Tag 0.14.1 |
21 | View Report |
| lxml | Latest master branch |
0 | View Report |
| pluggy | Latest main branch |
0 | View Report |
| jinja | Latest main branch |
0 | View Report |
| typer | Latest master branch |
0 | View Report |
- Placeholder reasoning output: Early reports showed generic filler text ("Vulnerability assessed by reasoning agent") instead of real LLM reasoning.
- Actual Fix: Resolved the JSON schema parsing of the LLM responses and integrated the
RiskAssessmentobject from the reasoning agent directly into the markdown report generator template.
- Actual Fix: Resolved the JSON schema parsing of the LLM responses and integrated the
- Contradictory reachability verdicts: Findings were marked "Possibly Reachable" in some tables even when the reachability trace found no call chain at all, or vice-versa.
- Actual Fix: Unified the reachability agent's findings to consistently reflect
"Possibly Reachable"for any verified call path flowing to package boundaries, ensuring both the reasoning agent's 429 rate limit/503 service unavailable fallbacks and AST reachability outputs are mathematically and logically aligned.
- Actual Fix: Unified the reachability agent's findings to consistently reflect
- Generic, non-differentiated risk scores: Business impact and exploitation likelihood landed on nearly identical values across unrelated vulnerabilities because the prompt gave the LLM a numeric range with no grounding instructions.
- Actual Fix: Added explicit, evidence-based scoring rules and an anti-repetition instruction to the reasoning prompt.
- CVSS Vector Parsing Error: Google's OSV API returned CVSS base vectors as strings inside its
scorefield, causing float conversionValueErrorand falling back to a hardcoded5.0.- Actual Fix: Implemented a native CVSS v3 math parsing engine in
reasoning_agent/agent.pyto calculate exact decimal CVSS scores locally.
- Actual Fix: Implemented a native CVSS v3 math parsing engine in
- Duplicate Representative Call Paths: The AST parser matched multiple call sites within the same entry point function, causing the report to list identical representative paths multiple times.
- Actual Fix: Implemented a deduplication filter in the reporting agent based on unique entry points and prioritized production source call paths (
src/,app/) over test files.
- Actual Fix: Implemented a deduplication filter in the reporting agent based on unique entry points and prioritized production source call paths (
- AST Parsing Limits: Standard static AST parsing cannot detect dynamic calls (e.g.,
getattr(module, func_name)()),eval(), or dependencies imported inside dynamically executed strings. - Ecosystem Limitation: Currently supports only the Python codebase and ecosystem (
requirements.txt,pyproject.toml,Pipfile,poetry.lock). - Reachability findings are evidence-based, not proofs: "Not Reachable" means no path was found, not that one is provably impossible.