Status: IMPLEMENTATION COMPLETE (Build verified:
next buildpasses) Last updated: 2026-02-09
This plan is authored from three perspectives working in concert:
| Role | Perspective |
|---|---|
| Agent 1 β Principal Security Review Engineer | Defines the security spec, threat grammar, frameworks, and acceptance criteria |
| Agent 2 β Principal SDE | Designs the system architecture, APIs, data models, and writes the automation code |
| Agent 3 β Customer Engineer | Submits a real GitHub repo and validates the end-to-end flow as a user |
Build an automated threat modeling pipeline that accepts a GitHub repository URL (or a design document) and produces:
- Data Flow Diagram (DFD) β visual representation of components, trust boundaries, data stores, and external entities
- Threat List β structured threat statements using AWS Threat Grammar, mapped to STRIDE categories
- Insights Dashboard β quality metrics (STRIDE coverage, mitigation rate, severity distribution)
- Threat Detail with Mitigations β when a repo is the source, generate code-level fixes; when a doc is the source, generate prose-based mitigation suggestions
- Apply Fix β a button that applies the generated code fix (creates a PR or applies locally), and transitions the threat status from "Identified" to "Mitigated"
Every generated threat statement MUST follow this grammar:
A [threat source] with [prerequisites] can [threat action],
which leads to [threat impact], negatively impacting [impacted assets].
Fields per threat:
| Field | Description | Example |
|---|---|---|
threatSource |
The entity performing the threat | "An authenticated tenant user" |
prerequisites |
Conditions that make the threat viable | "with access to the API and knowledge of building IDs" |
threatAction |
The action taken | "can modify the building_id parameter in HVAC setpoint API calls" |
threatImpact |
The direct result | "leading to unauthorized temperature manipulation in critical facilities" |
impactedAssets |
What is negatively affected | "HVAC Control Plane, Tenant Data Isolation" |
strideCategory |
STRIDE classification | "Elevation of Privilege" |
The system must classify each threat into exactly one STRIDE category:
| Category | Security Property | Detection Pattern |
|---|---|---|
| Spoofing | Authentication | Hardcoded creds, missing auth checks, session fixation |
| Tampering | Integrity | Missing input validation, no message signing, unsigned artifacts |
| Repudiation | Non-Repudiation | Missing audit logs, mutable log storage, no action attribution |
| Information Disclosure | Confidentiality | Exposed secrets, verbose errors, missing encryption, debug endpoints |
| Denial of Service | Availability | Missing rate limits, unbounded queries, resource exhaustion |
| Elevation of Privilege | Authorization | Missing RBAC, IDOR, broken access control, privilege escalation |
When "OWASP Top 10" is selected as the framework, map threats to:
| ID | Category | Relevant Threat Patterns |
|---|---|---|
| A01 | Broken Access Control | IDOR, missing function-level access control, CORS misconfiguration |
| A02 | Cryptographic Failures | Weak algorithms, hardcoded keys, plaintext storage |
| A03 | Injection | SQLi, XSS, command injection, LDAP injection |
| A04 | Insecure Design | Missing threat model, no defense in depth, business logic flaws |
| A05 | Security Misconfiguration | Default creds, unnecessary features, missing headers |
| A06 | Vulnerable Components | Outdated dependencies, known CVEs in deps |
| A07 | Auth Failures | Credential stuffing, weak passwords, missing MFA |
| A08 | Software & Data Integrity | Unsigned updates, insecure CI/CD, deserialization flaws |
| A09 | Logging & Monitoring | Missing audit trails, no alerting, insufficient logging |
| A10 | SSRF | Unvalidated URL fetches, internal service exposure |
- Each threat MUST have a structured threat statement following AWS Threat Grammar
- Each threat MUST be classified into a STRIDE category (or OWASP A01-A10 if that framework is selected)
- Each threat MUST have a severity (Critical/High/Medium/Low) with rationale
- Each threat from a repo source MUST have at least one code-level mitigation with before/after diff
- Each threat from a doc source MUST have at least one prose mitigation suggestion
- The DFD MUST show trust boundaries, data flows, processes, and external entities
- The "Apply Fix" action MUST create a branch and PR (or apply locally via VS Code)
- Mitigated threats MUST transition status from "Identified" β "Mitigated"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FRONTEND (Next.js 16) β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββββββ β
β β Session β β DFD β β Threat β β Threat Detail β β
β β Manager β β Viewer β β List β β + Apply Fix β β
β ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ ββββββββ¬βββββββββ β
β β β β β β
β ββββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββ β
β β API Calls β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β API LAYER (Next.js Route Handlers) β
β POST /api/threat-model/sessions β Create session β
β GET /api/threat-model/sessions/:id β Get session + threatsβ
β POST /api/threat-model/sessions/:id/analyze β Trigger analysis β
β GET /api/threat-model/sessions/:id/dfd β Get DFD data β
β POST /api/threat-model/threats/:id/apply-fix β Apply fix β
β PATCH /api/threat-model/threats/:id β Update threat status β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β BACKEND SERVICES β
β βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββββ β
β β Repo Analyzer β β Threat Engine β β Fix Generator β β
β β (GitHub Clone β β (LLM-powered β β (Code Patch β β
β β + AST Parse) β β STRIDE/OWASP) β β + PR Create) β β
β ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ βββββββββ¬βββββββββ β
β β β β β
β ββββββββββ΄βββββββββ βββββββββ΄βββββββββ βββββββββ΄βββββββββ β
β β DFD Generator β β Insight Engine β β Git Service β β
β β (Architecture β β (Quality β β (Branch + PR β β
β β β Mermaid DFD) β β Metrics) β β via GitHub) β β
β βββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β DATA / EXTERNAL β
β βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββββ β
β β GitHub API β β Claude/LLM API β β Local SQLite β β
β β (Repo access, β β (Threat gen, β β (Session & β β
β β PR creation) β β DFD gen, β β threat store) β β
β β β β fix gen) β β β β
β βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Files to create:
app/api/threat-model/
βββ sessions/
β βββ route.ts β POST (create), GET (list all)
β βββ [id]/
β βββ route.ts β GET (session detail), PATCH (update)
β βββ analyze/
β βββ route.ts β POST (trigger analysis pipeline)
βββ threats/
β βββ [id]/
β βββ route.ts β PATCH (update status)
β βββ apply-fix/
β βββ route.ts β POST (apply code fix, create PR)
lib/
βββ threat-engine/
β βββ repo-analyzer.ts β Clone repo, extract file structure, identify architecture
β βββ threat-generator.ts β LLM-powered STRIDE analysis, produce threat statements
β βββ dfd-generator.ts β Generate Mermaid DFD from repo architecture
β βββ insight-engine.ts β Compute quality metrics from threat list
β βββ fix-generator.ts β Generate code-level fixes for each threat
β βββ git-service.ts β GitHub API: clone, branch, commit, PR
βββ threat-data.ts β (existing) Types + mock data
βββ db.ts β SQLite session/threat persistence
Database schema (SQLite via better-sqlite3):
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
source TEXT CHECK(source IN ('design-doc', 'github-repo')),
source_ref TEXT,
framework TEXT DEFAULT 'STRIDE',
status TEXT DEFAULT 'Processing',
dfd_mermaid TEXT,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE threats (
id TEXT PRIMARY KEY,
session_id TEXT REFERENCES sessions(id),
title TEXT NOT NULL,
stride_category TEXT,
severity TEXT CHECK(severity IN ('Critical','High','Medium','Low')),
status TEXT DEFAULT 'Identified',
threat_source TEXT,
prerequisites TEXT,
threat_action TEXT,
threat_impact TEXT,
impacted_assets TEXT,
trust_boundary TEXT,
assumptions TEXT, -- JSON array
related_cve TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE mitigations (
id TEXT PRIMARY KEY,
threat_id TEXT REFERENCES threats(id),
description TEXT NOT NULL,
status TEXT DEFAULT 'Proposed',
code_file TEXT,
code_line INTEGER,
code_original TEXT,
code_fixed TEXT,
jira_key TEXT,
jira_summary TEXT,
jira_status TEXT
);The repo-analyzer.ts service will:
- Clone the repo β use
git clone --depth=1via child_process into a temp directory - Inventory the codebase β walk the file tree, identify:
- Languages used (by file extension)
- Framework detection (package.json, requirements.txt, go.mod, etc.)
- Entry points (main files, route definitions, API handlers)
- Configuration files (env, yaml, json configs)
- Infrastructure-as-code (Terraform, CloudFormation, Docker)
- Extract architecture signals β read key files to identify:
- External APIs called
- Database connections
- Authentication mechanisms
- Message queues / pub-sub (MQTT, Kafka, SQS)
- File upload endpoints
- Secret management patterns
- Produce a structured architecture summary β JSON object describing components, data flows, and trust boundaries
interface RepoAnalysis {
repoUrl: string;
languages: string[];
frameworks: string[];
components: {
name: string;
type: 'api' | 'service' | 'database' | 'queue' | 'gateway' | 'external';
files: string[];
description: string;
}[];
dataFlows: {
from: string;
to: string;
protocol: string;
dataType: string;
}[];
trustBoundaries: {
name: string;
components: string[];
}[];
securityFindings: {
file: string;
line: number;
pattern: string; // e.g., "hardcoded_secret", "missing_auth", "sql_concat"
snippet: string;
}[];
}The threat-generator.ts will use the Claude API (or configurable LLM) with a structured prompt:
System Prompt (Security Engineer persona):
You are a Principal Security Review Engineer performing a STRIDE-based threat model.
Given a repository architecture analysis, generate structured threat statements
following the AWS Threat Grammar:
"A [threat source] with [prerequisites] can [threat action],
which leads to [threat impact], negatively impacting [impacted assets]."
For each threat:
1. Classify into exactly one STRIDE category
2. Assign severity (Critical/High/Medium/Low) with justification
3. Identify the trust boundary being crossed
4. List assumptions
5. Propose at least one mitigation
If source code is available, provide specific file paths and line numbers
for both the vulnerable code and the proposed fix.
Output as structured JSON matching the Threat[] schema.
Input: RepoAnalysis JSON from Phase 2
Output: Threat[] array matching the existing data model
The dfd-generator.ts will:
- Take the
RepoAnalysis.components,dataFlows, andtrustBoundaries - Generate a Mermaid.js flowchart diagram string
- The frontend already has a static DFD β we will make it dynamic by rendering the Mermaid string
Frontend enhancement: Add mermaid npm package to render DFD diagrams dynamically instead of the current hardcoded component layout.
The fix-generator.ts will:
-
For repo sources:
- Read the identified vulnerable file from the cloned repo
- Use LLM to generate a specific code fix (before/after diff)
- Validate the fix compiles/parses (language-specific AST check)
-
For doc sources:
- Generate a prose mitigation suggestion
- No code diff, just descriptive guidance
The git-service.ts handles the "Apply Fix" flow:
- Fork or create a branch from the source repo (requires GitHub token)
- Apply the code change to the target file
- Commit with message:
fix: [threat-id] - [threat-title] - Open a PR against the default branch
- Return the PR URL to the frontend
- Update threat status to "Mitigated"
interface ApplyFixResult {
success: boolean;
prUrl?: string;
branch?: string;
commitSha?: string;
error?: string;
}Changes to existing app/threat-modeling/page.tsx:
- Connect to real API β replace
mockSessionwith API calls - New Session Dialog β wire up to
POST /api/threat-model/sessionsβPOST .../analyze - Processing State β poll session status via SSE or polling until analysis complete
- DFD Tab β render Mermaid diagram from API response instead of static layout
- Threat Detail Panel β add "Apply Fix" button with:
- Loading state while PR is being created
- Success state showing PR URL
- Threat status badge auto-updates to "Mitigated"
- Insights Tab β compute from real threat data instead of hardcoded values
New frontend components needed:
components/unitone/
βββ mermaid-diagram.tsx β Renders Mermaid DFD with zoom/pan
βββ apply-fix-button.tsx β Apply Fix button with PR creation flow
βββ threat-status-badge.tsx β Reactive status badge that updates on mitigation
| Component | Technology | Rationale |
|---|---|---|
| API | Next.js Route Handlers | Already in the stack, zero new infra |
| Database | SQLite (better-sqlite3) | Zero-config, file-based, sufficient for sessions |
| Git Operations | simple-git + Octokit | Clone repos, create PRs via GitHub API |
| LLM | Anthropic Claude API | Best code understanding for threat analysis |
| DFD Rendering | Mermaid.js | Already referenced in mock data, standard diagramming |
| File Analysis | Custom + tree-sitter (optional) | Walk repo, detect patterns |
{
"better-sqlite3": "^11.0.0",
"simple-git": "^3.27.0",
"@octokit/rest": "^21.0.0",
"@anthropic-ai/sdk": "^0.39.0",
"mermaid": "^11.4.0",
"uuid": "^11.0.0"
}GITHUB_TOKEN=ghp_... # GitHub PAT for repo cloning and PR creation
ANTHROPIC_API_KEY=sk-ant-... # Claude API key for threat generation
THREAT_MODEL_DB_PATH=./data/threats.db # SQLite database file pathAs an engineer on the JCI Smart Building team, I want to submit a GitHub repo and get a full threat model.
- Navigate to
/threat-modeling - Click "New Session"
- Select "GitHub Repo"
- Enter:
https://github.com/juice-shop/juice-shop(OWASP Juice Shop β intentionally vulnerable app) - Select framework: "STRIDE"
- Click "Generate Threat Model"
- Verify: Processing animation shows all 6 steps completing
- Verify: Session appears with status "Review"
- Verify DFD tab: Shows components (Express API, Angular SPA, SQLite DB, etc.) with trust boundaries
- Verify Threat List: At least 5 threats generated, each with:
- Structured threat statement
- STRIDE category
- Severity
- At least one mitigation with code diff
- Click on a Critical threat (e.g., SQL injection)
- Verify: Slide-over shows before/after code diff with file path and line number
- Click "Apply Fix"
- Verify: PR is created on a fork/branch
- Verify: Threat status changes to "Mitigated"
- Click "New Session"
- Select "Design Doc"
- Upload a sample architecture markdown document
- Select framework: "OWASP Top 10"
- Click "Generate Threat Model"
- Verify: Threats are generated without code diffs
- Verify: Mitigations are prose suggestions (not code patches)
- Verify: No "Apply Fix" button appears (only "Accept Risk" and "Create Jira Ticket")
- Open a session with identified threats
- Click on a threat β verify status is "Identified"
- Click "Apply Fix" β verify status changes to "Mitigated"
- Go back to threat list β verify the badge now shows "Mitigated" (green)
- Check Insights tab β verify mitigation rate percentage increased
| Scenario | Expected Behavior |
|---|---|
| Private repo without token | Error: "GitHub token required for private repos" |
| Very large repo (>1GB) | Use --depth=1 shallow clone, analyze only key files |
| Repo with no code (docs only) | Generate threats from README/docs, no code diffs |
| Invalid GitHub URL | Validation error in form |
| LLM rate limit hit | Queue analysis, show "Processing" with retry |
| Repo with no security issues | Return fewer threats, insights show high coverage |
| Step | Description | Dependencies | Status |
|---|---|---|---|
| 1 | Set up SQLite database schema and db.ts service |
None | DONE |
| 2 | Build repo-analyzer.ts β clone + file inventory + architecture extraction |
Step 1 | DONE |
| 3 | Build threat-generator.ts β LLM-powered STRIDE analysis |
Step 2 | DONE |
| 4 | Build dfd-generator.ts β Mermaid DFD from architecture |
Step 2 | DONE |
| 5 | Build fix-generator.ts β code-level mitigation generation |
Step 3 | DONE |
| 6 | Build git-service.ts β GitHub clone, branch, commit, PR |
Step 5 | DONE |
| 7 | Build insight-engine.ts β quality metrics computation |
Step 3 | DONE |
| 8 | Build API route handlers (all endpoints) | Steps 1-7 | DONE |
| 9 | Build mermaid-diagram.tsx frontend component |
Step 4 | DONE |
| 10 | Wire frontend to real APIs, add Apply Fix button | Steps 8-9 | DONE |
| 11 | End-to-end testing with OWASP Juice Shop | Step 10 | NEEDS API KEYS |
| 12 | Polish: error handling, loading states, edge cases | Step 11 | DONE |
Build verified:
next buildcompiles successfully with all routes registered.
app/api/threat-model/sessions/route.tsapp/api/threat-model/sessions/[id]/route.tsapp/api/threat-model/sessions/[id]/analyze/route.tsapp/api/threat-model/threats/[id]/route.tsapp/api/threat-model/threats/[id]/apply-fix/route.tslib/threat-engine/repo-analyzer.tslib/threat-engine/threat-generator.tslib/threat-engine/dfd-generator.tslib/threat-engine/insight-engine.tslib/threat-engine/fix-generator.tslib/threat-engine/git-service.tslib/db.ts
components/unitone/mermaid-diagram.tsxcomponents/unitone/apply-fix-button.tsx
app/threat-modeling/page.tsxβ connect to real APIs, dynamic DFD, Apply Fix flowlib/threat-data.tsβ add new types for API request/response shapespackage.jsonβ add new dependencies
.env.localβ add GITHUB_TOKEN, ANTHROPIC_API_KEY