Report Type

Technical Analysis

Deep-dive technical reports for security engineers and developers. Includes code context, data flow diagrams, and remediation guidance.

Overview

Technical analysis reports provide the detailed information developers need to understand and fix vulnerabilities. Each finding includes full code context, data flow traces, and specific remediation instructions.

Bash
1# Generate technical analysis report
2bloodhound report technical --output analysis.html
3
4# JSON format for integration with other tools
5bloodhound report technical --format json --output analysis.json
6
7# Focus on specific severity levels
8bloodhound report technical --severity critical,high --output critical-analysis.md
9
10# Include full code context (±20 lines)
11bloodhound report technical --context 20 --output detailed-analysis.html
Full Context
Code snippets
Data Flow
Trace diagrams
Fix Code
Ready to apply

Finding Details

Each finding in the technical report includes comprehensive details for understanding and fixing the issue.

Text
1# Sample Technical Finding
2
3═══════════════════════════════════════════════════════════════════
4FINDING: SQL-INJ-001
5═══════════════════════════════════════════════════════════════════
6
7Title: SQL Injection via User Input
8Severity: CRITICAL
9CWE: CWE-89 (SQL Injection)
10CVSS: 9.8 (Critical)
11File: src/api/users/controller.ts
12Line: 142
13Function: getUserById()
14
15DESCRIPTION
16───────────────────────────────────────────────────────────────────
17User-supplied input from the 'id' parameter is concatenated directly
18into an SQL query without sanitization or parameterization. An
19attacker can inject arbitrary SQL commands to read, modify, or
20delete database contents.
21
22DETECTION ENGINE
23───────────────────────────────────────────────────────────────────
24Primary: Taint Analysis (confidence: 98%)
25Confirmed by: Pattern Matching, SAST
26
27EXPLOITABILITY
28───────────────────────────────────────────────────────────────────
29Attack Vector: Network (public API endpoint)
30Complexity: Low (no authentication required)
31Privileges: None
32User Interaction: None
33
34PROOF OF CONCEPT
35───────────────────────────────────────────────────────────────────
36Request:
37 GET /api/users/1' OR '1'='1' --
38
39Expected Result:
40 Returns all users in database, bypassing ID filter
41
42Automated Test:
43 bloodhound test SQL-INJ-001 --target http://localhost:3000

Code Context

Full code context with syntax highlighting and vulnerability markers.

Text
1VULNERABLE CODE
2───────────────────────────────────────────────────────────────────
3File: src/api/users/controller.ts
4
5 135 │ import { db } from '../database';
6 136 │ import { Request, Response } from 'express';
7 137 │
8 138 │ export async function getUserById(req: Request, res: Response) {
9 139 │ const userId = req.params.id; // ← TAINT SOURCE
10 140 │
11 141 │ // VULNERABILITY: Unsanitized user input in SQL query
12 ► 142 │ const query = `SELECT * FROM users WHERE id = '${userId}'`;
13 │ ^^^^^^^^
14 │ TAINT SINK
15 143 │
16 144 │ try {
17 145 │ const result = await db.query(query); // ← SQL executed
18 146 │ res.json(result.rows[0]);
19 147 │ } catch (error) {
20 148 │ res.status(500).json({ error: 'Database error' });
21 149 │ }
22 150 │ }
23
24TAINT FLOW
25───────────────────────────────────────────────────────────────────
26req.params.id (line 139)
27
28 ▼ [Assignment]
29userId (line 139)
30
31 ▼ [String Interpolation]
32query (line 142) ← SQL Injection Point
33
34 ▼ [Function Argument]
35db.query(query) (line 145) ← SQL Execution

Data Flow Analysis

Visual representation of how tainted data flows through your application.

Text
1DATA FLOW DIAGRAM
2───────────────────────────────────────────────────────────────────
3
4┌─────────────────────────────────────────────────────────────────┐
5│ HTTP Request │
6│ GET /api/users/:id │
7└─────────────────────────────────────────────────────────────────┘
8
9
10┌─────────────────────────────────────────────────────────────────┐
11│ Express Router │
12│ routes/users.ts:12 │
13│ router.get('/:id', getUserById) │
14└─────────────────────────────────────────────────────────────────┘
15
16
17┌─────────────────────────────────────────────────────────────────┐
18│ Controller │
19│ controller.ts:139 │
20│ const userId = req.params.id ◄── TAINT SOURCE │
21└─────────────────────────────────────────────────────────────────┘
22
23 ▼ (propagates through assignment)
24┌─────────────────────────────────────────────────────────────────┐
25│ String Template │
26│ controller.ts:142 │
27│ `SELECT * FROM users WHERE id = '${userId}'` ◄── TAINT SINK │
28│ │
29│ ⚠️ NO SANITIZER APPLIED │
30└─────────────────────────────────────────────────────────────────┘
31
32
33┌─────────────────────────────────────────────────────────────────┐
34│ Database Adapter │
35│ database.ts:45 │
36│ pool.query(queryString) ◄── SQL EXECUTION │
37└─────────────────────────────────────────────────────────────────┘
38
39MISSING SANITIZERS
40───────────────────────────────────────────────────────────────────
41The following sanitizers would have prevented this vulnerability:
42
43• db.query() with parameterized query: db.query('SELECT ... WHERE id = $1', [id])
44• Input validation: parseInt(id) or UUID validation
45• ORM usage: User.findByPk(id) (Sequelize) or prisma.user.findUnique()

Engine Insights

Understand how each analysis engine contributed to the finding.

Text
1ENGINE ANALYSIS
2───────────────────────────────────────────────────────────────────
3
4┌─────────────────────────────────────────────────────────────────┐
5│ Engine 1: Pattern Matching │
6├─────────────────────────────────────────────────────────────────┤
7│ Matched Pattern: sql-injection-template-literal │
8│ Confidence: HIGH (92%) │
9│ Regex: /\`SELECT.*FROM.*WHERE.*\$\{.*\}\`/ │
10│ Note: Template literal with variable interpolation in SQL │
11└─────────────────────────────────────────────────────────────────┘
12
13┌─────────────────────────────────────────────────────────────────┐
14│ Engine 4: Taint Analysis │
15├─────────────────────────────────────────────────────────────────┤
16│ Taint Source: req.params (HTTP request parameter) │
17│ Taint Sink: db.query() (SQL execution) │
18│ Path Length: 3 nodes │
19│ Sanitizers Found: 0 │
20│ Confidence: VERY HIGH (98%) │
21│ │
22│ Interprocedural: YES (crosses function boundaries) │
23│ Cross-file: YES (routes/users.ts → controller.ts → database.ts) │
24└─────────────────────────────────────────────────────────────────┘
25
26┌─────────────────────────────────────────────────────────────────┐
27│ Engine 7: AI Verification │
28├─────────────────────────────────────────────────────────────────┤
29│ False Positive Check: PASSED (this is a real vulnerability) │
30│ │
31│ AI Analysis: │
32│ "The req.params.id value is used directly in a SQL template │
33│ string without any validation, escaping, or parameterization. │
34│ The db.query() function executes raw SQL, making this a │
35│ confirmed SQL injection vulnerability." │
36│ │
37│ Severity Calibration: CRITICAL (no changes from base score) │
38│ Reason: Public endpoint, no authentication, database access │
39└─────────────────────────────────────────────────────────────────┘

Remediation Code

Ready-to-apply fixes tailored to your codebase patterns.

Diff
1RECOMMENDED FIX
2───────────────────────────────────────────────────────────────────
3
4Option 1: Parameterized Query (Recommended)
5───────────────────────────────────────────────────────────────────
6
7- const query = `SELECT * FROM users WHERE id = '${userId}'`;
8- const result = await db.query(query);
9+ const query = 'SELECT * FROM users WHERE id = $1';
10+ const result = await db.query(query, [userId]);
11
12
13Option 2: Input Validation + Parameterization
14───────────────────────────────────────────────────────────────────
15
16+ import { z } from 'zod';
17+
18+ const userIdSchema = z.string().uuid();
19+
20 export async function getUserById(req: Request, res: Response) {
21- const userId = req.params.id;
22+ const parseResult = userIdSchema.safeParse(req.params.id);
23+ if (!parseResult.success) {
24+ return res.status(400).json({ error: 'Invalid user ID format' });
25+ }
26+ const userId = parseResult.data;
27
28 const query = 'SELECT * FROM users WHERE id = $1';
29 const result = await db.query(query, [userId]);
30
31
32Option 3: Use ORM (Your codebase uses Prisma elsewhere)
33───────────────────────────────────────────────────────────────────
34
35+ import { prisma } from '../prisma';
36
37 export async function getUserById(req: Request, res: Response) {
38- const userId = req.params.id;
39- const query = `SELECT * FROM users WHERE id = '${userId}'`;
40- const result = await db.query(query);
41- res.json(result.rows[0]);
42+ const user = await prisma.user.findUnique({
43+ where: { id: req.params.id }
44+ });
45+ if (!user) {
46+ return res.status(404).json({ error: 'User not found' });
47+ }
48+ res.json(user);
49 }
50
51
52APPLY FIX
53───────────────────────────────────────────────────────────────────
54# Preview the fix
55bloodhound fix SQL-INJ-001 --preview
56
57# Apply automatically
58bloodhound fix SQL-INJ-001 --apply
59
60# Apply with specific option
61bloodhound fix SQL-INJ-001 --option 2 --apply

Automatic Fixes

Use bloodhound fix --apply to automatically apply fixes. Changes are staged for review before committing.