guardlink

Threat Model
Assets 16
Open 15
Controls 12
Coverage 0%
Executive Summary
F
Critical Risk 2 critical exposure(s) require immediate attention
16
Assets
15
Open Threats
45
Mitigated
12
Controls
68
Data Flows
9
Boundaries
0
Transfers
0
Validations
19
Audits
0
Assumptions
0
Ownership
18
Comments
16
Shields
Threat Mitigation Coverage
75% 45 of 60 exposures mitigated
Severity Breakdown
Critical
2
High
25
Medium
24
Low
9
⚠ Open Threats (No Mitigation)
#prompt-injection medium
User prompt passed to agent CLI as argument
Asset: #agent-launcher
#dos low
No timeout on foreground spawn; agent controls duration
Asset: #agent-launcher
#prompt-injection high
User prompt concatenated into agent instruction text
Asset: #agent-launcher
#data-exposure low
Serializes full threat model and code snippets for LLM
Asset: #llm-client
#prompt-injection medium
User prompts sent to LLM API
Asset: #llm-client
#data-exposure low
Exposes threat model findings to SARIF consumers
Asset: #sarif
#cmd-injection critical
Agent launcher spawns child processes
Asset: #cli
#data-exposure low
Writes API key config to .guardlink/config.json
Asset: #init
#cmd-injection high
Accepts tool calls from external MCP clients
Asset: #mcp
#prompt-injection medium
annotate and threat_report tools pass user prompts to LLM
Asset: #mcp
#data-exposure medium
Resources expose full threat model to MCP clients
Asset: #mcp
#dos low
Large files loaded into memory for pattern scanning
Asset: #suggest
#arbitrary-write high
Writes modified content back to discovered files
Asset: #parser
#cmd-injection high
/annotate and /threat-report spawn child processes
Asset: #tui
#prompt-injection medium
Freeform chat sends user text to LLM
Asset: #tui
Data Flows
SourceTargetMechanismLocation
EnvVars #agent-launcher process.env src/agents/config.ts:19
ConfigFile #agent-launcher readFileSync src/agents/config.ts:20
#agent-launcher ConfigFile writeFileSync src/agents/config.ts:21
UserPrompt #agent-launcher launchAgent src/agents/launcher.ts:17
#agent-launcher AgentProcess spawn src/agents/launcher.ts:18
AgentProcess #agent-launcher stdout src/agents/launcher.ts:19
UserPrompt #agent-launcher buildAnnotatePrompt src/agents/prompts.ts:10
ThreatModel #agent-launcher model src/agents/prompts.ts:11
#agent-launcher AgentPrompt return src/agents/prompts.ts:12
ThreatModel #llm-client serializeModel src/analyze/index.ts:14
ProjectFiles #llm-client readFileSync src/analyze/index.ts:15
#llm-client ReportFile writeFileSync src/analyze/index.ts:16
LLMConfig #llm-client chatCompletion src/analyze/llm.ts:19
#llm-client LLMProvider fetch src/analyze/llm.ts:20
LLMProvider #llm-client response src/analyze/llm.ts:21
LLMToolCall #llm-client createToolExecutor src/analyze/tools.ts:15
#llm-client NVD fetch src/analyze/tools.ts:16
ProjectFiles #llm-client readFileSync src/analyze/tools.ts:17
ThreatModel #sarif generateSarif src/analyzer/sarif.ts:18
#sarif SarifLog return src/analyzer/sarif.ts:19
UserArgs #cli process.argv src/cli/index.ts:33
#cli FileSystem writeFile src/cli/index.ts:34
ThreatModel #dashboard computeStats src/dashboard/generate.ts:12
SourceFiles #dashboard readFileSync src/dashboard/generate.ts:13
#dashboard HTML return src/dashboard/generate.ts:14
ThreatModel #dashboard generateDashboardHTML src/dashboard/index.ts:6
GitRef #diff execSync src/diff/git.ts:12
#diff TempDir writeFileSync src/diff/git.ts:13
#diff ThreatModel parseProject src/diff/git.ts:14
GitRef #diff parseAtRef src/diff/index.ts:6
ProjectRoot #init detectProject src/init/detect.ts:7
ProjectRoot #init options.root src/init/index.ts:14
#init AgentFiles writeFileSync src/init/index.ts:15
#init ConfigFile writeFileSync src/init/index.ts:16
MCPClient #mcp stdio src/mcp/index.ts:6
QueryString #mcp lookup src/mcp/lookup.ts:18
MCPClient #mcp tool_call src/mcp/server.ts:36
#mcp FileSystem writeFile src/mcp/server.ts:37
#mcp #llm-client generateThreatReport src/mcp/server.ts:38
#mcp MCPClient resource src/mcp/server.ts:39
FilePath #suggest readFileSync src/mcp/suggest.ts:18
#suggest Suggestions suggestAnnotations src/mcp/suggest.ts:19
ProjectRoot #parser fast-glob src/parser/clear.ts:11
#parser SourceFiles writeFile src/parser/clear.ts:12
FilePath #parser readFile src/parser/parse-file.ts:8
#parser Annotations parseString src/parser/parse-file.ts:9
ProjectRoot #parser fast-glob src/parser/parse-project.ts:9
#parser ThreatModel assembleModel src/parser/parse-project.ts:10
ThreatModel #report generateReport src/report/report.ts:8
#report Markdown return src/report/report.ts:9
ThreatModel #cli getReviewableExposures src/review/index.ts:13
#cli SourceFiles writeFile src/review/index.ts:14
UserArgs #tui args src/tui/commands.ts:17
#tui FileSystem writeFile src/tui/commands.ts:18
#tui #agent-launcher launchAgent src/tui/commands.ts:19
#tui #llm-client chatCompletion src/tui/commands.ts:20
ConfigFile #tui loadProjectConfig src/tui/config.ts:9
#tui ConfigFile saveProjectConfig src/tui/config.ts:10
UserInput #tui readline src/tui/index.ts:13
#tui Commands dispatch src/tui/index.ts:14
RawStdin #tui process.stdin src/tui/input.ts:17
#tui Terminal process.stdout src/tui/input.ts:18
UserArgs #workspace-link linkProject src/workspace/link.ts:8
#workspace-link AgentFiles updateAgentWorkspaceContext src/workspace/link.ts:9
ReportJSON #merge-engine mergeReports src/workspace/merge.ts:10
#merge-engine MergedReport mergeReports src/workspace/merge.ts:11
GitRepo #report-metadata execSync src/workspace/metadata.ts:8
#report-metadata ThreatModel populateMetadata src/workspace/metadata.ts:9
Threat Reports
Threats & Exposures
Open Threats (15)

Exposed in code but not mitigated by any control.

AssetThreatSeverityDescriptionLocation
#agent-launcher #prompt-injection medium User prompt passed to agent CLI as argument src/agents/launcher.ts:13
#agent-launcher #dos low No timeout on foreground spawn; agent controls duration src/agents/launcher.ts:15
#agent-launcher #prompt-injection high User prompt concatenated into agent instruction text src/agents/prompts.ts:6
#llm-client #data-exposure low Serializes full threat model and code snippets for LLM src/analyze/index.ts:12
#llm-client #prompt-injection medium User prompts sent to LLM API src/analyze/llm.ts:17
#sarif #data-exposure low Exposes threat model findings to SARIF consumers src/analyzer/sarif.ts:15
#cli #cmd-injection critical Agent launcher spawns child processes src/cli/index.ts:31
#init #data-exposure low Writes API key config to .guardlink/config.json src/init/index.ts:12
#mcp #cmd-injection high Accepts tool calls from external MCP clients src/mcp/index.ts:4
#mcp #prompt-injection medium annotate and threat_report tools pass user prompts to LLM src/mcp/server.ts:30
#mcp #data-exposure medium Resources expose full threat model to MCP clients src/mcp/server.ts:34
#suggest #dos low Large files loaded into memory for pattern scanning src/mcp/suggest.ts:16
#parser #arbitrary-write high Writes modified content back to discovered files src/parser/clear.ts:7
#tui #cmd-injection high /annotate and /threat-report spawn child processes src/tui/commands.ts:11
#tui #prompt-injection medium Freeform chat sends user text to LLM src/tui/commands.ts:15
Mitigated Threats (45)
AssetThreatSeverityDescriptionLocation
#agent-launcher #api-key-exposure high API keys loaded from env vars, files; stored in config.json src/agents/config.ts:13
#agent-launcher #path-traversal medium Config paths resolved from root and homedir src/agents/config.ts:15
#agent-launcher #arbitrary-write medium saveProjectConfig writes to .guardlink/config.json src/agents/config.ts:17
#agent-launcher #child-proc-injection critical spawn/spawnSync execute external binaries src/agents/launcher.ts:10
#agent-launcher #path-traversal medium Reads reference docs from root-relative paths src/agents/prompts.ts:8
#llm-client #path-traversal medium buildProjectContext reads files from root-relative paths src/analyze/index.ts:8
#llm-client #arbitrary-write medium writeFileSync saves threat reports to .guardlink/ src/analyze/index.ts:10
#llm-client #ssrf medium fetch() calls external LLM API endpoints src/analyze/llm.ts:13
#llm-client #api-key-exposure high API keys passed in Authorization headers src/analyze/llm.ts:15
#llm-client #ssrf medium lookupCve fetches from NVD API with user-controlled CVE ID src/analyze/tools.ts:9
#llm-client #path-traversal medium searchCodebase reads files from project root src/analyze/tools.ts:11
#llm-client #dos low searchCodebase reads many files; bounded by maxResults src/analyze/tools.ts:13
#cli #path-traversal high User-supplied dir argument resolved via path.resolve src/cli/index.ts:25
#cli #arbitrary-write high init/report/sarif/dashboard write files to user-specified paths src/cli/index.ts:27
#cli #api-key-exposure high API keys handled in config set/show commands src/cli/index.ts:29
#dashboard #xss high Generates HTML with user-controlled threat model data src/dashboard/generate.ts:8
#dashboard #path-traversal medium readFileSync reads code files for annotation context src/dashboard/generate.ts:10
#dashboard #xss high Generates HTML with threat model data src/dashboard/index.ts:4
#diff #cmd-injection high execSync runs git commands with ref argument src/diff/git.ts:6
#diff #arbitrary-write medium writeFileSync creates files in temp directory src/diff/git.ts:8
#diff #path-traversal medium git show extracts files based on ls-tree output src/diff/git.ts:10
#diff #cmd-injection high git.ts uses execSync with ref argument src/diff/index.ts:4
#init #path-traversal low Reads package.json, pyproject.toml, etc. from root src/init/detect.ts:5
#init #arbitrary-write high Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc. src/init/index.ts:8
#init #path-traversal medium Reads/writes files based on root argument src/init/index.ts:10
#mcp #redos low Regex patterns applied to query strings src/mcp/lookup.ts:16
#mcp #path-traversal high Tool arguments include 'root' directory path from external client src/mcp/server.ts:26
#mcp #arbitrary-write high report, dashboard, sarif tools write files src/mcp/server.ts:28
#mcp #api-key-exposure medium threat_report tool uses API keys from environment src/mcp/server.ts:32
#suggest #path-traversal high File path from MCP client joined with root src/mcp/suggest.ts:12
#suggest #redos medium Complex regex patterns applied to source code src/mcp/suggest.ts:14
#parser #path-traversal high Glob patterns determine which files are modified src/parser/clear.ts:8
#parser #path-traversal high File path from caller read via readFile; no validation here src/parser/parse-file.ts:5
#parser #dos medium Large files loaded entirely into memory src/parser/parse-file.ts:6
#parser #redos medium Complex regex patterns applied to annotation text src/parser/parse-line.ts:5
#parser #path-traversal high Glob patterns could escape root directory src/parser/parse-project.ts:5
#parser #dos medium Large projects with many files could exhaust memory src/parser/parse-project.ts:7
#cli #arbitrary-write medium Writes @accepts/@audit annotations into source files src/review/index.ts:10
#tui #path-traversal high File paths from user args in /view, /sarif -o src/tui/commands.ts:7
#tui #arbitrary-write high /report, /sarif, /dashboard write files src/tui/commands.ts:9
#tui #api-key-exposure high /model handles API key input and storage src/tui/commands.ts:13
#tui #api-key-exposure high API keys loaded from and saved to config files src/tui/config.ts:7
#tui #path-traversal high User-supplied dir argument resolved via path.resolve src/tui/index.ts:9
#tui #api-key-exposure medium API keys displayed in banner via resolveLLMConfig src/tui/index.ts:11
#tui #dos low Rapid keystrokes could consume CPU in raw mode src/tui/input.ts:15
All Exposures (60)
StatusAssetThreatSeverityDescriptionLocation
Mitigated #agent-launcher #api-key-exposure high API keys loaded from env vars, files; stored in config.json src/agents/config.ts:13
Mitigated #agent-launcher #path-traversal medium Config paths resolved from root and homedir src/agents/config.ts:15
Mitigated #agent-launcher #arbitrary-write medium saveProjectConfig writes to .guardlink/config.json src/agents/config.ts:17
Mitigated #agent-launcher #child-proc-injection critical spawn/spawnSync execute external binaries src/agents/launcher.ts:10
Open #agent-launcher #prompt-injection medium User prompt passed to agent CLI as argument src/agents/launcher.ts:13
Open #agent-launcher #dos low No timeout on foreground spawn; agent controls duration src/agents/launcher.ts:15
Open #agent-launcher #prompt-injection high User prompt concatenated into agent instruction text src/agents/prompts.ts:6
Mitigated #agent-launcher #path-traversal medium Reads reference docs from root-relative paths src/agents/prompts.ts:8
Mitigated #llm-client #path-traversal medium buildProjectContext reads files from root-relative paths src/analyze/index.ts:8
Mitigated #llm-client #arbitrary-write medium writeFileSync saves threat reports to .guardlink/ src/analyze/index.ts:10
Open #llm-client #data-exposure low Serializes full threat model and code snippets for LLM src/analyze/index.ts:12
Mitigated #llm-client #ssrf medium fetch() calls external LLM API endpoints src/analyze/llm.ts:13
Mitigated #llm-client #api-key-exposure high API keys passed in Authorization headers src/analyze/llm.ts:15
Open #llm-client #prompt-injection medium User prompts sent to LLM API src/analyze/llm.ts:17
Mitigated #llm-client #ssrf medium lookupCve fetches from NVD API with user-controlled CVE ID src/analyze/tools.ts:9
Mitigated #llm-client #path-traversal medium searchCodebase reads files from project root src/analyze/tools.ts:11
Mitigated #llm-client #dos low searchCodebase reads many files; bounded by maxResults src/analyze/tools.ts:13
Open #sarif #data-exposure low Exposes threat model findings to SARIF consumers src/analyzer/sarif.ts:15
Mitigated #cli #path-traversal high User-supplied dir argument resolved via path.resolve src/cli/index.ts:25
Mitigated #cli #arbitrary-write high init/report/sarif/dashboard write files to user-specified paths src/cli/index.ts:27
Mitigated #cli #api-key-exposure high API keys handled in config set/show commands src/cli/index.ts:29
Open #cli #cmd-injection critical Agent launcher spawns child processes src/cli/index.ts:31
Mitigated #dashboard #xss high Generates HTML with user-controlled threat model data src/dashboard/generate.ts:8
Mitigated #dashboard #path-traversal medium readFileSync reads code files for annotation context src/dashboard/generate.ts:10
Mitigated #dashboard #xss high Generates HTML with threat model data src/dashboard/index.ts:4
Mitigated #diff #cmd-injection high execSync runs git commands with ref argument src/diff/git.ts:6
Mitigated #diff #arbitrary-write medium writeFileSync creates files in temp directory src/diff/git.ts:8
Mitigated #diff #path-traversal medium git show extracts files based on ls-tree output src/diff/git.ts:10
Mitigated #diff #cmd-injection high git.ts uses execSync with ref argument src/diff/index.ts:4
Mitigated #init #path-traversal low Reads package.json, pyproject.toml, etc. from root src/init/detect.ts:5
Mitigated #init #arbitrary-write high Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc. src/init/index.ts:8
Mitigated #init #path-traversal medium Reads/writes files based on root argument src/init/index.ts:10
Open #init #data-exposure low Writes API key config to .guardlink/config.json src/init/index.ts:12
Open #mcp #cmd-injection high Accepts tool calls from external MCP clients src/mcp/index.ts:4
Mitigated #mcp #redos low Regex patterns applied to query strings src/mcp/lookup.ts:16
Mitigated #mcp #path-traversal high Tool arguments include 'root' directory path from external client src/mcp/server.ts:26
Mitigated #mcp #arbitrary-write high report, dashboard, sarif tools write files src/mcp/server.ts:28
Open #mcp #prompt-injection medium annotate and threat_report tools pass user prompts to LLM src/mcp/server.ts:30
Mitigated #mcp #api-key-exposure medium threat_report tool uses API keys from environment src/mcp/server.ts:32
Open #mcp #data-exposure medium Resources expose full threat model to MCP clients src/mcp/server.ts:34
Mitigated #suggest #path-traversal high File path from MCP client joined with root src/mcp/suggest.ts:12
Mitigated #suggest #redos medium Complex regex patterns applied to source code src/mcp/suggest.ts:14
Open #suggest #dos low Large files loaded into memory for pattern scanning src/mcp/suggest.ts:16
Open #parser #arbitrary-write high Writes modified content back to discovered files src/parser/clear.ts:7
Mitigated #parser #path-traversal high Glob patterns determine which files are modified src/parser/clear.ts:8
Mitigated #parser #path-traversal high File path from caller read via readFile; no validation here src/parser/parse-file.ts:5
Mitigated #parser #dos medium Large files loaded entirely into memory src/parser/parse-file.ts:6
Mitigated #parser #redos medium Complex regex patterns applied to annotation text src/parser/parse-line.ts:5
Mitigated #parser #path-traversal high Glob patterns could escape root directory src/parser/parse-project.ts:5
Mitigated #parser #dos medium Large projects with many files could exhaust memory src/parser/parse-project.ts:7
Mitigated #cli #arbitrary-write medium Writes @accepts/@audit annotations into source files src/review/index.ts:10
Mitigated #tui #path-traversal high File paths from user args in /view, /sarif -o src/tui/commands.ts:7
Mitigated #tui #arbitrary-write high /report, /sarif, /dashboard write files src/tui/commands.ts:9
Open #tui #cmd-injection high /annotate and /threat-report spawn child processes src/tui/commands.ts:11
Mitigated #tui #api-key-exposure high /model handles API key input and storage src/tui/commands.ts:13
Open #tui #prompt-injection medium Freeform chat sends user text to LLM src/tui/commands.ts:15
Mitigated #tui #api-key-exposure high API keys loaded from and saved to config files src/tui/config.ts:7
Mitigated #tui #path-traversal high User-supplied dir argument resolved via path.resolve src/tui/index.ts:9
Mitigated #tui #api-key-exposure medium API keys displayed in banner via resolveLLMConfig src/tui/index.ts:11
Mitigated #tui #dos low Rapid keystrokes could consume CPU in raw mode src/tui/input.ts:15
Diagrams

Interactive diagrams from annotations. Scroll to zoom, drag to pan, double-click to reset.

graph LR
  subgraph TZ0["🧱 #agent-launcher"]
    _agent_launcher["🔷 #agent-launcher [SECRETS, INTERNAL]"]
  end
  subgraph TZ1["🧱 AgentProcess"]
  end
  subgraph TZ2["🧱 #llm-client"]
    _llm_client["🔷 #llm-client [INTERNAL, SECRETS]"]
  end
  subgraph TZ3["🧱 LLMProvider"]
  end
  subgraph TZ4["🧱 NVD"]
  end
  subgraph TZ5["🧱 #cli"]
    _cli["🔷 #cli [SECRETS, INTERNAL]"]
  end
  subgraph TZ6["🧱 UserInput"]
  end
  subgraph TZ7["🧱 #diff"]
    _diff["🔷 #diff"]
  end
  subgraph TZ8["🧱 GitRepo"]
  end
  subgraph TZ9["🧱 #mcp"]
    _mcp["🔷 #mcp [INTERNAL]"]
  end
  subgraph TZ10["🧱 MCPClient"]
  end
  subgraph TZ11["🧱 #parser"]
    _parser["🔷 #parser [INTERNAL]"]
  end
  subgraph TZ12["🧱 FileSystem"]
  end
  subgraph TZ13["🧱 #tui"]
    _tui["🔷 #tui [SECRETS, SECRETS, SECRETS]"]
  end
  _sarif["🔷 #sarif"]
  _dashboard["🔷 #dashboard [INTERNAL]"]
  _init["🔷 #init [INTERNAL]"]
  _suggest["🔷 #suggest"]
  _merge_engine["🔷 #merge-engine"]
  _workspace_config["🔷 #workspace-config"]
  _api_key_exposure["🟠 API_Key_Exposure (cwe:CWE-798)"]:::threat
  _path_traversal["🟠 Path_Traversal (cwe:CWE-22)"]:::threat
  _arbitrary_write["🟠 Arbitrary_File_Write (cwe:CWE-73)"]:::threat
  _child_proc_injection["🔴 Child_Process_Injection (cwe:CWE-78)"]:::threat
  _prompt_injection["🟠 Prompt_Injection (cwe:CWE-77)"]:::threat
  _dos["🟡 Denial_of_Service (cwe:CWE-400)"]:::threat
  _data_exposure["🟡 Sensitive_Data_Exposure (cwe:CWE-200)"]:::threat
  _ssrf["🟡 Server_Side_Request_Forgery (cwe:CWE-918)"]:::threat
  _cmd_injection["🔴 Command_Injection (cwe:CWE-78)"]:::threat
  _xss["🟠 Cross_Site_Scripting (cwe:CWE-79)"]:::threat
  _redos["🟡 ReDoS (cwe:CWE-1333)"]:::threat
  _tag_collision["🟡 Tag_Collision"]:::threat
  _config_tamper["🟡 Config_Tampering (cwe:CWE-15)"]:::threat
  _key_redaction["🛡️ key-redaction"]:::control
  _path_validation["🛡️ path-validation"]:::control
  _param_commands["🛡️ param-commands"]:::control
  _config_validation["🛡️ config-validation"]:::control
  _input_sanitize["🛡️ input-sanitize"]:::control
  _glob_filtering["🛡️ glob-filtering"]:::control
  _resource_limits["🛡️ resource-limits"]:::control
  _output_encoding["🛡️ output-encoding"]:::control
  _regex_anchoring["🛡️ regex-anchoring"]:::control
  _prefix_ownership["🛡️ prefix-ownership"]:::control
  _yaml_validation["🛡️ yaml-validation"]:::control
  _agent_launcher -. exposed .-> _api_key_exposure
  _agent_launcher -. exposed .-> _path_traversal
  _agent_launcher -. exposed .-> _arbitrary_write
  _agent_launcher -. exposed .-> _child_proc_injection
  _agent_launcher -. exposed .-> _prompt_injection
  _agent_launcher -. exposed .-> _dos
  _llm_client -. exposed .-> _path_traversal
  _llm_client -. exposed .-> _arbitrary_write
  _llm_client -. exposed .-> _data_exposure
  _llm_client -. exposed .-> _ssrf
  _llm_client -. exposed .-> _api_key_exposure
  _llm_client -. exposed .-> _prompt_injection
  _llm_client -. exposed .-> _dos
  _sarif -. exposed .-> _data_exposure
  _cli -. exposed .-> _path_traversal
  _cli -. exposed .-> _arbitrary_write
  _cli -. exposed .-> _api_key_exposure
  _cli -. exposed .-> _cmd_injection
  _dashboard -. exposed .-> _xss
  _dashboard -. exposed .-> _path_traversal
  _diff -. exposed .-> _cmd_injection
  _diff -. exposed .-> _arbitrary_write
  _diff -. exposed .-> _path_traversal
  _init -. exposed .-> _path_traversal
  _init -. exposed .-> _arbitrary_write
  _init -. exposed .-> _data_exposure
  _mcp -. exposed .-> _cmd_injection
  _mcp -. exposed .-> _redos
  _mcp -. exposed .-> _path_traversal
  _mcp -. exposed .-> _arbitrary_write
  _mcp -. exposed .-> _prompt_injection
  _mcp -. exposed .-> _api_key_exposure
  _mcp -. exposed .-> _data_exposure
  _suggest -. exposed .-> _path_traversal
  _suggest -. exposed .-> _redos
  _suggest -. exposed .-> _dos
  _parser -. exposed .-> _arbitrary_write
  _parser -. exposed .-> _path_traversal
  _parser -. exposed .-> _dos
  _parser -. exposed .-> _redos
  _tui -. exposed .-> _path_traversal
  _tui -. exposed .-> _arbitrary_write
  _tui -. exposed .-> _cmd_injection
  _tui -. exposed .-> _api_key_exposure
  _tui -. exposed .-> _prompt_injection
  _tui -. exposed .-> _dos
  _key_redaction -- mitigates --> _api_key_exposure
  _key_redaction -.- _agent_launcher
  _path_validation -- mitigates --> _path_traversal
  _path_validation -.- _agent_launcher
  _path_validation -- mitigates --> _arbitrary_write
  _param_commands -- mitigates --> _child_proc_injection
  _param_commands -.- _agent_launcher
  _param_commands -- mitigates --> _cmd_injection
  _path_validation -.- _llm_client
  _config_validation -- mitigates --> _ssrf
  _config_validation -.- _llm_client
  _key_redaction -.- _llm_client
  _input_sanitize -- mitigates --> _ssrf
  _input_sanitize -.- _llm_client
  _glob_filtering -- mitigates --> _path_traversal
  _glob_filtering -.- _llm_client
  _resource_limits -- mitigates --> _dos
  _resource_limits -.- _llm_client
  _path_validation -.- _cli
  _key_redaction -.- _cli
  _output_encoding -- mitigates --> _xss
  _output_encoding -.- _dashboard
  _path_validation -.- _dashboard
  _input_sanitize -- mitigates --> _cmd_injection
  _input_sanitize -.- _diff
  _path_validation -.- _diff
  _glob_filtering -.- _diff
  _path_validation -.- _init
  _regex_anchoring -- mitigates --> _redos
  _regex_anchoring -.- _mcp
  _path_validation -.- _mcp
  _key_redaction -.- _mcp
  _path_validation -.- _suggest
  _regex_anchoring -.- _suggest
  _glob_filtering -.- _parser
  _regex_anchoring -.- _parser
  _resource_limits -.- _parser
  _path_validation -.- _tui
  _key_redaction -.- _tui
  _resource_limits -.- _tui
  _prefix_ownership -- mitigates --> _tag_collision
  _prefix_ownership -.- _merge_engine
  _yaml_validation -- mitigates --> _config_tamper
  _yaml_validation -.- _workspace_config
  _mcp -- "📡 generateThreatReport" --> _llm_client
  _tui -- "📡 launchAgent" --> _agent_launcher
  _tui -- "📡 chatCompletion" --> _llm_client
  classDef threat fill:#991b1b,stroke:#ef4444,color:#fecaca
  classDef control fill:#065f46,stroke:#10b981,color:#a7f3d0
%%{init: {"flowchart": {"nodeSpacing": 43, "rankSpacing": 59, "curve": "basis"}}}%%
graph LR
  subgraph Z0["🧱 Trust Zone · #agent-launcher"]
    _agent_launcher["🧩 #agent-launcher"]
  end
  subgraph Z1["🧱 Trust Zone · AgentProcess"]
    AgentProcess["🧩 AgentProcess"]
  end
  subgraph Z2["🧱 Trust Zone · #llm-client"]
    _llm_client["👤 #llm-client"]
  end
  subgraph Z3["🧱 Trust Zone · LLMProvider"]
    LLMProvider["🧩 LLMProvider"]
  end
  subgraph Z4["🧱 Trust Zone · NVD"]
    NVD["🧩 NVD"]
  end
  subgraph Z5["🧱 Trust Zone · #cli"]
    _cli["🧩 #cli"]
  end
  subgraph Z6["🧱 Trust Zone · UserInput"]
    UserInput["👤 UserInput"]
  end
  subgraph Z7["🧱 Trust Zone · #diff"]
    _diff["🧩 #diff"]
  end
  subgraph Z8["🧱 Trust Zone · GitRepo"]
    GitRepo["🧩 GitRepo"]
  end
  subgraph Z9["🧱 Trust Zone · #mcp"]
    _mcp["🧩 #mcp"]
  end
  subgraph Z10["🧱 Trust Zone · MCPClient"]
    MCPClient["👤 MCPClient"]
  end
  subgraph Z11["🧱 Trust Zone · #parser"]
    _parser["🧩 #parser"]
  end
  subgraph Z12["🧱 Trust Zone · FileSystem"]
    FileSystem["🧩 FileSystem"]
  end
  subgraph Z13["🧱 Trust Zone · #tui"]
    _tui["👤 #tui"]
  end
  _agent_launcher -.-|🧱 Trust boundary at process spawn| AgentProcess
  _llm_client -.-|🧱 Trust boundary at external API call| LLMProvider
  _llm_client -.-|🧱 Trust boundary at external API| NVD
  _cli -.-|🧱 Trust boundary at CLI argument parsing| UserInput
  _diff -.-|🧱 Trust boundary at git command execution| GitRepo
  _mcp -.-|🧱 Trust boundary at MCP protocol| MCPClient
  _mcp -.-|🧱 Trust boundary at tool argument parsing| MCPClient
  _parser -.-|🧱 Trust boundary between parser and disk I/O| FileSystem
  _tui -.-|🧱 Trust boundary at interactive input| UserInput
  EnvVars["🧩 EnvVars"]
  ConfigFile["🧩 ConfigFile"]
  UserPrompt["👤 UserPrompt"]
  ThreatModel["🧩 ThreatModel"]
  AgentPrompt["🧩 AgentPrompt"]
  ProjectFiles["🧩 ProjectFiles"]
  ReportFile["🧩 ReportFile"]
  LLMConfig["🧩 LLMConfig"]
  LLMToolCall["🧩 LLMToolCall"]
  _sarif["🧩 #sarif"]
  SarifLog["🧩 SarifLog"]
  UserArgs["👤 UserArgs"]
  _dashboard["🧩 #dashboard · internal"]
  SourceFiles["🧩 SourceFiles"]
  HTML["🧩 HTML"]
  GitRef["🧩 GitRef"]
  TempDir["🧩 TempDir"]
  ProjectRoot["🧩 ProjectRoot"]
  _init["🧩 #init · internal"]
  AgentFiles["🧩 AgentFiles"]
  QueryString["🧩 QueryString"]
  FilePath["🧩 FilePath"]
  _suggest["🧩 #suggest"]
  Suggestions["🧩 Suggestions"]
  Annotations["🧩 Annotations"]
  _report["🧩 #report"]
  Markdown["🧩 Markdown"]
  Commands["🧩 Commands"]
  RawStdin["🧩 RawStdin"]
  Terminal["🧩 Terminal"]
  _workspace_link["🧩 #workspace-link"]
  ReportJSON["🧩 ReportJSON"]
  _merge_engine["🧩 #merge-engine"]
  MergedReport["🧩 MergedReport"]
  _report_metadata["🧩 #report-metadata"]
  EnvVars -- "📡 process.env" --> _agent_launcher
  ConfigFile -- "🗄️ readFileSync" --> _agent_launcher
  _agent_launcher -- "🗄️ writeFileSync" --> ConfigFile
  UserPrompt -- "📡 launchAgent" --> _agent_launcher
  _agent_launcher -- "📡 spawn" --> AgentProcess
  AgentProcess -- "📡 stdout" --> _agent_launcher
  UserPrompt -- "📡 buildAnnotatePrompt" --> _agent_launcher
  ThreatModel -- "📡 model" --> _agent_launcher
  _agent_launcher -- "📡 return" --> AgentPrompt
  ThreatModel -- "📡 serializeModel" --> _llm_client
  ProjectFiles -- "🗄️ readFileSync" --> _llm_client
  _llm_client -- "🗄️ writeFileSync" --> ReportFile
  LLMConfig -- "📡 chatCompletion" --> _llm_client
  _llm_client -- "📡 fetch" --> LLMProvider
  LLMProvider -- "📡 response" --> _llm_client
  LLMToolCall -- "📡 createToolExecutor" --> _llm_client
  _llm_client -- "📡 fetch" --> NVD
  ProjectFiles -- "🗄️ readFileSync" --> _llm_client
  ThreatModel -- "📡 generateSarif" --> _sarif
  _sarif -- "📡 return" --> SarifLog
  UserArgs -- "📡 process.argv" --> _cli
  _cli -- "🗄️ writeFile" --> FileSystem
  ThreatModel -- "📡 computeStats" --> _dashboard
  SourceFiles -- "🗄️ readFileSync" --> _dashboard
  _dashboard -- "📡 return" --> HTML
  ThreatModel -- "📡 generateDashboardHTML" --> _dashboard
  GitRef -- "📡 execSync" --> _diff
  _diff -- "🗄️ writeFileSync" --> TempDir
  _diff -- "📡 parseProject" --> ThreatModel
  GitRef -- "📡 parseAtRef" --> _diff
  ProjectRoot -- "📡 detectProject" --> _init
  ProjectRoot -- "📡 options.root" --> _init
  _init -- "🗄️ writeFileSync" --> AgentFiles
  _init -- "🗄️ writeFileSync" --> ConfigFile
  MCPClient -- "📡 stdio" --> _mcp
  QueryString -- "📡 lookup" --> _mcp
  MCPClient -- "📡 tool_call" --> _mcp
  _mcp -- "🗄️ writeFile" --> FileSystem
  _mcp -- "📡 generateThreatReport" --> _llm_client
  _mcp -- "📡 resource" --> MCPClient
  FilePath -- "🗄️ readFileSync" --> _suggest
  _suggest -- "📡 suggestAnnotations" --> Suggestions
  ProjectRoot -- "📡 fast-glob" --> _parser
  _parser -- "🗄️ writeFile" --> SourceFiles
  FilePath -- "🗄️ readFile" --> _parser
  _parser -- "📡 parseString" --> Annotations
  ProjectRoot -- "📡 fast-glob" --> _parser
  _parser -- "📡 assembleModel" --> ThreatModel
  ThreatModel -- "📡 generateReport" --> _report
  _report -- "📡 return" --> Markdown
  ThreatModel -- "📡 getReviewableExposures" --> _cli
  _cli -- "🗄️ writeFile" --> SourceFiles
  UserArgs -- "📡 args" --> _tui
  _tui -- "🗄️ writeFile" --> FileSystem
  _tui -- "📡 launchAgent" --> _agent_launcher
  _tui -- "📡 chatCompletion" --> _llm_client
  ConfigFile -- "📡 loadProjectConfig" --> _tui
  _tui -- "📡 saveProjectConfig" --> ConfigFile
  UserInput -- "📡 readline" --> _tui
  _tui -- "📡 dispatch" --> Commands
  RawStdin -- "📡 process.stdin" --> _tui
  _tui -- "📡 process.stdout" --> Terminal
  UserArgs -- "📡 linkProject" --> _workspace_link
  _workspace_link -- "📡 updateAgentWorkspaceContext" --> AgentFiles
  ReportJSON -- "📡 mergeReports" --> _merge_engine
  _merge_engine -- "📡 mergeReports" --> MergedReport
  GitRepo -- "📡 execSync" --> _report_metadata
  _report_metadata -- "📡 populateMetadata" --> ThreatModel
graph LR
  subgraph A__agent_launcher["#agent-launcher"]
    direction TB
    E0["✅ child-proc-injection"]:::sev_crit
    E1["✅ api-key-exposure"]:::sev_high
    E2["⚠️ prompt-injection x2"]:::sev_high
    E3["✅ path-traversal x2"]:::sev_med
    E4["✅ arbitrary-write"]:::sev_med
    E5["⚠️ dos"]:::sev_low
  end
  subgraph A__llm_client["#llm-client"]
    direction TB
    E6["✅ api-key-exposure"]:::sev_high
    E7["✅ path-traversal x2"]:::sev_med
    E8["✅ arbitrary-write"]:::sev_med
    E9["✅ ssrf x2"]:::sev_med
    E10["⚠️ prompt-injection"]:::sev_med
    E11["⚠️ data-exposure"]:::sev_low
    E12["✅ dos"]:::sev_low
  end
  subgraph A__sarif["#sarif"]
    direction TB
    E13["⚠️ data-exposure"]:::sev_low
  end
  subgraph A__cli["#cli"]
    direction TB
    E14["⚠️ cmd-injection"]:::sev_crit
    E15["✅ path-traversal"]:::sev_high
    E16["✅ arbitrary-write x2"]:::sev_high
    E17["✅ api-key-exposure"]:::sev_high
  end
  subgraph A__dashboard["#dashboard"]
    direction TB
    E18["✅ xss x2"]:::sev_high
    E19["✅ path-traversal"]:::sev_med
  end
  subgraph A__diff["#diff"]
    direction TB
    E20["✅ cmd-injection x2"]:::sev_high
    E21["✅ arbitrary-write"]:::sev_med
    E22["✅ path-traversal"]:::sev_med
  end
  subgraph A__init["#init"]
    direction TB
    E23["✅ arbitrary-write"]:::sev_high
    E24["✅ path-traversal x2"]:::sev_med
    E25["⚠️ data-exposure"]:::sev_low
  end
  subgraph A__mcp["#mcp"]
    direction TB
    E26["⚠️ cmd-injection"]:::sev_high
    E27["✅ path-traversal"]:::sev_high
    E28["✅ arbitrary-write"]:::sev_high
    E29["⚠️ prompt-injection"]:::sev_med
    E30["✅ api-key-exposure"]:::sev_med
    E31["⚠️ data-exposure"]:::sev_med
    E32["✅ redos"]:::sev_low
  end
  subgraph A__suggest["#suggest"]
    direction TB
    E33["✅ path-traversal"]:::sev_high
    E34["✅ redos"]:::sev_med
    E35["⚠️ dos"]:::sev_low
  end
  subgraph A__parser["#parser"]
    direction TB
    E36["⚠️ arbitrary-write"]:::sev_high
    E37["✅ path-traversal x3"]:::sev_high
    E38["✅ dos x2"]:::sev_med
    E39["✅ redos"]:::sev_med
  end
  subgraph A__tui["#tui"]
    direction TB
    E40["✅ path-traversal x2"]:::sev_high
    E41["✅ arbitrary-write"]:::sev_high
    E42["⚠️ cmd-injection"]:::sev_high
    E43["✅ api-key-exposure x3"]:::sev_high
    E44["⚠️ prompt-injection"]:::sev_med
    E45["✅ dos"]:::sev_low
  end
  classDef sev_crit fill:#7f1d1d,stroke:#ef4444,color:#fecaca
  classDef sev_high fill:#7c2d12,stroke:#f97316,color:#fed7aa
  classDef sev_med fill:#78350f,stroke:#f59e0b,color:#fef3c7
  classDef sev_low fill:#1e3a5f,stroke:#3b82f6,color:#bfdbfe
  classDef sev_unset fill:#374151,stroke:#9ca3af,color:#e5e7eb
</> Code & Annotations

Every file with GuardLink annotations. Click any annotation to see details.

.guardlink/definitions.ts 37
L15 asset GuardLink.Parser
Reads source files from disk, extracts security annotations using regex patterns
10 │ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11 │ 12 │ // ─── ASSETS ─────────────────────────────────────────────────────────── 13 │ // Components that process data, handle user input, or interact with external systems 14 │ 15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data"
L16 asset GuardLink.CLI
Command-line interface, handles user arguments, invokes subcommands
11 │ 12 │ // ─── ASSETS ─────────────────────────────────────────────────────────── 13 │ // Components that process data, handle user input, or interact with external systems 14 │ 15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk"
L17 asset GuardLink.TUI
Interactive terminal interface with readline input and command dispatch
12 │ // ─── ASSETS ─────────────────────────────────────────────────────────── 13 │ // Components that process data, handle user input, or interact with external systems 14 │ 15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)"
L18 asset GuardLink.MCP
Model Context Protocol server, accepts tool calls from AI agents over stdio
13 │ // Components that process data, handle user input, or interact with external systems 14 │ 15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands"
L19 asset GuardLink.LLM_Client
Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)
14 │ 15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams"
L20 asset GuardLink.Dashboard
Generates interactive HTML threat model dashboard from ThreatModel data
15 │ // @asset GuardLink.Parser (#parser) -- "Reads source files from disk, extracts security annotations using regex patterns" 16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling"
L21 asset GuardLink.Init
Initializes projects, writes config files and agent instruction files to disk
16 │ // @asset GuardLink.CLI (#cli) -- "Command-line interface, handles user arguments, invokes subcommands" 17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations"
L22 asset GuardLink.Agent_Launcher
Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)
17 │ // @asset GuardLink.TUI (#tui) -- "Interactive terminal interface with readline input and command dispatch" 18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │
L23 asset GuardLink.Diff
Compares threat models across git commits, invokes git commands
18 │ // @asset GuardLink.MCP (#mcp) -- "Model Context Protocol server, accepts tool calls from AI agents over stdio" 19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │ 28 │ // ─── THREATS ──────────────────────────────────────────────────────────
L24 asset GuardLink.Report
Generates markdown threat model reports with Mermaid diagrams
19 │ // @asset GuardLink.LLM_Client (#llm-client) -- "Makes HTTP requests to external AI providers (Anthropic, OpenAI, DeepSeek, OpenRouter)" 20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │ 28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application
L25 asset GuardLink.SARIF
Exports findings as SARIF 2.1.0 JSON for security tooling
20 │ // @asset GuardLink.Dashboard (#dashboard) -- "Generates interactive HTML threat model dashboard from ThreatModel data" 21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │ 28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application 30 │
L26 asset GuardLink.Suggest
Analyzes code patterns to suggest appropriate security annotations
21 │ // @asset GuardLink.Init (#init) -- "Initializes projects, writes config files and agent instruction files to disk" 22 │ // @asset GuardLink.Agent_Launcher (#agent-launcher) -- "Spawns child processes for AI coding agents (Claude Code, Cursor, Codex)" 23 │ // @asset GuardLink.Diff (#diff) -- "Compares threat models across git commits, invokes git commands" 24 │ // @asset GuardLink.Report (#report) -- "Generates markdown threat model reports with Mermaid diagrams" 25 │ // @asset GuardLink.SARIF (#sarif) -- "Exports findings as SARIF 2.1.0 JSON for security tooling" 26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │ 28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application 30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths"
L31 threat Path_Traversal
File read/write operations outside intended project directory via ../ sequences or absolute paths
26 │ // @asset GuardLink.Suggest (#suggest) -- "Analyzes code patterns to suggest appropriate security annotations" 27 │ 28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application 30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content"
L32 threat Command_Injection
Shell command execution with unsanitized user input
27 │ 28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application 30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project"
L33 threat Cross_Site_Scripting
Injection of malicious scripts into generated HTML output
28 │ // ─── THREATS ────────────────────────────────────────────────────────── 29 │ // Security threats that can impact the application 30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts"
L34 threat API_Key_Exposure
API keys leaked in logs, error messages, or unintended output
29 │ // Security threats that can impact the application 30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees"
L35 threat Server_Side_Request_Forgery
LLM API requests to attacker-controlled URLs via config override
30 │ 31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties"
L36 threat ReDoS
Regular expression denial of service from crafted annotation content
31 │ // @threat Path_Traversal (#path-traversal) [high] cwe:CWE-22 -- "File read/write operations outside intended project directory via ../ sequences or absolute paths" 32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files"
L37 threat Arbitrary_File_Write
Writing files to attacker-controlled paths outside project
32 │ // @threat Command_Injection (#cmd-injection) [critical] cwe:CWE-78 -- "Shell command execution with unsanitized user input" 33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn"
L38 threat Prompt_Injection
Malicious content in annotations injected into LLM prompts
33 │ // @threat Cross_Site_Scripting (#xss) [high] cwe:CWE-79 -- "Injection of malicious scripts into generated HTML output" 34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details"
L39 threat Denial_of_Service
Resource exhaustion from processing large files or deep directory trees
34 │ // @threat API_Key_Exposure (#api-key-exposure) [high] cwe:CWE-798 -- "API keys leaked in logs, error messages, or unintended output" 35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │
L40 threat Sensitive_Data_Exposure
Threat model details exposed to unauthorized parties
35 │ // @threat Server_Side_Request_Forgery (#ssrf) [medium] cwe:CWE-918 -- "LLM API requests to attacker-controlled URLs via config override" 36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │ 45 │ // ─── CONTROLS ─────────────────────────────────────────────────────────
L41 threat Insecure_Deserialization
Unsafe parsing of JSON/YAML configuration files
36 │ // @threat ReDoS (#redos) [medium] cwe:CWE-1333 -- "Regular expression denial of service from crafted annotation content" 37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │ 45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats
L42 threat Child_Process_Injection
Agent launcher executing attacker-controlled commands via process spawn
37 │ // @threat Arbitrary_File_Write (#arbitrary-write) [high] cwe:CWE-73 -- "Writing files to attacker-controlled paths outside project" 38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │ 45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats 47 │
L43 threat Information_Disclosure
Unintended exposure of internal paths, structure, or implementation details
38 │ // @threat Prompt_Injection (#prompt-injection) [medium] cwe:CWE-77 -- "Malicious content in annotations injected into LLM prompts" 39 │ // @threat Denial_of_Service (#dos) [medium] cwe:CWE-400 -- "Resource exhaustion from processing large files or deep directory trees" 40 │ // @threat Sensitive_Data_Exposure (#data-exposure) [medium] cwe:CWE-200 -- "Threat model details exposed to unauthorized parties" 41 │ // @threat Insecure_Deserialization (#insecure-deser) [medium] cwe:CWE-502 -- "Unsafe parsing of JSON/YAML configuration files" 42 │ // @threat Child_Process_Injection (#child-proc-injection) [high] cwe:CWE-78 -- "Agent launcher executing attacker-controlled commands via process spawn" 43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │ 45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats 47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories"
L48 control Path_Validation
Validates file paths using resolve() + startsWith() to ensure access within allowed directories
43 │ // @threat Information_Disclosure (#info-disclosure) [low] cwe:CWE-200 -- "Unintended exposure of internal paths, structure, or implementation details" 44 │ 45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats 47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use"
L49 control Input_Sanitization
Input validation with anchored regex patterns and length limits
44 │ 45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats 47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints"
L50 control Output_Encoding
HTML entity encoding for untrusted data in generated output
45 │ // ─── CONTROLS ───────────────────────────────────────────────────────── 46 │ // Security controls that mitigate threats 47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation"
L51 control Key_Redaction
Masking API keys in logs and error messages
46 │ // Security controls that mitigate threats 47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes"
L52 control Process_Sandboxing
Controlled child process spawning with explicit args array, no shell
47 │ 48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking"
L53 control Config_Validation
Schema validation for configuration files before use
48 │ // @control Path_Validation (#path-validation) -- "Validates file paths using resolve() + startsWith() to ensure access within allowed directories" 49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions"
L54 control Resource_Limits
File size limits, recursion depth limits, timeout constraints
49 │ // @control Input_Sanitization (#input-sanitize) -- "Input validation with anchored regex patterns and length limits" 50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files"
L55 control Parameterized_Commands
Using spawn with args array instead of shell string interpolation
50 │ // @control Output_Encoding (#output-encoding) -- "HTML entity encoding for untrusted data in generated output" 51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files" 60 │
L56 control Glob_Pattern_Filtering
Filtering files using glob patterns with explicit excludes
51 │ // @control Key_Redaction (#key-redaction) -- "Masking API keys in logs and error messages" 52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files" 60 │
L57 control Regex_Anchoring
Using anchored regex patterns (^...$) to prevent backtracking
52 │ // @control Process_Sandboxing (#process-sandbox) -- "Controlled child process spawning with explicit args array, no shell" 53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files" 60 │
L58 control Prefix_Ownership
Tag prefix determines owning repo, preventing cross-repo tag collisions
53 │ // @control Config_Validation (#config-validation) -- "Schema validation for configuration files before use" 54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files" 60 │
L59 control YAML_Validation
Schema validation for workspace.yaml configuration files
54 │ // @control Resource_Limits (#resource-limits) -- "File size limits, recursion depth limits, timeout constraints" 55 │ // @control Parameterized_Commands (#param-commands) -- "Using spawn with args array instead of shell string interpolation" 56 │ // @control Glob_Pattern_Filtering (#glob-filtering) -- "Filtering files using glob patterns with explicit excludes" 57 │ // @control Regex_Anchoring (#regex-anchoring) -- "Using anchored regex patterns (^...$) to prevent backtracking" 58 │ // @control Prefix_Ownership (#prefix-ownership) -- "Tag prefix determines owning repo, preventing cross-repo tag collisions" 59 │ // @control YAML_Validation (#yaml-validation) -- "Schema validation for workspace.yaml configuration files" 60 │
src/agents/config.ts 10
L13 exposes #agent-launcher → #api-key-exposure
API keys loaded from env vars, files; stored in config.json
8 │ * 4. Project config: .guardlink/config.json 9 │ * 5. Global config: ~/.config/guardlink/config.json 10 │ * 11 │ * Replaces the fragmented tui-config.json / CLI flag / env var resolution. 12 │ * 13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root"
L14 mitigates #key-redaction mitigates #api-key-exposure
maskKey() redacts keys for display; keys never logged
9 │ * 5. Global config: ~/.config/guardlink/config.json 10 │ * 11 │ * Replaces the fragmented tui-config.json / CLI flag / env var resolution. 12 │ * 13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input"
L15 exposes #agent-launcher → #path-traversal
Config paths resolved from root and homedir
10 │ * 11 │ * Replaces the fragmented tui-config.json / CLI flag / env var resolution. 12 │ * 13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read"
L16 mitigates #path-validation mitigates #path-traversal
join() with known base dirs constrains paths
11 │ * Replaces the fragmented tui-config.json / CLI flag / env var resolution. 12 │ * 13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write"
L17 exposes #agent-launcher → #arbitrary-write
saveProjectConfig writes to .guardlink/config.json
12 │ * 13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys"
L18 mitigates #path-validation mitigates #arbitrary-write
Output path is fixed relative to project root
13 │ * @exposes #agent-launcher to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from env vars, files; stored in config.json" 14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys" 23 │ */
L19 flow EnvVars → #agent-launcher
Environment variable input
14 │ * @mitigates #agent-launcher against #api-key-exposure using #key-redaction -- "maskKey() redacts keys for display; keys never logged" 15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys" 23 │ */ 24 │
L20 flow ConfigFile → #agent-launcher
Config file read
15 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Config paths resolved from root and homedir" 16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys" 23 │ */ 24 │ 25 │ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
L21 flow #agent-launcher → ConfigFile
Config file write
16 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "join() with known base dirs constrains paths" 17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys" 23 │ */ 24 │ 25 │ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'; 26 │ import { join } from 'node:path';
L22 handles #agent-launcher: secrets
Processes and stores LLM API keys
17 │ * @exposes #agent-launcher to #arbitrary-write [medium] cwe:CWE-73 -- "saveProjectConfig writes to .guardlink/config.json" 18 │ * @mitigates #agent-launcher against #arbitrary-write using #path-validation -- "Output path is fixed relative to project root" 19 │ * @flows EnvVars -> #agent-launcher via process.env -- "Environment variable input" 20 │ * @flows ConfigFile -> #agent-launcher via readFileSync -- "Config file read" 21 │ * @flows #agent-launcher -> ConfigFile via writeFileSync -- "Config file write" 22 │ * @handles secrets on #agent-launcher -- "Processes and stores LLM API keys" 23 │ */ 24 │ 25 │ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'; 26 │ import { join } from 'node:path'; 27 │ import { homedir } from 'node:os';
src/agents/index.ts 2
L7 comment Agent binaries are hardcoded; no user-controlled binary names
Agent binaries are hardcoded; no user-controlled binary names
2 │ * GuardLink Agents — Shared agent registry. 3 │ * 4 │ * Used by CLI, TUI, and MCP to identify and resolve coding agents 5 │ * (Claude Code, Codex, Cursor, Windsurf, Gemini, clipboard). 6 │ * 7 │ * @comment -- "Agent binaries are hardcoded; no user-controlled binary names" 8 │ * @comment -- "parseAgentFlag extracts flags from args; no injection risk" 9 │ */ 10 │ 11 │ // ─── Agent registry ────────────────────────────────────────────────── 12 │
L8 comment parseAgentFlag extracts flags from args; no injection risk
parseAgentFlag extracts flags from args; no injection risk
3 │ * 4 │ * Used by CLI, TUI, and MCP to identify and resolve coding agents 5 │ * (Claude Code, Codex, Cursor, Windsurf, Gemini, clipboard). 6 │ * 7 │ * @comment -- "Agent binaries are hardcoded; no user-controlled binary names" 8 │ * @comment -- "parseAgentFlag extracts flags from args; no injection risk" 9 │ */ 10 │ 11 │ // ─── Agent registry ────────────────────────────────────────────────── 12 │ 13 │ export interface AgentEntry {
src/agents/launcher.ts 11
L10 exposes #agent-launcher → #child-proc-injection
spawn/spawnSync execute external binaries
5 │ * 1. Foreground spawn (CLI + TUI): takes over terminal, returns on exit 6 │ * 2. IDE launch: opens GUI app with project directory 7 │ * 8 │ * Clipboard copy is always performed first regardless of agent type. 9 │ * 10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration"
L11 mitigates #param-commands mitigates #child-proc-injection
Binary names from hardcoded AGENTS registry; no shell interpolation
6 │ * 2. IDE launch: opens GUI app with project directory 7 │ * 8 │ * Clipboard copy is always performed first regardless of agent type. 9 │ * 10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control"
L12 mitigates #param-commands mitigates #cmd-injection
Arguments passed as array, not shell string
7 │ * 8 │ * Clipboard copy is always performed first regardless of agent type. 9 │ * 10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path"
L13 exposes #agent-launcher → #prompt-injection
User prompt passed to agent CLI as argument
8 │ * Clipboard copy is always performed first regardless of agent type. 9 │ * 10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path"
L14 audit Audit: #agent-launcher
Prompt content is opaque to agent binary; injection risk depends on agent implementation
9 │ * 10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture"
L15 exposes #agent-launcher → #dos
No timeout on foreground spawn; agent controls duration
10 │ * @exposes #agent-launcher to #child-proc-injection [critical] cwe:CWE-78 -- "spawn/spawnSync execute external binaries" 11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn"
L16 audit Audit: #agent-launcher
Timeout intentionally omitted for interactive sessions; inline mode has implicit control
11 │ * @mitigates #agent-launcher against #child-proc-injection using #param-commands -- "Binary names from hardcoded AGENTS registry; no shell interpolation" 12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn" 21 │ */
L17 flow UserPrompt → #agent-launcher
Prompt input path
12 │ * @mitigates #agent-launcher against #cmd-injection using #param-commands -- "Arguments passed as array, not shell string" 13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn" 21 │ */ 22 │
L18 flow #agent-launcher → AgentProcess
Process spawn path
13 │ * @exposes #agent-launcher to #prompt-injection [medium] cwe:CWE-77 -- "User prompt passed to agent CLI as argument" 14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn" 21 │ */ 22 │ 23 │ import { spawnSync, spawn } from 'node:child_process';
L19 flow AgentProcess → #agent-launcher
Agent output capture
14 │ * @audit #agent-launcher -- "Prompt content is opaque to agent binary; injection risk depends on agent implementation" 15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn" 21 │ */ 22 │ 23 │ import { spawnSync, spawn } from 'node:child_process'; 24 │ import { platform } from 'node:os';
L20 boundary #agent-launcher ↔ AgentProcess
Trust boundary at process spawn
15 │ * @exposes #agent-launcher to #dos [low] cwe:CWE-400 -- "No timeout on foreground spawn; agent controls duration" 16 │ * @audit #agent-launcher -- "Timeout intentionally omitted for interactive sessions; inline mode has implicit control" 17 │ * @flows UserPrompt -> #agent-launcher via launchAgent -- "Prompt input path" 18 │ * @flows #agent-launcher -> AgentProcess via spawn -- "Process spawn path" 19 │ * @flows AgentProcess -> #agent-launcher via stdout -- "Agent output capture" 20 │ * @boundary #agent-launcher and AgentProcess (#agent-boundary) -- "Trust boundary at process spawn" 21 │ */ 22 │ 23 │ import { spawnSync, spawn } from 'node:child_process'; 24 │ import { platform } from 'node:os'; 25 │ import { mkdtempSync, readFileSync, unlinkSync, existsSync } from 'node:fs';
src/agents/prompts.ts 24
L6 exposes #agent-launcher → #prompt-injection
User prompt concatenated into agent instruction text
1 │ /** 2 │ * GuardLink Agents — Prompt builders for annotation and analysis. 3 │ * 4 │ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP. 5 │ * 6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection"
L7 audit Audit: #agent-launcher
Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context
2 │ * GuardLink Agents — Prompt builders for annotation and analysis. 3 │ * 4 │ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP. 5 │ * 6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output"
L8 exposes #agent-launcher → #path-traversal
Reads reference docs from root-relative paths
3 │ * 4 │ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP. 5 │ * 6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt"
L9 mitigates #path-validation mitigates #path-traversal
resolve() with root constrains file access
4 │ * Extracted from tui/commands.ts for shared use across CLI, TUI, MCP. 5 │ * 6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt" 14 │ */
L10 flow UserPrompt → #agent-launcher
User instruction input
5 │ * 6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt" 14 │ */ 15 │
L11 flow ThreatModel → #agent-launcher
Model context injection
6 │ * @exposes #agent-launcher to #prompt-injection [high] cwe:CWE-77 -- "User prompt concatenated into agent instruction text" 7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt" 14 │ */ 15 │ 16 │ import { existsSync, readFileSync } from 'node:fs';
L12 flow #agent-launcher → AgentPrompt
Assembled prompt output
7 │ * @audit #agent-launcher -- "Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context" 8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt" 14 │ */ 15 │ 16 │ import { existsSync, readFileSync } from 'node:fs'; 17 │ import { resolve } from 'node:path';
L13 handles #agent-launcher: internal
Serializes threat model IDs and flows into prompt
8 │ * @exposes #agent-launcher to #path-traversal [medium] cwe:CWE-22 -- "Reads reference docs from root-relative paths" 9 │ * @mitigates #agent-launcher against #path-traversal using #path-validation -- "resolve() with root constrains file access" 10 │ * @flows UserPrompt -> #agent-launcher via buildAnnotatePrompt -- "User instruction input" 11 │ * @flows ThreatModel -> #agent-launcher via model -- "Model context injection" 12 │ * @flows #agent-launcher -> AgentPrompt via return -- "Assembled prompt output" 13 │ * @handles internal on #agent-launcher -- "Serializes threat model IDs and flows into prompt" 14 │ */ 15 │ 16 │ import { existsSync, readFileSync } from 'node:fs'; 17 │ import { resolve } from 'node:path'; 18 │ import type { ThreatModel } from '../types/index.js';
L148 shield Example annotation block for reference, excluded from parsing
143 │ 144 │ ### Always Couple Annotations Together 145 │ A file's doc-block should paint the full security picture of that module. Group annotations logically: 146 │ 147 │ \`\`\` 148 │ // @shield:begin -- "Example annotation block for reference, excluded from parsing" 149 │ // 150 │ // GOOD — Complete story at a single code location: 151 │ // @exposes #auth-api to #sqli [P1] cwe:CWE-89 -- "User-supplied email passed to findUser() query builder" 152 │ // @mitigates #auth-api against #sqli using #input-validation -- "Zod schema validates email format before query" 153 │ // @flows User_Input -> #auth-api via POST./login -- "Login form submits credentials"
L161 shield Shielded region
156 │ // @comment -- "Password comparison uses bcrypt.compare with timing-safe equality" 157 │ // 158 │ // BAD — Isolated annotation with no context: 159 │ // @exposes #auth-api to #sqli -- "SQL injection possible" 160 │ // 161 │ // @shield:end 162 │ \`\`\` 163 │ 164 │ ### Description Style — Reference Actual Code 165 │ Descriptions must reference the real code: function names, variable names, libraries, mechanisms. 166 │
L168 shield Description examples, excluded from parsing
163 │ 164 │ ### Description Style — Reference Actual Code 165 │ Descriptions must reference the real code: function names, variable names, libraries, mechanisms. 166 │ 167 │ \`\`\` 168 │ // @shield:begin -- "Description examples, excluded from parsing" 169 │ // 170 │ // GOOD: -- "req.body.token passed to jwt.verify() without audience check" 171 │ // GOOD: -- "bcrypt rounds set to 12 via BCRYPT_COST env var" 172 │ // GOOD: -- "Rate limiter uses express-rate-limit at 100req/15min on /api/*" 173 │ //
L178 shield Shielded region
173 │ // 174 │ // BAD: -- "Input not validated" (too vague — WHICH input? WHERE?) 175 │ // BAD: -- "Uses encryption" (WHAT encryption? On WHAT data?) 176 │ // BAD: -- "Security vulnerability exists" (meaningless — be specific) 177 │ // 178 │ // @shield:end 179 │ \`\`\` 180 │ 181 │ ### @flows — Stitch the Complete Data Path 182 │ @flows is the backbone of the threat model. Trace data movement accurately: 183 │
L185 shield Flow examples, excluded from parsing
180 │ 181 │ ### @flows — Stitch the Complete Data Path 182 │ @flows is the backbone of the threat model. Trace data movement accurately: 183 │ 184 │ \`\`\` 185 │ // @shield:begin -- "Flow examples, excluded from parsing" 186 │ // 187 │ // Trace a request through the full stack: 188 │ // @flows User_Browser -> #api-gateway via HTTPS -- "Client sends auth request" 189 │ // @flows #api-gateway -> #auth-service via internal.gRPC -- "Gateway forwards to auth microservice" 190 │ // @flows #auth-service -> #user-db via pg.query -- "Looks up user record by email"
L194 shield Shielded region
189 │ // @flows #api-gateway -> #auth-service via internal.gRPC -- "Gateway forwards to auth microservice" 190 │ // @flows #auth-service -> #user-db via pg.query -- "Looks up user record by email" 191 │ // @flows #auth-service -> #session-store via redis.set -- "Stores session token with TTL" 192 │ // @flows #auth-service -> User_Browser via Set-Cookie -- "Returns session cookie to client" 193 │ // 194 │ // @shield:end 195 │ \`\`\` 196 │ 197 │ ### @boundary — Mark Every Trust Zone Crossing 198 │ Place @boundary annotations where trust level changes between two components: 199 │
L201 shield Boundary examples, excluded from parsing
196 │ 197 │ ### @boundary — Mark Every Trust Zone Crossing 198 │ Place @boundary annotations where trust level changes between two components: 199 │ 200 │ \`\`\` 201 │ // @shield:begin -- "Boundary examples, excluded from parsing" 202 │ // 203 │ // @boundary between #api-gateway and External_Internet (#public-boundary) -- "TLS termination, rate limiting at edge" 204 │ // @boundary between #backend and #database (#data-boundary) -- "Application to persistence layer, connection pooling via pgBouncer" 205 │ // @boundary between #app and #payment-provider (#vendor-boundary) -- "PCI-DSS scope boundary, tokenized card data only" 206 │ //
L207 shield Shielded region
202 │ // 203 │ // @boundary between #api-gateway and External_Internet (#public-boundary) -- "TLS termination, rate limiting at edge" 204 │ // @boundary between #backend and #database (#data-boundary) -- "Application to persistence layer, connection pooling via pgBouncer" 205 │ // @boundary between #app and #payment-provider (#vendor-boundary) -- "PCI-DSS scope boundary, tokenized card data only" 206 │ // 207 │ // @shield:end 208 │ \`\`\` 209 │ 210 │ ### Where to Place Annotations 211 │ Annotations go in the file's top doc-block comment OR directly above the security-relevant code: 212 │
L214 shield Placement examples, excluded from parsing
209 │ 210 │ ### Where to Place Annotations 211 │ Annotations go in the file's top doc-block comment OR directly above the security-relevant code: 212 │ 213 │ \`\`\` 214 │ // @shield:begin -- "Placement examples, excluded from parsing" 215 │ // 216 │ // FILE-LEVEL (top doc-block) — for module-wide security properties: 217 │ // Place @exposes, @mitigates, @flows, @handles, @boundary that describe the module as a whole 218 │ // 219 │ // INLINE (above specific functions/methods) — for function-specific concerns:
L223 shield Shielded region
218 │ // 219 │ // INLINE (above specific functions/methods) — for function-specific concerns: 220 │ // Place @exposes, @mitigates above the exact function where the risk or control lives 221 │ // Place @comment above tricky security-relevant code to explain intent 222 │ // 223 │ // @shield:end 224 │ \`\`\` 225 │ 226 │ ### Severity — Be Honest, Not Alarmist 227 │ Annotations capture what COULD go wrong, calibrated to realistic risk: 228 │ - **[P0] / [critical]**: Directly exploitable by external attacker, severe impact (RCE, auth bypass, data breach)
L250 shield @accepts alternative examples, excluded from parsing
245 │ 3. Add @comment explaining what controls COULD be added 246 │ 4. Optionally add @assumes to document any assumptions the code makes 247 │ 248 │ Example — what to do when no mitigation exists: 249 │ \`\`\` 250 │ // @shield:begin -- "@accepts alternative examples, excluded from parsing" 251 │ // 252 │ // WRONG (AI rubber-stamping risk): 253 │ // @accepts #prompt-injection on #ai-endpoint -- "Relying on model safety filters" 254 │ // 255 │ // RIGHT (flag for human review):
L260 shield Shielded region
255 │ // RIGHT (flag for human review): 256 │ // @exposes #ai-endpoint to #prompt-injection [P1] cwe:CWE-77 -- "User prompt passed directly to LLM API without sanitization" 257 │ // @audit #ai-endpoint -- "No prompt sanitization — needs human review to decide: add input filter or accept risk" 258 │ // @comment -- "Potential controls: #prompt-filter (input sanitization), #output-validator (response filtering)" 259 │ // 260 │ // @shield:end 261 │ \`\`\` 262 │ 263 │ Leaving exposures unmitigated is HONEST. The dashboard and reports will surface them as open risks for humans to triage. 264 │ 265 │ ### @shield — DO NOT USE Unless Explicitly Asked
L277 shield Definition syntax examples, excluded from parsing
272 │ 273 │ Definitions go in .guardlink/definitions.{ts,js,py,rs}. Source files use only relationship verbs. 274 │ 275 │ ### Definitions (in .guardlink/definitions file) 276 │ \`\`\` 277 │ // @shield:begin -- "Definition syntax examples, excluded from parsing" 278 │ // @asset Server.Auth (#auth) -- "Authentication service handling login and session management" 279 │ // @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input reaches SQL query builder" 280 │ // @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries via ORM or driver placeholders" 281 │ // @shield:end 282 │ \`\`\`
L281 shield Shielded region
276 │ \`\`\` 277 │ // @shield:begin -- "Definition syntax examples, excluded from parsing" 278 │ // @asset Server.Auth (#auth) -- "Authentication service handling login and session management" 279 │ // @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input reaches SQL query builder" 280 │ // @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries via ORM or driver placeholders" 281 │ // @shield:end 282 │ \`\`\` 283 │ 284 │ ### Relationships (in source files) 285 │ \`\`\` 286 │ // @shield:begin -- "Relationship syntax examples, excluded from parsing"
L286 shield Relationship syntax examples, excluded from parsing
281 │ // @shield:end 282 │ \`\`\` 283 │ 284 │ ### Relationships (in source files) 285 │ \`\`\` 286 │ // @shield:begin -- "Relationship syntax examples, excluded from parsing" 287 │ // @exposes #auth to #sqli [P0] cwe:CWE-89 owasp:A03:2021 -- "User input concatenated into query" 288 │ // @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries via sqlx" 289 │ // @audit #auth -- "Timing attack risk — needs human review to decide if bcrypt constant-time comparison is sufficient" 290 │ // @transfers #ddos from #api to #cdn -- "Cloudflare handles L7 DDoS mitigation" 291 │ // @flows req.body.username -> db.query via string-concat -- "User input flows to SQL"
L299 shield Shielded region
294 │ // @validates #prepared-stmts for #auth -- "Integration test sqlInjectionTest.ts confirms parameterized queries block SQLi payloads" 295 │ // @audit #auth -- "Session token rotation logic needs cryptographic review" 296 │ // @assumes #auth -- "Upstream API gateway has already validated TLS and rate-limited requests" 297 │ // @owns security-team for #auth -- "Security team reviews all auth PRs" 298 │ // @comment -- "Password hashing uses bcrypt with cost factor 12, migration from SHA256 completed in v2.1" 299 │ // @shield:end 300 │ \`\`\` 301 │ 302 │ ## CRITICAL SYNTAX RULES (violations cause parse errors) 303 │ 304 │ 1. **@boundary requires TWO assets**: \`@boundary between #A and #B\` or \`@boundary #A | #B\`.
src/analyze/index.ts 10
L8 exposes #llm-client → #path-traversal
buildProjectContext reads files from root-relative paths
3 │ * 4 │ * Serializes the threat model, sends it to an LLM with a framework- 5 │ * specific prompt, streams the response, and saves timestamped results 6 │ * to .guardlink/threat-reports/. 7 │ * 8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis"
L9 mitigates #path-validation mitigates #path-traversal
join() with root constrains file access
4 │ * Serializes the threat model, sends it to an LLM with a framework- 5 │ * specific prompt, streams the response, and saves timestamped results 6 │ * to .guardlink/threat-reports/. 7 │ * 8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input"
L10 exposes #llm-client → #arbitrary-write
writeFileSync saves threat reports to .guardlink/
5 │ * specific prompt, streams the response, and saves timestamped results 6 │ * to .guardlink/threat-reports/. 7 │ * 8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read"
L11 mitigates #path-validation mitigates #arbitrary-write
Output path is fixed to .guardlink/threat-reports/
6 │ * to .guardlink/threat-reports/. 7 │ * 8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output"
L12 exposes #llm-client → #data-exposure
Serializes full threat model and code snippets for LLM
7 │ * 8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets"
L13 audit Audit: #llm-client
Threat model data intentionally sent to LLM for analysis
8 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "buildProjectContext reads files from root-relative paths" 9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets" 18 │ */
L14 flow ThreatModel → #llm-client
Model serialization input
9 │ * @mitigates #llm-client against #path-traversal using #path-validation -- "join() with root constrains file access" 10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets" 18 │ */ 19 │
L15 flow ProjectFiles → #llm-client
Project context read
10 │ * @exposes #llm-client to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync saves threat reports to .guardlink/" 11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets" 18 │ */ 19 │ 20 │ import { existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync } from 'node:fs';
L16 flow #llm-client → ReportFile
Report output
11 │ * @mitigates #llm-client against #arbitrary-write using #path-validation -- "Output path is fixed to .guardlink/threat-reports/" 12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets" 18 │ */ 19 │ 20 │ import { existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync } from 'node:fs'; 21 │ import { join, relative } from 'node:path';
L17 handles #llm-client: internal
Processes project dependencies, env examples, code snippets
12 │ * @exposes #llm-client to #data-exposure [low] cwe:CWE-200 -- "Serializes full threat model and code snippets for LLM" 13 │ * @audit #llm-client -- "Threat model data intentionally sent to LLM for analysis" 14 │ * @flows ThreatModel -> #llm-client via serializeModel -- "Model serialization input" 15 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Project context read" 16 │ * @flows #llm-client -> ReportFile via writeFileSync -- "Report output" 17 │ * @handles internal on #llm-client -- "Processes project dependencies, env examples, code snippets" 18 │ */ 19 │ 20 │ import { existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync } from 'node:fs'; 21 │ import { join, relative } from 'node:path'; 22 │ import type { ThreatModel } from '../types/index.js';
src/analyze/llm.ts 11
L13 exposes #llm-client → #ssrf
fetch() calls external LLM API endpoints
8 │ * - OpenAI-compatible Chat Completions (DeepSeek, OpenRouter, Ollama) 9 │ * - DeepSeek reasoning mode (deepseek-reasoner) 10 │ * 11 │ * Zero dependencies — uses Node 20+ built-in fetch. 12 │ * 13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only"
L14 mitigates #config-validation mitigates #ssrf
BASE_URLS are hardcoded; baseUrl override is optional config
9 │ * - DeepSeek reasoning mode (deepseek-reasoner) 10 │ * 11 │ * Zero dependencies — uses Node 20+ built-in fetch. 12 │ * 13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input"
L15 exposes #llm-client → #api-key-exposure
API keys passed in Authorization headers
10 │ * 11 │ * Zero dependencies — uses Node 20+ built-in fetch. 12 │ * 13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output"
L16 mitigates #key-redaction mitigates #api-key-exposure
Keys never logged; passed directly to API
11 │ * Zero dependencies — uses Node 20+ built-in fetch. 12 │ * 13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input"
L17 exposes #llm-client → #prompt-injection
User prompts sent to LLM API
12 │ * 13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call"
L18 audit Audit: #llm-client
Prompt injection mitigated by LLM provider safety; local code is read-only
13 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "fetch() calls external LLM API endpoints" 14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication"
L19 flow LLMConfig → #llm-client
Config and prompt input
14 │ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded; baseUrl override is optional config" 15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication" 24 │ */
L20 flow #llm-client → LLMProvider
API request output
15 │ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "API keys passed in Authorization headers" 16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication" 24 │ */ 25 │
L21 flow LLMProvider → #llm-client
API response input
16 │ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys never logged; passed directly to API" 17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication" 24 │ */ 25 │ 26 │ export type LLMProvider = 'anthropic' | 'openai' | 'google' | 'openrouter' | 'deepseek' | 'ollama';
L22 boundary #llm-client ↔ LLMProvider
Trust boundary at external API call
17 │ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "User prompts sent to LLM API" 18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication" 24 │ */ 25 │ 26 │ export type LLMProvider = 'anthropic' | 'openai' | 'google' | 'openrouter' | 'deepseek' | 'ollama'; 27 │
L23 handles #llm-client: secrets
Processes API keys for authentication
18 │ * @audit #llm-client -- "Prompt injection mitigated by LLM provider safety; local code is read-only" 19 │ * @flows LLMConfig -> #llm-client via chatCompletion -- "Config and prompt input" 20 │ * @flows #llm-client -> LLMProvider via fetch -- "API request output" 21 │ * @flows LLMProvider -> #llm-client via response -- "API response input" 22 │ * @boundary #llm-client and LLMProvider (#llm-api-boundary) -- "Trust boundary at external API call" 23 │ * @handles secrets on #llm-client -- "Processes API keys for authentication" 24 │ */ 25 │ 26 │ export type LLMProvider = 'anthropic' | 'openai' | 'google' | 'openrouter' | 'deepseek' | 'ollama'; 27 │ 28 │ // ─── Tool definitions ────────────────────────────────────────────────
src/analyze/prompts.ts 2
L7 comment Prompt templates are static; no user input interpolation in system prompts
Prompt templates are static; no user input interpolation in system prompts
2 │ * GuardLink Threat Reports — Framework-specific analysis prompts. 3 │ * 4 │ * Each framework produces a structured security analysis from the 5 │ * serialized threat model. The LLM acts as a senior security architect. 6 │ * 7 │ * @comment -- "Prompt templates are static; no user input interpolation in system prompts" 8 │ * @comment -- "customPrompt is appended to user message, not system prompt — bounded injection risk" 9 │ */ 10 │ 11 │ export type AnalysisFramework = 'stride' | 'dread' | 'pasta' | 'attacker' | 'rapid' | 'general'; 12 │
L8 comment customPrompt is appended to user message, not system prompt — bounded injection risk
customPrompt is appended to user message, not system prompt — bounded injection risk
3 │ * 4 │ * Each framework produces a structured security analysis from the 5 │ * serialized threat model. The LLM acts as a senior security architect. 6 │ * 7 │ * @comment -- "Prompt templates are static; no user input interpolation in system prompts" 8 │ * @comment -- "customPrompt is appended to user message, not system prompt — bounded injection risk" 9 │ */ 10 │ 11 │ export type AnalysisFramework = 'stride' | 'dread' | 'pasta' | 'attacker' | 'rapid' | 'general'; 12 │ 13 │ export const FRAMEWORK_LABELS: Record<AnalysisFramework, string> = {
src/analyze/tools.ts 10
L9 exposes #llm-client → #ssrf
lookupCve fetches from NVD API with user-controlled CVE ID
4 │ * Defines tools that the LLM can invoke during threat analysis: 5 │ * - lookup_cve: Search for CVE details (via web fetch) 6 │ * - validate_finding: Cross-reference a finding against the parsed model 7 │ * - search_codebase: Search project files for patterns 8 │ * 9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter"
L10 mitigates #input-sanitize mitigates #ssrf
CVE ID validated with strict regex; URL hardcoded to NVD
5 │ * - lookup_cve: Search for CVE details (via web fetch) 6 │ * - validate_finding: Cross-reference a finding against the parsed model 7 │ * - search_codebase: Search project files for patterns 8 │ * 9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input"
L11 exposes #llm-client → #path-traversal
searchCodebase reads files from project root
6 │ * - validate_finding: Cross-reference a finding against the parsed model 7 │ * - search_codebase: Search project files for patterns 8 │ * 9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call"
L12 mitigates #glob-filtering mitigates #path-traversal
skipDirs excludes sensitive directories; relative() bounds output
7 │ * - search_codebase: Search project files for patterns 8 │ * 9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads"
L13 exposes #llm-client → #dos
searchCodebase reads many files; bounded by maxResults
8 │ * 9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API"
L14 mitigates #resource-limits mitigates #dos
maxResults caps output; stat.size < 500KB filter
9 │ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "lookupCve fetches from NVD API with user-controlled CVE ID" 10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API" 19 │ */
L15 flow LLMToolCall → #llm-client
Tool invocation input
10 │ * @mitigates #llm-client against #ssrf using #input-sanitize -- "CVE ID validated with strict regex; URL hardcoded to NVD" 11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API" 19 │ */ 20 │
L16 flow #llm-client → NVD
CVE lookup API call
11 │ * @exposes #llm-client to #path-traversal [medium] cwe:CWE-22 -- "searchCodebase reads files from project root" 12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API" 19 │ */ 20 │ 21 │ import { readFileSync, readdirSync, statSync } from 'node:fs';
L17 flow ProjectFiles → #llm-client
Codebase search reads
12 │ * @mitigates #llm-client against #path-traversal using #glob-filtering -- "skipDirs excludes sensitive directories; relative() bounds output" 13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API" 19 │ */ 20 │ 21 │ import { readFileSync, readdirSync, statSync } from 'node:fs'; 22 │ import { join, relative } from 'node:path';
L18 boundary #llm-client ↔ NVD
Trust boundary at external API
13 │ * @exposes #llm-client to #dos [low] cwe:CWE-400 -- "searchCodebase reads many files; bounded by maxResults" 14 │ * @mitigates #llm-client against #dos using #resource-limits -- "maxResults caps output; stat.size < 500KB filter" 15 │ * @flows LLMToolCall -> #llm-client via createToolExecutor -- "Tool invocation input" 16 │ * @flows #llm-client -> NVD via fetch -- "CVE lookup API call" 17 │ * @flows ProjectFiles -> #llm-client via readFileSync -- "Codebase search reads" 18 │ * @boundary #llm-client and NVD (#nvd-api-boundary) -- "Trust boundary at external API" 19 │ */ 20 │ 21 │ import { readFileSync, readdirSync, statSync } from 'node:fs'; 22 │ import { join, relative } from 'node:path'; 23 │ import type { ToolDefinition, ToolExecutor } from './llm.js';
src/analyzer/index.ts 2
L4 comment SARIF generation is pure transformation; no I/O in this module
SARIF generation is pure transformation; no I/O in this module
1 │ /** 2 │ * GuardLink Analyzer — exports. 3 │ * 4 │ * @comment -- "SARIF generation is pure transformation; no I/O in this module" 5 │ * @comment -- "File writes handled by CLI/MCP callers" 6 │ */ 7 │ 8 │ export { generateSarif, type SarifOptions } from './sarif.js'; 9 │
L5 comment File writes handled by CLI/MCP callers
File writes handled by CLI/MCP callers
1 │ /** 2 │ * GuardLink Analyzer — exports. 3 │ * 4 │ * @comment -- "SARIF generation is pure transformation; no I/O in this module" 5 │ * @comment -- "File writes handled by CLI/MCP callers" 6 │ */ 7 │ 8 │ export { generateSarif, type SarifOptions } from './sarif.js'; 9 │
src/analyzer/sarif.ts 5
L15 exposes #sarif → #data-exposure
Exposes threat model findings to SARIF consumers
10 │ * We emit results for: 11 │ * 1. Unmitigated exposures (the primary security findings) 12 │ * 2. Parse errors (annotation syntax problems) 13 │ * 3. Dangling references (broken #id refs) 14 │ * 15 │ * @exposes #sarif to #data-exposure [low] cwe:CWE-200 -- "Exposes threat model findings to SARIF consumers" 16 │ * @audit #sarif -- "SARIF output intentionally reveals security findings for CI/CD integration" 17 │ * @comment -- "Pure function: transforms ThreatModel to SARIF JSON; no I/O" 18 │ * @flows ThreatModel -> #sarif via generateSarif -- "Model input" 19 │ * @flows #sarif -> SarifLog via return -- "SARIF output" 20 │ */
L16 audit Audit: #sarif
SARIF output intentionally reveals security findings for CI/CD integration
11 │ * 1. Unmitigated exposures (the primary security findings) 12 │ * 2. Parse errors (annotation syntax problems) 13 │ * 3. Dangling references (broken #id refs) 14 │ * 15 │ * @exposes #sarif to #data-exposure [low] cwe:CWE-200 -- "Exposes threat model findings to SARIF consumers" 16 │ * @audit #sarif -- "SARIF output intentionally reveals security findings for CI/CD integration" 17 │ * @comment -- "Pure function: transforms ThreatModel to SARIF JSON; no I/O" 18 │ * @flows ThreatModel -> #sarif via generateSarif -- "Model input" 19 │ * @flows #sarif -> SarifLog via return -- "SARIF output" 20 │ */ 21 │
L17 comment Pure function: transforms ThreatModel to SARIF JSON; no I/O
Pure function: transforms ThreatModel to SARIF JSON; no I/O
12 │ * 2. Parse errors (annotation syntax problems) 13 │ * 3. Dangling references (broken #id refs) 14 │ * 15 │ * @exposes #sarif to #data-exposure [low] cwe:CWE-200 -- "Exposes threat model findings to SARIF consumers" 16 │ * @audit #sarif -- "SARIF output intentionally reveals security findings for CI/CD integration" 17 │ * @comment -- "Pure function: transforms ThreatModel to SARIF JSON; no I/O" 18 │ * @flows ThreatModel -> #sarif via generateSarif -- "Model input" 19 │ * @flows #sarif -> SarifLog via return -- "SARIF output" 20 │ */ 21 │ 22 │ import type { ThreatModel, ThreatModelExposure, ParseDiagnostic, Severity } from '../types/index.js';
L18 flow ThreatModel → #sarif
Model input
13 │ * 3. Dangling references (broken #id refs) 14 │ * 15 │ * @exposes #sarif to #data-exposure [low] cwe:CWE-200 -- "Exposes threat model findings to SARIF consumers" 16 │ * @audit #sarif -- "SARIF output intentionally reveals security findings for CI/CD integration" 17 │ * @comment -- "Pure function: transforms ThreatModel to SARIF JSON; no I/O" 18 │ * @flows ThreatModel -> #sarif via generateSarif -- "Model input" 19 │ * @flows #sarif -> SarifLog via return -- "SARIF output" 20 │ */ 21 │ 22 │ import type { ThreatModel, ThreatModelExposure, ParseDiagnostic, Severity } from '../types/index.js'; 23 │
L19 flow #sarif → SarifLog
SARIF output
14 │ * 15 │ * @exposes #sarif to #data-exposure [low] cwe:CWE-200 -- "Exposes threat model findings to SARIF consumers" 16 │ * @audit #sarif -- "SARIF output intentionally reveals security findings for CI/CD integration" 17 │ * @comment -- "Pure function: transforms ThreatModel to SARIF JSON; no I/O" 18 │ * @flows ThreatModel -> #sarif via generateSarif -- "Model input" 19 │ * @flows #sarif -> SarifLog via return -- "SARIF output" 20 │ */ 21 │ 22 │ import type { ThreatModel, ThreatModelExposure, ParseDiagnostic, Severity } from '../types/index.js'; 23 │ 24 │ // ─── SARIF 2.1.0 types (subset) ─────────────────────────────────────
src/cli/index.ts 12
L25 exposes #cli → #path-traversal
User-supplied dir argument resolved via path.resolve
20 │ * guardlink tui [dir] Interactive TUI with slash commands + AI chat 21 │ * guardlink gal Display GAL annotation language quick reference 22 │ * guardlink link-project <repos...> Link repos into a shared workspace 23 │ * guardlink merge <files...> Merge repo reports into unified dashboard 24 │ * 25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output"
L26 mitigates #path-validation mitigates #path-traversal
resolve() canonicalizes paths; cwd-relative by design
21 │ * guardlink gal Display GAL annotation language quick reference 22 │ * guardlink link-project <repos...> Link repos into a shared workspace 23 │ * guardlink merge <files...> Merge repo reports into unified dashboard 24 │ * 25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes"
L27 exposes #cli → #arbitrary-write
init/report/sarif/dashboard write files to user-specified paths
22 │ * guardlink link-project <repos...> Link repos into a shared workspace 23 │ * guardlink merge <files...> Merge repo reports into unified dashboard 24 │ * 25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args"
L28 mitigates #path-validation mitigates #arbitrary-write
Output paths resolved relative to project root
23 │ * guardlink merge <files...> Merge repo reports into unified dashboard 24 │ * 25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path"
L29 exposes #cli → #api-key-exposure
API keys handled in config set/show commands
24 │ * 25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path"
L30 mitigates #key-redaction mitigates #api-key-exposure
maskKey() redacts keys in show output
25 │ * @exposes #cli to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing"
L31 exposes #cli → #cmd-injection
Agent launcher spawns child processes
26 │ * @mitigates #cli against #path-traversal using #path-validation -- "resolve() canonicalizes paths; cwd-relative by design" 27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands"
L32 audit Audit: #cli
Child process spawning delegated to agents/launcher.ts with explicit args
27 │ * @exposes #cli to #arbitrary-write [high] cwe:CWE-73 -- "init/report/sarif/dashboard write files to user-specified paths" 28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands" 37 │ */
L33 flow UserArgs → #cli
CLI argument input path
28 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands" 37 │ */ 38 │
L34 flow #cli → FileSystem
Report/config output path
29 │ * @exposes #cli to #api-key-exposure [high] cwe:CWE-798 -- "API keys handled in config set/show commands" 30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands" 37 │ */ 38 │ 39 │ import { Command } from 'commander';
L35 boundary #cli ↔ UserInput
Trust boundary at CLI argument parsing
30 │ * @mitigates #cli against #api-key-exposure using #key-redaction -- "maskKey() redacts keys in show output" 31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands" 37 │ */ 38 │ 39 │ import { Command } from 'commander'; 40 │ import { resolve, basename } from 'node:path';
L36 handles #cli: secrets
Processes API keys via config commands
31 │ * @exposes #cli to #cmd-injection [critical] cwe:CWE-78 -- "Agent launcher spawns child processes" 32 │ * @audit #cli -- "Child process spawning delegated to agents/launcher.ts with explicit args" 33 │ * @flows UserArgs -> #cli via process.argv -- "CLI argument input path" 34 │ * @flows #cli -> FileSystem via writeFile -- "Report/config output path" 35 │ * @boundary #cli and UserInput (#cli-input-boundary) -- "Trust boundary at CLI argument parsing" 36 │ * @handles secrets on #cli -- "Processes API keys via config commands" 37 │ */ 38 │ 39 │ import { Command } from 'commander'; 40 │ import { resolve, basename } from 'node:path'; 41 │ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
src/dashboard/generate.ts 8
L8 exposes #dashboard → #xss
Generates HTML with user-controlled threat model data
3 │ * 4 │ * Sidebar navigation + drawer detail panel + dark/light toggle. 5 │ * 7 pages: Summary, AI Analysis, Threats, Diagrams, Code, Data, Assets. 6 │ * Mermaid.js via CDN for diagrams. Zero build step. 7 │ * 8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads"
L9 mitigates #output-encoding mitigates #xss
esc() HTML-encodes all interpolated values
4 │ * Sidebar navigation + drawer detail panel + dark/light toggle. 5 │ * 7 pages: Summary, AI Analysis, Threats, Diagrams, Code, Data, Assets. 6 │ * Mermaid.js via CDN for diagrams. Zero build step. 7 │ * 8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output"
L10 exposes #dashboard → #path-traversal
readFileSync reads code files for annotation context
5 │ * 7 pages: Summary, AI Analysis, Threats, Diagrams, Code, Data, Assets. 6 │ * Mermaid.js via CDN for diagrams. Zero build step. 7 │ * 8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data"
L11 mitigates #path-validation mitigates #path-traversal
resolve() with root constrains file access
6 │ * Mermaid.js via CDN for diagrams. Zero build step. 7 │ * 8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data" 16 │ */
L12 flow ThreatModel → #dashboard
Model statistics input
7 │ * 8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data" 16 │ */ 17 │
L13 flow SourceFiles → #dashboard
Code snippet reads
8 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with user-controlled threat model data" 9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data" 16 │ */ 17 │ 18 │ import type { ThreatModel } from '../types/index.js';
L14 flow #dashboard → HTML
Generated HTML output
9 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() HTML-encodes all interpolated values" 10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data" 16 │ */ 17 │ 18 │ import type { ThreatModel } from '../types/index.js'; 19 │ import { computeStats, computeSeverity, computeExposures, computeAssetHeatmap } from './data.js';
L15 handles #dashboard: internal
Processes and displays threat model data
10 │ * @exposes #dashboard to #path-traversal [medium] cwe:CWE-22 -- "readFileSync reads code files for annotation context" 11 │ * @mitigates #dashboard against #path-traversal using #path-validation -- "resolve() with root constrains file access" 12 │ * @flows ThreatModel -> #dashboard via computeStats -- "Model statistics input" 13 │ * @flows SourceFiles -> #dashboard via readFileSync -- "Code snippet reads" 14 │ * @flows #dashboard -> HTML via return -- "Generated HTML output" 15 │ * @handles internal on #dashboard -- "Processes and displays threat model data" 16 │ */ 17 │ 18 │ import type { ThreatModel } from '../types/index.js'; 19 │ import { computeStats, computeSeverity, computeExposures, computeAssetHeatmap } from './data.js'; 20 │ import type { DashboardStats, SeverityBreakdown, ExposureRow, AssetHeatmapEntry } from './data.js';
src/dashboard/index.ts 4
L4 exposes #dashboard → #xss
Generates HTML with threat model data
1 │ /** 2 │ * GuardLink Dashboard — Self-contained HTML threat model dashboard. 3 │ * 4 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with threat model data" 5 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() function encodes all interpolated values" 6 │ * @flows ThreatModel -> #dashboard via generateDashboardHTML -- "Model to HTML transformation" 7 │ * @comment -- "Self-contained HTML; no external data injection after generation" 8 │ */ 9 │
L5 mitigates #output-encoding mitigates #xss
esc() function encodes all interpolated values
1 │ /** 2 │ * GuardLink Dashboard — Self-contained HTML threat model dashboard. 3 │ * 4 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with threat model data" 5 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() function encodes all interpolated values" 6 │ * @flows ThreatModel -> #dashboard via generateDashboardHTML -- "Model to HTML transformation" 7 │ * @comment -- "Self-contained HTML; no external data injection after generation" 8 │ */ 9 │ 10 │ export { generateDashboardHTML } from './generate.js';
L6 flow ThreatModel → #dashboard
Model to HTML transformation
1 │ /** 2 │ * GuardLink Dashboard — Self-contained HTML threat model dashboard. 3 │ * 4 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with threat model data" 5 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() function encodes all interpolated values" 6 │ * @flows ThreatModel -> #dashboard via generateDashboardHTML -- "Model to HTML transformation" 7 │ * @comment -- "Self-contained HTML; no external data injection after generation" 8 │ */ 9 │ 10 │ export { generateDashboardHTML } from './generate.js'; 11 │ export { computeStats, computeSeverity, computeExposures, computeAssetHeatmap } from './data.js';
L7 comment Self-contained HTML; no external data injection after generation
Self-contained HTML; no external data injection after generation
2 │ * GuardLink Dashboard — Self-contained HTML threat model dashboard. 3 │ * 4 │ * @exposes #dashboard to #xss [high] cwe:CWE-79 -- "Generates HTML with threat model data" 5 │ * @mitigates #dashboard against #xss using #output-encoding -- "esc() function encodes all interpolated values" 6 │ * @flows ThreatModel -> #dashboard via generateDashboardHTML -- "Model to HTML transformation" 7 │ * @comment -- "Self-contained HTML; no external data injection after generation" 8 │ */ 9 │ 10 │ export { generateDashboardHTML } from './generate.js'; 11 │ export { computeStats, computeSeverity, computeExposures, computeAssetHeatmap } from './data.js'; 12 │ export { generateThreatGraph, generateDataFlowDiagram, generateAttackSurface } from './diagrams.js';
src/diff/git.ts 10
L6 exposes #diff → #cmd-injection
execSync runs git commands with ref argument
1 │ /** 2 │ * GuardLink Diff — Git integration. 3 │ * Resolves git refs to threat models by checking out files at a given commit 4 │ * and parsing them in a temp directory. 5 │ * 6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree"
L7 mitigates #input-sanitize mitigates #cmd-injection
rev-parse validates ref exists before use in other commands
2 │ * GuardLink Diff — Git integration. 3 │ * Resolves git refs to threat models by checking out files at a given commit 4 │ * and parsing them in a temp directory. 5 │ * 6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution"
L8 exposes #diff → #arbitrary-write
writeFileSync creates files in temp directory
3 │ * Resolves git refs to threat models by checking out files at a given commit 4 │ * and parsing them in a temp directory. 5 │ * 6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes"
L9 mitigates #path-validation mitigates #arbitrary-write
mkdtempSync creates isolated temp dir; rmSync cleans up
4 │ * and parsing them in a temp directory. 5 │ * 6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output"
L10 exposes #diff → #path-traversal
git show extracts files based on ls-tree output
5 │ * 6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution"
L11 mitigates #glob-filtering mitigates #path-traversal
Files constrained to relevantFiles from git ls-tree
6 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "execSync runs git commands with ref argument" 7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution" 16 │ */
L12 flow GitRef → #diff
Git command execution
7 │ * @mitigates #diff against #cmd-injection using #input-sanitize -- "rev-parse validates ref exists before use in other commands" 8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution" 16 │ */ 17 │
L13 flow #diff → TempDir
Extracted file writes
8 │ * @exposes #diff to #arbitrary-write [medium] cwe:CWE-73 -- "writeFileSync creates files in temp directory" 9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution" 16 │ */ 17 │ 18 │ import { execSync } from 'node:child_process';
L14 flow #diff → ThreatModel
Parsed model output
9 │ * @mitigates #diff against #arbitrary-write using #path-validation -- "mkdtempSync creates isolated temp dir; rmSync cleans up" 10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution" 16 │ */ 17 │ 18 │ import { execSync } from 'node:child_process'; 19 │ import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
L15 boundary #diff ↔ GitRepo
Trust boundary at git command execution
10 │ * @exposes #diff to #path-traversal [medium] cwe:CWE-22 -- "git show extracts files based on ls-tree output" 11 │ * @mitigates #diff against #path-traversal using #glob-filtering -- "Files constrained to relevantFiles from git ls-tree" 12 │ * @flows GitRef -> #diff via execSync -- "Git command execution" 13 │ * @flows #diff -> TempDir via writeFileSync -- "Extracted file writes" 14 │ * @flows #diff -> ThreatModel via parseProject -- "Parsed model output" 15 │ * @boundary #diff and GitRepo (#git-boundary) -- "Trust boundary at git command execution" 16 │ */ 17 │ 18 │ import { execSync } from 'node:child_process'; 19 │ import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs'; 20 │ import { join } from 'node:path';
src/diff/index.ts 3
L4 exposes #diff → #cmd-injection
git.ts uses execSync with ref argument
1 │ /** 2 │ * GuardLink Diff — exports. 3 │ * 4 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "git.ts uses execSync with ref argument" 5 │ * @audit #diff -- "Git commands use execSync; ref is validated with rev-parse before use" 6 │ * @flows GitRef -> #diff via parseAtRef -- "Git reference input" 7 │ */ 8 │ 9 │ export { diffModels, type ThreatModelDiff, type DiffSummary, type Change, type ChangeKind } from './engine.js';
L5 audit Audit: #diff
Git commands use execSync; ref is validated with rev-parse before use
1 │ /** 2 │ * GuardLink Diff — exports. 3 │ * 4 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "git.ts uses execSync with ref argument" 5 │ * @audit #diff -- "Git commands use execSync; ref is validated with rev-parse before use" 6 │ * @flows GitRef -> #diff via parseAtRef -- "Git reference input" 7 │ */ 8 │ 9 │ export { diffModels, type ThreatModelDiff, type DiffSummary, type Change, type ChangeKind } from './engine.js'; 10 │ export { formatDiff, formatDiffMarkdown } from './format.js';
L6 flow GitRef → #diff
Git reference input
1 │ /** 2 │ * GuardLink Diff — exports. 3 │ * 4 │ * @exposes #diff to #cmd-injection [high] cwe:CWE-78 -- "git.ts uses execSync with ref argument" 5 │ * @audit #diff -- "Git commands use execSync; ref is validated with rev-parse before use" 6 │ * @flows GitRef -> #diff via parseAtRef -- "Git reference input" 7 │ */ 8 │ 9 │ export { diffModels, type ThreatModelDiff, type DiffSummary, type Change, type ChangeKind } from './engine.js'; 10 │ export { formatDiff, formatDiffMarkdown } from './format.js'; 11 │ export { parseAtRef, getCurrentRef } from './git.js';
src/init/detect.ts 4
L5 exposes #init → #path-traversal
Reads package.json, pyproject.toml, etc. from root
1 │ /** 2 │ * GuardLink init — Project detection utilities. 3 │ * Detects language, project name, and existing agent instruction files. 4 │ * 5 │ * @exposes #init to #path-traversal [low] cwe:CWE-22 -- "Reads package.json, pyproject.toml, etc. from root" 6 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with root constrains; reads well-known files only" 7 │ * @flows ProjectRoot -> #init via detectProject -- "Project detection input" 8 │ * @comment -- "Detection is read-only; no file writes" 9 │ */ 10 │
L6 mitigates #path-validation mitigates #path-traversal
join() with root constrains; reads well-known files only
1 │ /** 2 │ * GuardLink init — Project detection utilities. 3 │ * Detects language, project name, and existing agent instruction files. 4 │ * 5 │ * @exposes #init to #path-traversal [low] cwe:CWE-22 -- "Reads package.json, pyproject.toml, etc. from root" 6 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with root constrains; reads well-known files only" 7 │ * @flows ProjectRoot -> #init via detectProject -- "Project detection input" 8 │ * @comment -- "Detection is read-only; no file writes" 9 │ */ 10 │ 11 │ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
L7 flow ProjectRoot → #init
Project detection input
2 │ * GuardLink init — Project detection utilities. 3 │ * Detects language, project name, and existing agent instruction files. 4 │ * 5 │ * @exposes #init to #path-traversal [low] cwe:CWE-22 -- "Reads package.json, pyproject.toml, etc. from root" 6 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with root constrains; reads well-known files only" 7 │ * @flows ProjectRoot -> #init via detectProject -- "Project detection input" 8 │ * @comment -- "Detection is read-only; no file writes" 9 │ */ 10 │ 11 │ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; 12 │ import { join, basename } from 'node:path';
L8 comment Detection is read-only; no file writes
Detection is read-only; no file writes
3 │ * Detects language, project name, and existing agent instruction files. 4 │ * 5 │ * @exposes #init to #path-traversal [low] cwe:CWE-22 -- "Reads package.json, pyproject.toml, etc. from root" 6 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with root constrains; reads well-known files only" 7 │ * @flows ProjectRoot -> #init via detectProject -- "Project detection input" 8 │ * @comment -- "Detection is read-only; no file writes" 9 │ */ 10 │ 11 │ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; 12 │ import { join, basename } from 'node:path'; 13 │
src/init/index.ts 10
L8 exposes #init → #arbitrary-write
Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc.
3 │ * 4 │ * Detects project language and existing agent files, creates .guardlink/ 5 │ * directory with shared definitions, and injects GuardLink instructions 6 │ * into agent instruction files (CLAUDE.md, .cursorrules, etc.). 7 │ * 8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically"
L9 mitigates #path-validation mitigates #arbitrary-write
All paths are relative to root; join() constrains
4 │ * Detects project language and existing agent files, creates .guardlink/ 5 │ * directory with shared definitions, and injects GuardLink instructions 6 │ * into agent instruction files (CLAUDE.md, .cursorrules, etc.). 7 │ * 8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input"
L10 exposes #init → #path-traversal
Reads/writes files based on root argument
5 │ * directory with shared definitions, and injects GuardLink instructions 6 │ * into agent instruction files (CLAUDE.md, .cursorrules, etc.). 7 │ * 8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes"
L11 mitigates #path-validation mitigates #path-traversal
join() with explicit root constrains file access
6 │ * into agent instruction files (CLAUDE.md, .cursorrules, etc.). 7 │ * 8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write"
L12 exposes #init → #data-exposure
Writes API key config to .guardlink/config.json
7 │ * 8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content"
L13 audit Audit: #init
Config file may contain API keys; .gitignore entry added automatically
8 │ * @exposes #init to #arbitrary-write [high] cwe:CWE-73 -- "Creates/modifies files: .guardlink/, CLAUDE.md, .cursorrules, etc." 9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content" 18 │ */
L14 flow ProjectRoot → #init
Project root input
9 │ * @mitigates #init against #arbitrary-write using #path-validation -- "All paths are relative to root; join() constrains" 10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content" 18 │ */ 19 │
L15 flow #init → AgentFiles
Agent instruction file writes
10 │ * @exposes #init to #path-traversal [medium] cwe:CWE-22 -- "Reads/writes files based on root argument" 11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content" 18 │ */ 19 │ 20 │ import { existsSync, readFileSync, mkdirSync, writeFileSync, appendFileSync } from 'node:fs';
L16 flow #init → ConfigFile
Config file write
11 │ * @mitigates #init against #path-traversal using #path-validation -- "join() with explicit root constrains file access" 12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content" 18 │ */ 19 │ 20 │ import { existsSync, readFileSync, mkdirSync, writeFileSync, appendFileSync } from 'node:fs'; 21 │ import { join, dirname } from 'node:path';
L17 handles #init: internal
Generates definitions and agent instruction content
12 │ * @exposes #init to #data-exposure [low] cwe:CWE-200 -- "Writes API key config to .guardlink/config.json" 13 │ * @audit #init -- "Config file may contain API keys; .gitignore entry added automatically" 14 │ * @flows ProjectRoot -> #init via options.root -- "Project root input" 15 │ * @flows #init -> AgentFiles via writeFileSync -- "Agent instruction file writes" 16 │ * @flows #init -> ConfigFile via writeFileSync -- "Config file write" 17 │ * @handles internal on #init -- "Generates definitions and agent instruction content" 18 │ */ 19 │ 20 │ import { existsSync, readFileSync, mkdirSync, writeFileSync, appendFileSync } from 'node:fs'; 21 │ import { join, dirname } from 'node:path'; 22 │ import { detectProject, type ProjectInfo, type AgentFile } from './detect.js';
src/mcp/index.ts 4
L4 exposes #mcp → #cmd-injection
Accepts tool calls from external MCP clients
1 │ /** 2 │ * GuardLink MCP Server — exports and stdio entry point. 3 │ * 4 │ * @exposes #mcp to #cmd-injection [high] cwe:CWE-78 -- "Accepts tool calls from external MCP clients" 5 │ * @audit #mcp -- "All tool calls validated by server.ts before execution" 6 │ * @flows MCPClient -> #mcp via stdio -- "MCP protocol transport" 7 │ * @boundary #mcp and MCPClient (#mcp-boundary) -- "Trust boundary at MCP protocol" 8 │ */ 9 │
L5 audit Audit: #mcp
All tool calls validated by server.ts before execution
1 │ /** 2 │ * GuardLink MCP Server — exports and stdio entry point. 3 │ * 4 │ * @exposes #mcp to #cmd-injection [high] cwe:CWE-78 -- "Accepts tool calls from external MCP clients" 5 │ * @audit #mcp -- "All tool calls validated by server.ts before execution" 6 │ * @flows MCPClient -> #mcp via stdio -- "MCP protocol transport" 7 │ * @boundary #mcp and MCPClient (#mcp-boundary) -- "Trust boundary at MCP protocol" 8 │ */ 9 │ 10 │ export { createServer } from './server.js';
L6 flow MCPClient → #mcp
MCP protocol transport
1 │ /** 2 │ * GuardLink MCP Server — exports and stdio entry point. 3 │ * 4 │ * @exposes #mcp to #cmd-injection [high] cwe:CWE-78 -- "Accepts tool calls from external MCP clients" 5 │ * @audit #mcp -- "All tool calls validated by server.ts before execution" 6 │ * @flows MCPClient -> #mcp via stdio -- "MCP protocol transport" 7 │ * @boundary #mcp and MCPClient (#mcp-boundary) -- "Trust boundary at MCP protocol" 8 │ */ 9 │ 10 │ export { createServer } from './server.js'; 11 │ export { lookup, type LookupResult } from './lookup.js';
L7 boundary #mcp ↔ MCPClient
Trust boundary at MCP protocol
2 │ * GuardLink MCP Server — exports and stdio entry point. 3 │ * 4 │ * @exposes #mcp to #cmd-injection [high] cwe:CWE-78 -- "Accepts tool calls from external MCP clients" 5 │ * @audit #mcp -- "All tool calls validated by server.ts before execution" 6 │ * @flows MCPClient -> #mcp via stdio -- "MCP protocol transport" 7 │ * @boundary #mcp and MCPClient (#mcp-boundary) -- "Trust boundary at MCP protocol" 8 │ */ 9 │ 10 │ export { createServer } from './server.js'; 11 │ export { lookup, type LookupResult } from './lookup.js'; 12 │ export { suggestAnnotations, type Suggestion, type SuggestOptions } from './suggest.js';
src/mcp/lookup.ts 4
L16 exposes #mcp → #redos
Regex patterns applied to query strings
11 │ * - "flows from #config" → data flows with source = config 12 │ * - "unmitigated" → all unmitigated exposures 13 │ * - "boundary #config" → boundaries involving asset 14 │ * - Free text → fuzzy match across assets, threats, controls 15 │ * 16 │ * @exposes #mcp to #redos [low] cwe:CWE-1333 -- "Regex patterns applied to query strings" 17 │ * @mitigates #mcp against #redos using #regex-anchoring -- "Patterns are simple and bounded" 18 │ * @flows QueryString -> #mcp via lookup -- "Query input path" 19 │ * @comment -- "Pure function; no I/O; operates on in-memory ThreatModel" 20 │ */ 21 │
L17 mitigates #regex-anchoring mitigates #redos
Patterns are simple and bounded
12 │ * - "unmitigated" → all unmitigated exposures 13 │ * - "boundary #config" → boundaries involving asset 14 │ * - Free text → fuzzy match across assets, threats, controls 15 │ * 16 │ * @exposes #mcp to #redos [low] cwe:CWE-1333 -- "Regex patterns applied to query strings" 17 │ * @mitigates #mcp against #redos using #regex-anchoring -- "Patterns are simple and bounded" 18 │ * @flows QueryString -> #mcp via lookup -- "Query input path" 19 │ * @comment -- "Pure function; no I/O; operates on in-memory ThreatModel" 20 │ */ 21 │ 22 │ import type {
L18 flow QueryString → #mcp
Query input path
13 │ * - "boundary #config" → boundaries involving asset 14 │ * - Free text → fuzzy match across assets, threats, controls 15 │ * 16 │ * @exposes #mcp to #redos [low] cwe:CWE-1333 -- "Regex patterns applied to query strings" 17 │ * @mitigates #mcp against #redos using #regex-anchoring -- "Patterns are simple and bounded" 18 │ * @flows QueryString -> #mcp via lookup -- "Query input path" 19 │ * @comment -- "Pure function; no I/O; operates on in-memory ThreatModel" 20 │ */ 21 │ 22 │ import type { 23 │ ThreatModel, ThreatModelAsset, ThreatModelThreat, ThreatModelControl,
L19 comment Pure function; no I/O; operates on in-memory ThreatModel
Pure function; no I/O; operates on in-memory ThreatModel
14 │ * - Free text → fuzzy match across assets, threats, controls 15 │ * 16 │ * @exposes #mcp to #redos [low] cwe:CWE-1333 -- "Regex patterns applied to query strings" 17 │ * @mitigates #mcp against #redos using #regex-anchoring -- "Patterns are simple and bounded" 18 │ * @flows QueryString -> #mcp via lookup -- "Query input path" 19 │ * @comment -- "Pure function; no I/O; operates on in-memory ThreatModel" 20 │ */ 21 │ 22 │ import type { 23 │ ThreatModel, ThreatModelAsset, ThreatModelThreat, ThreatModelControl, 24 │ ThreatModelExposure, ThreatModelMitigation, ThreatModelFlow,
src/mcp/server.ts 16
L26 exposes #mcp → #path-traversal
Tool arguments include 'root' directory path from external client
21 │ * guardlink://definitions — Assets, threats, controls 22 │ * guardlink://unmitigated — Unmitigated exposures list 23 │ * 24 │ * Transport: stdio (for Claude Code .mcp.json, Cursor, etc.) 25 │ * 26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only"
L27 mitigates #path-validation mitigates #path-traversal
Zod schema validates root; resolve() canonicalizes
22 │ * guardlink://unmitigated — Unmitigated exposures list 23 │ * 24 │ * Transport: stdio (for Claude Code .mcp.json, Cursor, etc.) 25 │ * 26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment"
L28 exposes #mcp → #arbitrary-write
report, dashboard, sarif tools write files
23 │ * 24 │ * Transport: stdio (for Claude Code .mcp.json, Cursor, etc.) 25 │ * 26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned"
L29 mitigates #path-validation mitigates #arbitrary-write
Output paths resolved relative to validated root
24 │ * Transport: stdio (for Claude Code .mcp.json, Cursor, etc.) 25 │ * 26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients"
L30 exposes #mcp → #prompt-injection
annotate and threat_report tools pass user prompts to LLM
25 │ * 26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents"
L31 audit Audit: #mcp
User prompts passed to LLM; model context is read-only
26 │ * @exposes #mcp to #path-traversal [high] cwe:CWE-22 -- "Tool arguments include 'root' directory path from external client" 27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input"
L32 exposes #mcp → #api-key-exposure
threat_report tool uses API keys from environment
27 │ * @mitigates #mcp against #path-traversal using #path-validation -- "Zod schema validates root; resolve() canonicalizes" 28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output"
L33 mitigates #key-redaction mitigates #api-key-exposure
Keys from env only; never logged or returned
28 │ * @exposes #mcp to #arbitrary-write [high] cwe:CWE-73 -- "report, dashboard, sarif tools write files" 29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path"
L34 exposes #mcp → #data-exposure
Resources expose full threat model to MCP clients
29 │ * @mitigates #mcp against #arbitrary-write using #path-validation -- "Output paths resolved relative to validated root" 30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output"
L35 audit Audit: #mcp
Threat model data intentionally exposed to connected agents
30 │ * @exposes #mcp to #prompt-injection [medium] cwe:CWE-77 -- "annotate and threat_report tools pass user prompts to LLM" 31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing"
L36 flow MCPClient → #mcp
Tool invocation input
31 │ * @audit #mcp -- "User prompts passed to LLM; model context is read-only" 32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data"
L37 flow #mcp → FileSystem
Report/dashboard output
32 │ * @exposes #mcp to #api-key-exposure [medium] cwe:CWE-798 -- "threat_report tool uses API keys from environment" 33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data" 42 │ */
L38 flow #mcp → #llm-client
LLM API call path
33 │ * @mitigates #mcp against #api-key-exposure using #key-redaction -- "Keys from env only; never logged or returned" 34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data" 42 │ */ 43 │
L39 flow #mcp → MCPClient
Threat model data output
34 │ * @exposes #mcp to #data-exposure [medium] cwe:CWE-200 -- "Resources expose full threat model to MCP clients" 35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data" 42 │ */ 43 │ 44 │ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
L40 boundary #mcp ↔ MCPClient
Trust boundary at tool argument parsing
35 │ * @audit #mcp -- "Threat model data intentionally exposed to connected agents" 36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data" 42 │ */ 43 │ 44 │ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; 45 │ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
L41 handles #mcp: internal
Processes project annotations and threat model data
36 │ * @flows MCPClient -> #mcp via tool_call -- "Tool invocation input" 37 │ * @flows #mcp -> FileSystem via writeFile -- "Report/dashboard output" 38 │ * @flows #mcp -> #llm-client via generateThreatReport -- "LLM API call path" 39 │ * @flows #mcp -> MCPClient via resource -- "Threat model data output" 40 │ * @boundary #mcp and MCPClient (#mcp-tool-boundary) -- "Trust boundary at tool argument parsing" 41 │ * @handles internal on #mcp -- "Processes project annotations and threat model data" 42 │ */ 43 │ 44 │ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; 45 │ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; 46 │ import { z } from 'zod';
src/mcp/suggest.ts 9
L12 exposes #suggest → #path-traversal
File path from MCP client joined with root
7 │ * - HTTP handlers, auth checks, input parsing 8 │ * - Missing annotations on files that handle sensitive data 9 │ * 10 │ * Designed for both file-based and diff-based analysis (§8.2). 11 │ * 12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes"
L13 mitigates #path-validation mitigates #path-traversal
join() with validated root constrains access
8 │ * - Missing annotations on files that handle sensitive data 9 │ * 10 │ * Designed for both file-based and diff-based analysis (§8.2). 11 │ * 12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path"
L14 exposes #suggest → #redos
Complex regex patterns applied to source code
9 │ * 10 │ * Designed for both file-based and diff-based analysis (§8.2). 11 │ * 12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output"
L15 mitigates #regex-anchoring mitigates #redos
Patterns designed with bounded quantifiers
10 │ * Designed for both file-based and diff-based analysis (§8.2). 11 │ * 12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories"
L16 exposes #suggest → #dos
Large files loaded into memory for pattern scanning
11 │ * 12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories" 21 │ */
L17 audit Audit: #suggest
File size is bounded by project scope; production use involves reasonable file sizes
12 │ * @exposes #suggest to #path-traversal [high] cwe:CWE-22 -- "File path from MCP client joined with root" 13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories" 21 │ */ 22 │
L18 flow FilePath → #suggest
File read path
13 │ * @mitigates #suggest against #path-traversal using #path-validation -- "join() with validated root constrains access" 14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories" 21 │ */ 22 │ 23 │ import { readFileSync, existsSync } from 'node:fs';
L19 flow #suggest → Suggestions
Suggestion output
14 │ * @exposes #suggest to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to source code" 15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories" 21 │ */ 22 │ 23 │ import { readFileSync, existsSync } from 'node:fs'; 24 │ import { join, extname } from 'node:path';
L20 comment Skips node_modules and .guardlink directories
Skips node_modules and .guardlink directories
15 │ * @mitigates #suggest against #redos using #regex-anchoring -- "Patterns designed with bounded quantifiers" 16 │ * @exposes #suggest to #dos [low] cwe:CWE-400 -- "Large files loaded into memory for pattern scanning" 17 │ * @audit #suggest -- "File size is bounded by project scope; production use involves reasonable file sizes" 18 │ * @flows FilePath -> #suggest via readFileSync -- "File read path" 19 │ * @flows #suggest -> Suggestions via suggestAnnotations -- "Suggestion output" 20 │ * @comment -- "Skips node_modules and .guardlink directories" 21 │ */ 22 │ 23 │ import { readFileSync, existsSync } from 'node:fs'; 24 │ import { join, extname } from 'node:path'; 25 │ import type { ThreatModel } from '../types/index.js';
src/parser/clear.ts 7
L7 exposes #parser → #arbitrary-write
Writes modified content back to discovered files
2 │ * GuardLink — Annotation clearing utility. 3 │ * Scans project source files and removes all GuardLink annotation comment lines. 4 │ * 5 │ * Used by `guardlink clear` and `/clear` to let users start fresh with annotations. 6 │ * 7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path"
L8 exposes #parser → #path-traversal
Glob patterns determine which files are modified
3 │ * Scans project source files and removes all GuardLink annotation comment lines. 4 │ * 5 │ * Used by `guardlink clear` and `/clear` to let users start fresh with annotations. 6 │ * 7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only"
L9 mitigates #glob-filtering mitigates #path-traversal
DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope
4 │ * 5 │ * Used by `guardlink clear` and `/clear` to let users start fresh with annotations. 6 │ * 7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only" 14 │ */
L10 audit Audit: #parser
Destructive operation requires explicit user confirmation via dryRun flag
5 │ * Used by `guardlink clear` and `/clear` to let users start fresh with annotations. 6 │ * 7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only" 14 │ */ 15 │
L11 flow ProjectRoot → #parser
File discovery path
6 │ * 7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only" 14 │ */ 15 │ 16 │ import fg from 'fast-glob';
L12 flow #parser → SourceFiles
Modified file write path
7 │ * @exposes #parser to #arbitrary-write [high] cwe:CWE-73 -- "Writes modified content back to discovered files" 8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only" 14 │ */ 15 │ 16 │ import fg from 'fast-glob'; 17 │ import { readFile, writeFile } from 'node:fs/promises';
L13 handles #parser: internal
Operates on project source files only
8 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns determine which files are modified" 9 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks sensitive dirs; cwd constrains scope" 10 │ * @audit #parser -- "Destructive operation requires explicit user confirmation via dryRun flag" 11 │ * @flows ProjectRoot -> #parser via fast-glob -- "File discovery path" 12 │ * @flows #parser -> SourceFiles via writeFile -- "Modified file write path" 13 │ * @handles internal on #parser -- "Operates on project source files only" 14 │ */ 15 │ 16 │ import fg from 'fast-glob'; 17 │ import { readFile, writeFile } from 'node:fs/promises'; 18 │ import { relative } from 'node:path';
src/parser/parse-file.ts 5
L5 exposes #parser → #path-traversal
File path from caller read via readFile; no validation here
1 │ /** 2 │ * GuardLink — File-level parser. 3 │ * Reads source files and extracts all GuardLink annotations. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "File path from caller read via readFile; no validation here" 6 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large files loaded entirely into memory" 7 │ * @audit #parser -- "Path validation delegated to callers (CLI/MCP validate root)" 8 │ * @flows FilePath -> #parser via readFile -- "Disk read path" 9 │ * @flows #parser -> Annotations via parseString -- "Parsed annotation output" 10 │ */
L6 exposes #parser → #dos
Large files loaded entirely into memory
1 │ /** 2 │ * GuardLink — File-level parser. 3 │ * Reads source files and extracts all GuardLink annotations. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "File path from caller read via readFile; no validation here" 6 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large files loaded entirely into memory" 7 │ * @audit #parser -- "Path validation delegated to callers (CLI/MCP validate root)" 8 │ * @flows FilePath -> #parser via readFile -- "Disk read path" 9 │ * @flows #parser -> Annotations via parseString -- "Parsed annotation output" 10 │ */ 11 │
L7 audit Audit: #parser
Path validation delegated to callers (CLI/MCP validate root)
2 │ * GuardLink — File-level parser. 3 │ * Reads source files and extracts all GuardLink annotations. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "File path from caller read via readFile; no validation here" 6 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large files loaded entirely into memory" 7 │ * @audit #parser -- "Path validation delegated to callers (CLI/MCP validate root)" 8 │ * @flows FilePath -> #parser via readFile -- "Disk read path" 9 │ * @flows #parser -> Annotations via parseString -- "Parsed annotation output" 10 │ */ 11 │ 12 │ import { readFile } from 'node:fs/promises';
L8 flow FilePath → #parser
Disk read path
3 │ * Reads source files and extracts all GuardLink annotations. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "File path from caller read via readFile; no validation here" 6 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large files loaded entirely into memory" 7 │ * @audit #parser -- "Path validation delegated to callers (CLI/MCP validate root)" 8 │ * @flows FilePath -> #parser via readFile -- "Disk read path" 9 │ * @flows #parser -> Annotations via parseString -- "Parsed annotation output" 10 │ */ 11 │ 12 │ import { readFile } from 'node:fs/promises'; 13 │ import { basename, extname } from 'node:path';
L9 flow #parser → Annotations
Parsed annotation output
4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "File path from caller read via readFile; no validation here" 6 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large files loaded entirely into memory" 7 │ * @audit #parser -- "Path validation delegated to callers (CLI/MCP validate root)" 8 │ * @flows FilePath -> #parser via readFile -- "Disk read path" 9 │ * @flows #parser -> Annotations via parseString -- "Parsed annotation output" 10 │ */ 11 │ 12 │ import { readFile } from 'node:fs/promises'; 13 │ import { basename, extname } from 'node:path'; 14 │ import type { Annotation, ParseDiagnostic, ParseResult } from '../types/index.js';
src/parser/parse-line.ts 3
L5 exposes #parser → #redos
Complex regex patterns applied to annotation text
1 │ /** 2 │ * GuardLink — Line-level annotation parser. 3 │ * Parses a single comment line into a typed Annotation. 4 │ * 5 │ * @exposes #parser to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to annotation text" 6 │ * @mitigates #parser against #redos using #regex-anchoring -- "All patterns are anchored (^...$) to prevent backtracking" 7 │ * @comment -- "Regex patterns designed with bounded quantifiers and explicit structure" 8 │ */ 9 │ 10 │ import type {
L6 mitigates #regex-anchoring mitigates #redos
All patterns are anchored (^...$) to prevent backtracking
1 │ /** 2 │ * GuardLink — Line-level annotation parser. 3 │ * Parses a single comment line into a typed Annotation. 4 │ * 5 │ * @exposes #parser to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to annotation text" 6 │ * @mitigates #parser against #redos using #regex-anchoring -- "All patterns are anchored (^...$) to prevent backtracking" 7 │ * @comment -- "Regex patterns designed with bounded quantifiers and explicit structure" 8 │ */ 9 │ 10 │ import type { 11 │ Annotation, AnnotationVerb, Severity, DataClassification,
L7 comment Regex patterns designed with bounded quantifiers and explicit structure
Regex patterns designed with bounded quantifiers and explicit structure
2 │ * GuardLink — Line-level annotation parser. 3 │ * Parses a single comment line into a typed Annotation. 4 │ * 5 │ * @exposes #parser to #redos [medium] cwe:CWE-1333 -- "Complex regex patterns applied to annotation text" 6 │ * @mitigates #parser against #redos using #regex-anchoring -- "All patterns are anchored (^...$) to prevent backtracking" 7 │ * @comment -- "Regex patterns designed with bounded quantifiers and explicit structure" 8 │ */ 9 │ 10 │ import type { 11 │ Annotation, AnnotationVerb, Severity, DataClassification, 12 │ ParseDiagnostic, SourceLocation,
src/parser/parse-project.ts 7
L5 exposes #parser → #path-traversal
Glob patterns could escape root directory
1 │ /** 2 │ * GuardLink — Project-level parser. 3 │ * Walks a directory, parses all source files, and assembles a ThreatModel. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output"
L6 mitigates #glob-filtering mitigates #path-traversal
DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan
1 │ /** 2 │ * GuardLink — Project-level parser. 3 │ * Walks a directory, parses all source files, and assembles a ThreatModel. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O"
L7 exposes #parser → #dos
Large projects with many files could exhaust memory
2 │ * GuardLink — Project-level parser. 3 │ * Walks a directory, parses all source files, and assembles a ThreatModel. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O" 12 │ */
L8 mitigates #resource-limits mitigates #dos
DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count
3 │ * Walks a directory, parses all source files, and assembles a ThreatModel. 4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O" 12 │ */ 13 │
L9 flow ProjectRoot → #parser
Directory traversal path
4 │ * 5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O" 12 │ */ 13 │ 14 │ import fg from 'fast-glob';
L10 flow #parser → ThreatModel
Aggregated threat model output
5 │ * @exposes #parser to #path-traversal [high] cwe:CWE-22 -- "Glob patterns could escape root directory" 6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O" 12 │ */ 13 │ 14 │ import fg from 'fast-glob'; 15 │ import { relative } from 'node:path';
L11 boundary #parser ↔ FileSystem
Trust boundary between parser and disk I/O
6 │ * @mitigates #parser against #path-traversal using #glob-filtering -- "DEFAULT_EXCLUDE blocks node_modules, .git; fast-glob cwd constrains scan" 7 │ * @exposes #parser to #dos [medium] cwe:CWE-400 -- "Large projects with many files could exhaust memory" 8 │ * @mitigates #parser against #dos using #resource-limits -- "DEFAULT_EXCLUDE skips build artifacts, tests; limits effective file count" 9 │ * @flows ProjectRoot -> #parser via fast-glob -- "Directory traversal path" 10 │ * @flows #parser -> ThreatModel via assembleModel -- "Aggregated threat model output" 11 │ * @boundary #parser and FileSystem (#fs-boundary) -- "Trust boundary between parser and disk I/O" 12 │ */ 13 │ 14 │ import fg from 'fast-glob'; 15 │ import { relative } from 'node:path'; 16 │ import type {
src/report/index.ts 2
L4 comment Report generation is pure transformation; no I/O in this module
Report generation is pure transformation; no I/O in this module
1 │ /** 2 │ * GuardLink Report — exports. 3 │ * 4 │ * @comment -- "Report generation is pure transformation; no I/O in this module" 5 │ * @comment -- "File writes handled by CLI/MCP callers" 6 │ */ 7 │ 8 │ export { generateMermaid } from './mermaid.js'; 9 │ export { generateReport } from './report.js';
L5 comment File writes handled by CLI/MCP callers
File writes handled by CLI/MCP callers
1 │ /** 2 │ * GuardLink Report — exports. 3 │ * 4 │ * @comment -- "Report generation is pure transformation; no I/O in this module" 5 │ * @comment -- "File writes handled by CLI/MCP callers" 6 │ */ 7 │ 8 │ export { generateMermaid } from './mermaid.js'; 9 │ export { generateReport } from './report.js'; 10 │
src/report/report.ts 4
L6 comment Pure function: transforms ThreatModel to markdown string
Pure function: transforms ThreatModel to markdown string
1 │ /** 2 │ * GuardLink Report — Markdown report generator. 3 │ * Produces a human-readable threat model report with 4 │ * embedded Mermaid diagram, finding tables, and coverage stats. 5 │ * 6 │ * @comment -- "Pure function: transforms ThreatModel to markdown string" 7 │ * @comment -- "No file I/O; caller (CLI/MCP) handles write" 8 │ * @flows ThreatModel -> #report via generateReport -- "Model input" 9 │ * @flows #report -> Markdown via return -- "Report output" 10 │ */ 11 │
L7 comment No file I/O; caller (CLI/MCP) handles write
No file I/O; caller (CLI/MCP) handles write
2 │ * GuardLink Report — Markdown report generator. 3 │ * Produces a human-readable threat model report with 4 │ * embedded Mermaid diagram, finding tables, and coverage stats. 5 │ * 6 │ * @comment -- "Pure function: transforms ThreatModel to markdown string" 7 │ * @comment -- "No file I/O; caller (CLI/MCP) handles write" 8 │ * @flows ThreatModel -> #report via generateReport -- "Model input" 9 │ * @flows #report -> Markdown via return -- "Report output" 10 │ */ 11 │ 12 │ import type { ThreatModel, ThreatModelExposure, Severity } from '../types/index.js';
L8 flow ThreatModel → #report
Model input
3 │ * Produces a human-readable threat model report with 4 │ * embedded Mermaid diagram, finding tables, and coverage stats. 5 │ * 6 │ * @comment -- "Pure function: transforms ThreatModel to markdown string" 7 │ * @comment -- "No file I/O; caller (CLI/MCP) handles write" 8 │ * @flows ThreatModel -> #report via generateReport -- "Model input" 9 │ * @flows #report -> Markdown via return -- "Report output" 10 │ */ 11 │ 12 │ import type { ThreatModel, ThreatModelExposure, Severity } from '../types/index.js'; 13 │ import { generateMermaid } from './mermaid.js';
L9 flow #report → Markdown
Report output
4 │ * embedded Mermaid diagram, finding tables, and coverage stats. 5 │ * 6 │ * @comment -- "Pure function: transforms ThreatModel to markdown string" 7 │ * @comment -- "No file I/O; caller (CLI/MCP) handles write" 8 │ * @flows ThreatModel -> #report via generateReport -- "Model input" 9 │ * @flows #report -> Markdown via return -- "Report output" 10 │ */ 11 │ 12 │ import type { ThreatModel, ThreatModelExposure, Severity } from '../types/index.js'; 13 │ import { generateMermaid } from './mermaid.js'; 14 │
src/review/index.ts 6
L10 exposes #cli → #arbitrary-write
Writes @accepts/@audit annotations into source files
5 │ * Users walk through the GAL (Governance Acceptance List) and decide: 6 │ * accept — write @accepts + @audit (risk acknowledged, intentional) 7 │ * remediate — write @audit with planned-fix note 8 │ * skip — leave open for now 9 │ * 10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text"
L11 mitigates #path-validation mitigates #arbitrary-write
Only modifies files already in the parsed project
6 │ * accept — write @accepts + @audit (risk acknowledged, intentional) 7 │ * remediate — write @audit with planned-fix note 8 │ * skip — leave open for now 9 │ * 10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text" 16 │ */
L12 audit Audit: #cli
Review decisions require human justification; no empty accepts allowed
7 │ * remediate — write @audit with planned-fix note 8 │ * skip — leave open for now 9 │ * 10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text" 16 │ */ 17 │
L13 flow ThreatModel → #cli
Exposure list input
8 │ * skip — leave open for now 9 │ * 10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text" 16 │ */ 17 │ 18 │ import { readFile, writeFile } from 'node:fs/promises';
L14 flow #cli → SourceFiles
Annotation insertion output
9 │ * 10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text" 16 │ */ 17 │ 18 │ import { readFile, writeFile } from 'node:fs/promises'; 19 │ import { resolve } from 'node:path';
L15 handles #cli: internal
Processes exposure metadata and user justification text
10 │ * @exposes #cli to #arbitrary-write [medium] cwe:CWE-73 -- "Writes @accepts/@audit annotations into source files" 11 │ * @mitigates #cli against #arbitrary-write using #path-validation -- "Only modifies files already in the parsed project" 12 │ * @audit #cli -- "Review decisions require human justification; no empty accepts allowed" 13 │ * @flows ThreatModel -> #cli via getReviewableExposures -- "Exposure list input" 14 │ * @flows #cli -> SourceFiles via writeFile -- "Annotation insertion output" 15 │ * @handles internal on #cli -- "Processes exposure metadata and user justification text" 16 │ */ 17 │ 18 │ import { readFile, writeFile } from 'node:fs/promises'; 19 │ import { resolve } from 'node:path'; 20 │ import { stripCommentPrefix } from '../parser/comment-strip.js';
src/tui/commands.ts 15
L7 exposes #tui → #path-traversal
File paths from user args in /view, /sarif -o
2 │ * GuardLink TUI — Command implementations. 3 │ * 4 │ * Each command function takes (args, ctx) and prints output directly. 5 │ * Returns void. Throws on fatal errors. 6 │ * 7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts"
L8 mitigates #path-validation mitigates #path-traversal
resolve() with ctx.root constrains file access
3 │ * 4 │ * Each command function takes (args, ctx) and prints output directly. 5 │ * Returns void. Throws on fatal errors. 6 │ * 7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage"
L9 exposes #tui → #arbitrary-write
/report, /sarif, /dashboard write files
4 │ * Each command function takes (args, ctx) and prints output directly. 5 │ * Returns void. Throws on fatal errors. 6 │ * 7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output"
L10 mitigates #path-validation mitigates #arbitrary-write
Output paths resolved relative to project root
5 │ * Returns void. Throws on fatal errors. 6 │ * 7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM"
L11 exposes #tui → #cmd-injection
/annotate and /threat-report spawn child processes
6 │ * 7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only"
L12 audit Audit: #tui
Child process spawning delegated to agents/launcher.ts
7 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "File paths from user args in /view, /sarif -o" 8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input"
L13 exposes #tui → #api-key-exposure
/model handles API key input and storage
8 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() with ctx.root constrains file access" 9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output"
L14 mitigates #key-redaction mitigates #api-key-exposure
API keys masked in /model show output
9 │ * @exposes #tui to #arbitrary-write [high] cwe:CWE-73 -- "/report, /sarif, /dashboard write files" 10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path"
L15 exposes #tui → #prompt-injection
Freeform chat sends user text to LLM
10 │ * @mitigates #tui against #arbitrary-write using #path-validation -- "Output paths resolved relative to project root" 11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path"
L16 audit Audit: #tui
User freeform text passed to LLM via cmdChat; model context is read-only
11 │ * @exposes #tui to #cmd-injection [high] cwe:CWE-78 -- "/annotate and /threat-report spawn child processes" 12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model"
L17 flow UserArgs → #tui
Command argument input
12 │ * @audit #tui -- "Child process spawning delegated to agents/launcher.ts" 13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model" 22 │ */
L18 flow #tui → FileSystem
Report/config output
13 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "/model handles API key input and storage" 14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model" 22 │ */ 23 │
L19 flow #tui → #agent-launcher
Agent spawn path
14 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "API keys masked in /model show output" 15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model" 22 │ */ 23 │ 24 │ import { resolve, basename, isAbsolute } from 'node:path';
L20 flow #tui → #llm-client
LLM API call path
15 │ * @exposes #tui to #prompt-injection [medium] cwe:CWE-77 -- "Freeform chat sends user text to LLM" 16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model" 22 │ */ 23 │ 24 │ import { resolve, basename, isAbsolute } from 'node:path'; 25 │ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
L21 handles #tui: secrets
Processes and stores API keys via /model
16 │ * @audit #tui -- "User freeform text passed to LLM via cmdChat; model context is read-only" 17 │ * @flows UserArgs -> #tui via args -- "Command argument input" 18 │ * @flows #tui -> FileSystem via writeFile -- "Report/config output" 19 │ * @flows #tui -> #agent-launcher via launchAgent -- "Agent spawn path" 20 │ * @flows #tui -> #llm-client via chatCompletion -- "LLM API call path" 21 │ * @handles secrets on #tui -- "Processes and stores API keys via /model" 22 │ */ 23 │ 24 │ import { resolve, basename, isAbsolute } from 'node:path'; 25 │ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs'; 26 │ import { parseProject, findDanglingRefs, findUnmitigatedExposures, findAcceptedWithoutAudit, findAcceptedExposures, clearAnnotations } from '../parser/index.js';
src/tui/config.ts 5
L7 exposes #tui → #api-key-exposure
API keys loaded from and saved to config files
2 │ * GuardLink TUI — Config persistence for LLM settings. 3 │ * 4 │ * Now delegates to the unified agents/config.ts resolution chain. 5 │ * Keeps backward compatibility with tui-config.json (legacy). 6 │ * 7 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from and saved to config files" 8 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "Delegates to agents/config.ts with masking" 9 │ * @flows ConfigFile -> #tui via loadProjectConfig -- "Config load path" 10 │ * @flows #tui -> ConfigFile via saveProjectConfig -- "Config save path" 11 │ * @handles secrets on #tui -- "API keys stored in .guardlink/config.json" 12 │ */
L8 mitigates #key-redaction mitigates #api-key-exposure
Delegates to agents/config.ts with masking
3 │ * 4 │ * Now delegates to the unified agents/config.ts resolution chain. 5 │ * Keeps backward compatibility with tui-config.json (legacy). 6 │ * 7 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from and saved to config files" 8 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "Delegates to agents/config.ts with masking" 9 │ * @flows ConfigFile -> #tui via loadProjectConfig -- "Config load path" 10 │ * @flows #tui -> ConfigFile via saveProjectConfig -- "Config save path" 11 │ * @handles secrets on #tui -- "API keys stored in .guardlink/config.json" 12 │ */ 13 │
L9 flow ConfigFile → #tui
Config load path
4 │ * Now delegates to the unified agents/config.ts resolution chain. 5 │ * Keeps backward compatibility with tui-config.json (legacy). 6 │ * 7 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from and saved to config files" 8 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "Delegates to agents/config.ts with masking" 9 │ * @flows ConfigFile -> #tui via loadProjectConfig -- "Config load path" 10 │ * @flows #tui -> ConfigFile via saveProjectConfig -- "Config save path" 11 │ * @handles secrets on #tui -- "API keys stored in .guardlink/config.json" 12 │ */ 13 │ 14 │ import type { LLMConfig, LLMProvider } from '../analyze/llm.js';
L10 flow #tui → ConfigFile
Config save path
5 │ * Keeps backward compatibility with tui-config.json (legacy). 6 │ * 7 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from and saved to config files" 8 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "Delegates to agents/config.ts with masking" 9 │ * @flows ConfigFile -> #tui via loadProjectConfig -- "Config load path" 10 │ * @flows #tui -> ConfigFile via saveProjectConfig -- "Config save path" 11 │ * @handles secrets on #tui -- "API keys stored in .guardlink/config.json" 12 │ */ 13 │ 14 │ import type { LLMConfig, LLMProvider } from '../analyze/llm.js'; 15 │ import { resolveConfig, saveProjectConfig, loadProjectConfig } from '../agents/config.js';
L11 handles #tui: secrets
API keys stored in .guardlink/config.json
6 │ * 7 │ * @exposes #tui to #api-key-exposure [high] cwe:CWE-798 -- "API keys loaded from and saved to config files" 8 │ * @mitigates #tui against #api-key-exposure using #key-redaction -- "Delegates to agents/config.ts with masking" 9 │ * @flows ConfigFile -> #tui via loadProjectConfig -- "Config load path" 10 │ * @flows #tui -> ConfigFile via saveProjectConfig -- "Config save path" 11 │ * @handles secrets on #tui -- "API keys stored in .guardlink/config.json" 12 │ */ 13 │ 14 │ import type { LLMConfig, LLMProvider } from '../analyze/llm.js'; 15 │ import { resolveConfig, saveProjectConfig, loadProjectConfig } from '../agents/config.js'; 16 │
src/tui/index.ts 8
L9 exposes #tui → #path-traversal
User-supplied dir argument resolved via path.resolve
4 │ * GuardLink TUI — Interactive terminal interface. 5 │ * 6 │ * Claude Code-style inline REPL: stays in your terminal, 7 │ * slash commands + freeform AI chat, Ctrl+C to exit. 8 │ * 9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing"
L10 mitigates #path-validation mitigates #path-traversal
resolve() canonicalizes paths; starts from cwd
5 │ * 6 │ * Claude Code-style inline REPL: stays in your terminal, 7 │ * slash commands + freeform AI chat, Ctrl+C to exit. 8 │ * 9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input"
L11 exposes #tui → #api-key-exposure
API keys displayed in banner via resolveLLMConfig
6 │ * Claude Code-style inline REPL: stays in your terminal, 7 │ * slash commands + freeform AI chat, Ctrl+C to exit. 8 │ * 9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys"
L12 audit Audit: #tui
API keys masked via maskKey() in banner display
7 │ * slash commands + freeform AI chat, Ctrl+C to exit. 8 │ * 9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys" 17 │ */
L13 flow UserInput → #tui
Interactive command input
8 │ * 9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys" 17 │ */ 18 │
L14 flow #tui → Commands
Command routing
9 │ * @exposes #tui to #path-traversal [high] cwe:CWE-22 -- "User-supplied dir argument resolved via path.resolve" 10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys" 17 │ */ 18 │ 19 │ import { createInterface, type Interface } from 'node:readline';
L15 boundary #tui ↔ UserInput
Trust boundary at interactive input
10 │ * @mitigates #tui against #path-traversal using #path-validation -- "resolve() canonicalizes paths; starts from cwd" 11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys" 17 │ */ 18 │ 19 │ import { createInterface, type Interface } from 'node:readline'; 20 │ import { resolve, basename } from 'node:path';
L16 handles #tui: secrets
Displays LLM config including masked API keys
11 │ * @exposes #tui to #api-key-exposure [medium] cwe:CWE-798 -- "API keys displayed in banner via resolveLLMConfig" 12 │ * @audit #tui -- "API keys masked via maskKey() in banner display" 13 │ * @flows UserInput -> #tui via readline -- "Interactive command input" 14 │ * @flows #tui -> Commands via dispatch -- "Command routing" 15 │ * @boundary #tui and UserInput (#tui-input-boundary) -- "Trust boundary at interactive input" 16 │ * @handles secrets on #tui -- "Displays LLM config including masked API keys" 17 │ */ 18 │ 19 │ import { createInterface, type Interface } from 'node:readline'; 20 │ import { resolve, basename } from 'node:path'; 21 │ import { existsSync, readFileSync } from 'node:fs';
src/tui/input.ts 5
L15 exposes #tui → #dos
Rapid keystrokes could consume CPU in raw mode
10 │ * /files Browse files 11 │ * /assets Asset tree 12 │ * 13 │ * Uses raw stdin mode for full keystroke control. 14 │ * 15 │ * @exposes #tui to #dos [low] cwe:CWE-400 -- "Rapid keystrokes could consume CPU in raw mode" 16 │ * @mitigates #tui against #dos using #resource-limits -- "Keystroke buffer bounded by terminal width" 17 │ * @flows RawStdin -> #tui via process.stdin -- "Raw keystroke input" 18 │ * @flows #tui -> Terminal via process.stdout -- "ANSI escape sequence output" 19 │ * @comment -- "Raw mode enables full keystroke control for command palette" 20 │ */
L16 mitigates #resource-limits mitigates #dos
Keystroke buffer bounded by terminal width
11 │ * /assets Asset tree 12 │ * 13 │ * Uses raw stdin mode for full keystroke control. 14 │ * 15 │ * @exposes #tui to #dos [low] cwe:CWE-400 -- "Rapid keystrokes could consume CPU in raw mode" 16 │ * @mitigates #tui against #dos using #resource-limits -- "Keystroke buffer bounded by terminal width" 17 │ * @flows RawStdin -> #tui via process.stdin -- "Raw keystroke input" 18 │ * @flows #tui -> Terminal via process.stdout -- "ANSI escape sequence output" 19 │ * @comment -- "Raw mode enables full keystroke control for command palette" 20 │ */ 21 │
L17 flow RawStdin → #tui
Raw keystroke input
12 │ * 13 │ * Uses raw stdin mode for full keystroke control. 14 │ * 15 │ * @exposes #tui to #dos [low] cwe:CWE-400 -- "Rapid keystrokes could consume CPU in raw mode" 16 │ * @mitigates #tui against #dos using #resource-limits -- "Keystroke buffer bounded by terminal width" 17 │ * @flows RawStdin -> #tui via process.stdin -- "Raw keystroke input" 18 │ * @flows #tui -> Terminal via process.stdout -- "ANSI escape sequence output" 19 │ * @comment -- "Raw mode enables full keystroke control for command palette" 20 │ */ 21 │ 22 │ import chalk from 'chalk';
L18 flow #tui → Terminal
ANSI escape sequence output
13 │ * Uses raw stdin mode for full keystroke control. 14 │ * 15 │ * @exposes #tui to #dos [low] cwe:CWE-400 -- "Rapid keystrokes could consume CPU in raw mode" 16 │ * @mitigates #tui against #dos using #resource-limits -- "Keystroke buffer bounded by terminal width" 17 │ * @flows RawStdin -> #tui via process.stdin -- "Raw keystroke input" 18 │ * @flows #tui -> Terminal via process.stdout -- "ANSI escape sequence output" 19 │ * @comment -- "Raw mode enables full keystroke control for command palette" 20 │ */ 21 │ 22 │ import chalk from 'chalk'; 23 │
L19 comment Raw mode enables full keystroke control for command palette
Raw mode enables full keystroke control for command palette
14 │ * 15 │ * @exposes #tui to #dos [low] cwe:CWE-400 -- "Rapid keystrokes could consume CPU in raw mode" 16 │ * @mitigates #tui against #dos using #resource-limits -- "Keystroke buffer bounded by terminal width" 17 │ * @flows RawStdin -> #tui via process.stdin -- "Raw keystroke input" 18 │ * @flows #tui -> Terminal via process.stdout -- "ANSI escape sequence output" 19 │ * @comment -- "Raw mode enables full keystroke control for command palette" 20 │ */ 21 │ 22 │ import chalk from 'chalk'; 23 │ 24 │ const BRAVOS = '#2dd4a7';
src/workspace/index.ts 1
L4 comment Workspace module: config loading, merge engine, link-project setup
Workspace module: config loading, merge engine, link-project setup
1 │ /** 2 │ * GuardLink Workspace — Multi-repo linking and merge. 3 │ * 4 │ * @comment -- "Workspace module: config loading, merge engine, link-project setup" 5 │ */ 6 │ 7 │ export type { 8 │ WorkspaceConfig, WorkspaceRepo, 9 │ TagOwnership, UnresolvedRef, MergeWarning, MergeWarningCode,
src/workspace/link.ts 3
L7 asset Workspace.Link
Multi-repo workspace linking setup
2 │ * GuardLink Workspace — link-project command logic. 3 │ * 4 │ * Scaffolds workspace.yaml in each repo and updates agent instruction 5 │ * files with workspace context so agents write cross-repo-aware annotations. 6 │ * 7 │ * @asset Workspace.Link (#workspace-link) -- "Multi-repo workspace linking setup" 8 │ * @flows UserArgs -> #workspace-link via linkProject -- "CLI args to workspace scaffolding" 9 │ * @flows #workspace-link -> AgentFiles via updateAgentWorkspaceContext -- "Inject workspace context" 10 │ */ 11 │ 12 │ import { existsSync, readFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from 'node:fs';
L8 flow UserArgs → #workspace-link
CLI args to workspace scaffolding
3 │ * 4 │ * Scaffolds workspace.yaml in each repo and updates agent instruction 5 │ * files with workspace context so agents write cross-repo-aware annotations. 6 │ * 7 │ * @asset Workspace.Link (#workspace-link) -- "Multi-repo workspace linking setup" 8 │ * @flows UserArgs -> #workspace-link via linkProject -- "CLI args to workspace scaffolding" 9 │ * @flows #workspace-link -> AgentFiles via updateAgentWorkspaceContext -- "Inject workspace context" 10 │ */ 11 │ 12 │ import { existsSync, readFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from 'node:fs'; 13 │ import { writeFileSync } from 'node:fs';
L9 flow #workspace-link → AgentFiles
Inject workspace context
4 │ * Scaffolds workspace.yaml in each repo and updates agent instruction 5 │ * files with workspace context so agents write cross-repo-aware annotations. 6 │ * 7 │ * @asset Workspace.Link (#workspace-link) -- "Multi-repo workspace linking setup" 8 │ * @flows UserArgs -> #workspace-link via linkProject -- "CLI args to workspace scaffolding" 9 │ * @flows #workspace-link -> AgentFiles via updateAgentWorkspaceContext -- "Inject workspace context" 10 │ */ 11 │ 12 │ import { existsSync, readFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from 'node:fs'; 13 │ import { writeFileSync } from 'node:fs'; 14 │ import { resolve, basename, dirname, join } from 'node:path';
src/workspace/merge.ts 5
L7 asset Workspace.Merge
Cross-repo threat model unification
2 │ * GuardLink Workspace — Merge engine for multi-repo reports. 3 │ * 4 │ * Takes N per-repo report JSONs and produces a unified MergedReport 5 │ * with cross-repo tag resolution, warning detection, and aggregated stats. 6 │ * 7 │ * @asset Workspace.Merge (#merge-engine) -- "Cross-repo threat model unification" 8 │ * @threat Tag_Collision (#tag-collision) [medium] -- "Duplicate tag definitions across repos" 9 │ * @mitigates #merge-engine against #tag-collision using #prefix-ownership -- "Tag prefix determines owning repo" 10 │ * @flows ReportJSON -> #merge-engine via mergeReports -- "Per-repo reports feed into merge" 11 │ * @flows #merge-engine -> MergedReport via mergeReports -- "Unified output" 12 │ */
L8 threat Tag_Collision
Duplicate tag definitions across repos
3 │ * 4 │ * Takes N per-repo report JSONs and produces a unified MergedReport 5 │ * with cross-repo tag resolution, warning detection, and aggregated stats. 6 │ * 7 │ * @asset Workspace.Merge (#merge-engine) -- "Cross-repo threat model unification" 8 │ * @threat Tag_Collision (#tag-collision) [medium] -- "Duplicate tag definitions across repos" 9 │ * @mitigates #merge-engine against #tag-collision using #prefix-ownership -- "Tag prefix determines owning repo" 10 │ * @flows ReportJSON -> #merge-engine via mergeReports -- "Per-repo reports feed into merge" 11 │ * @flows #merge-engine -> MergedReport via mergeReports -- "Unified output" 12 │ */ 13 │
L9 mitigates #prefix-ownership mitigates #tag-collision
Tag prefix determines owning repo
4 │ * Takes N per-repo report JSONs and produces a unified MergedReport 5 │ * with cross-repo tag resolution, warning detection, and aggregated stats. 6 │ * 7 │ * @asset Workspace.Merge (#merge-engine) -- "Cross-repo threat model unification" 8 │ * @threat Tag_Collision (#tag-collision) [medium] -- "Duplicate tag definitions across repos" 9 │ * @mitigates #merge-engine against #tag-collision using #prefix-ownership -- "Tag prefix determines owning repo" 10 │ * @flows ReportJSON -> #merge-engine via mergeReports -- "Per-repo reports feed into merge" 11 │ * @flows #merge-engine -> MergedReport via mergeReports -- "Unified output" 12 │ */ 13 │ 14 │ import { readFile } from 'node:fs/promises';
L10 flow ReportJSON → #merge-engine
Per-repo reports feed into merge
5 │ * with cross-repo tag resolution, warning detection, and aggregated stats. 6 │ * 7 │ * @asset Workspace.Merge (#merge-engine) -- "Cross-repo threat model unification" 8 │ * @threat Tag_Collision (#tag-collision) [medium] -- "Duplicate tag definitions across repos" 9 │ * @mitigates #merge-engine against #tag-collision using #prefix-ownership -- "Tag prefix determines owning repo" 10 │ * @flows ReportJSON -> #merge-engine via mergeReports -- "Per-repo reports feed into merge" 11 │ * @flows #merge-engine -> MergedReport via mergeReports -- "Unified output" 12 │ */ 13 │ 14 │ import { readFile } from 'node:fs/promises'; 15 │ import { basename } from 'node:path';
L11 flow #merge-engine → MergedReport
Unified output
6 │ * 7 │ * @asset Workspace.Merge (#merge-engine) -- "Cross-repo threat model unification" 8 │ * @threat Tag_Collision (#tag-collision) [medium] -- "Duplicate tag definitions across repos" 9 │ * @mitigates #merge-engine against #tag-collision using #prefix-ownership -- "Tag prefix determines owning repo" 10 │ * @flows ReportJSON -> #merge-engine via mergeReports -- "Per-repo reports feed into merge" 11 │ * @flows #merge-engine -> MergedReport via mergeReports -- "Unified output" 12 │ */ 13 │ 14 │ import { readFile } from 'node:fs/promises'; 15 │ import { basename } from 'node:path'; 16 │ import type {
src/workspace/metadata.ts 3
L7 asset Workspace.Metadata
Report provenance data
2 │ * GuardLink Workspace — Report metadata population. 3 │ * 4 │ * Enriches a ThreatModel with provenance metadata (git SHA, branch, 5 │ * workspace info) for the report JSON contract. 6 │ * 7 │ * @asset Workspace.Metadata (#report-metadata) -- "Report provenance data" 8 │ * @flows GitRepo -> #report-metadata via execSync -- "Git info extraction" 9 │ * @flows #report-metadata -> ThreatModel via populateMetadata -- "Metadata injection" 10 │ */ 11 │ 12 │ import { execSync } from 'node:child_process';
L8 flow GitRepo → #report-metadata
Git info extraction
3 │ * 4 │ * Enriches a ThreatModel with provenance metadata (git SHA, branch, 5 │ * workspace info) for the report JSON contract. 6 │ * 7 │ * @asset Workspace.Metadata (#report-metadata) -- "Report provenance data" 8 │ * @flows GitRepo -> #report-metadata via execSync -- "Git info extraction" 9 │ * @flows #report-metadata -> ThreatModel via populateMetadata -- "Metadata injection" 10 │ */ 11 │ 12 │ import { execSync } from 'node:child_process'; 13 │ import { readFileSync, existsSync } from 'node:fs';
L9 flow #report-metadata → ThreatModel
Metadata injection
4 │ * Enriches a ThreatModel with provenance metadata (git SHA, branch, 5 │ * workspace info) for the report JSON contract. 6 │ * 7 │ * @asset Workspace.Metadata (#report-metadata) -- "Report provenance data" 8 │ * @flows GitRepo -> #report-metadata via execSync -- "Git info extraction" 9 │ * @flows #report-metadata -> ThreatModel via populateMetadata -- "Metadata injection" 10 │ */ 11 │ 12 │ import { execSync } from 'node:child_process'; 13 │ import { readFileSync, existsSync } from 'node:fs'; 14 │ import { join } from 'node:path';
src/workspace/types.ts 3
L7 asset Workspace.Config
Multi-repo workspace definition
2 │ * GuardLink Workspace — Types for multi-repo linking. 3 │ * 4 │ * workspace.yaml lives in each repo's .guardlink/ directory. 5 │ * It declares membership in a workspace and lists sibling repos. 6 │ * 7 │ * @asset Workspace.Config (#workspace-config) -- "Multi-repo workspace definition" 8 │ * @threat Config_Tampering (#config-tamper) [medium] cwe:CWE-15 -- "Malicious workspace.yaml could misdirect agent annotations" 9 │ * @mitigates #workspace-config against #config-tamper using #yaml-validation -- "Schema validation on load" 10 │ */ 11 │ 12 │ import type { ThreatModel, Severity, ExternalRef } from '../types/index.js';
L8 threat Config_Tampering
Malicious workspace.yaml could misdirect agent annotations
3 │ * 4 │ * workspace.yaml lives in each repo's .guardlink/ directory. 5 │ * It declares membership in a workspace and lists sibling repos. 6 │ * 7 │ * @asset Workspace.Config (#workspace-config) -- "Multi-repo workspace definition" 8 │ * @threat Config_Tampering (#config-tamper) [medium] cwe:CWE-15 -- "Malicious workspace.yaml could misdirect agent annotations" 9 │ * @mitigates #workspace-config against #config-tamper using #yaml-validation -- "Schema validation on load" 10 │ */ 11 │ 12 │ import type { ThreatModel, Severity, ExternalRef } from '../types/index.js'; 13 │
L9 mitigates #yaml-validation mitigates #config-tamper
Schema validation on load
4 │ * workspace.yaml lives in each repo's .guardlink/ directory. 5 │ * It declares membership in a workspace and lists sibling repos. 6 │ * 7 │ * @asset Workspace.Config (#workspace-config) -- "Multi-repo workspace definition" 8 │ * @threat Config_Tampering (#config-tamper) [medium] cwe:CWE-15 -- "Malicious workspace.yaml could misdirect agent annotations" 9 │ * @mitigates #workspace-config against #config-tamper using #yaml-validation -- "Schema validation on load" 10 │ */ 11 │ 12 │ import type { ThreatModel, Severity, ExternalRef } from '../types/index.js'; 13 │ 14 │ // ─── Workspace Configuration (workspace.yaml) ───────────────────────
File Coverage
38 of 60 files have GuardLink annotations
⚠ Unannotated Files (22)

Source files with no GuardLink annotations. Not all files need annotations — only those touching security boundaries.

.github/ISSUE_TEMPLATE/bug_report.yml
.github/ISSUE_TEMPLATE/config.yml
.github/ISSUE_TEMPLATE/feature_request.yml
.github/workflows/ci.yml
.github/workflows/release.yml
examples/ci/per-repo-report.yml
examples/ci/workspace-merge.yml
examples/github-action.yml
src/dashboard/data.ts
src/dashboard/diagrams.ts
src/diff/engine.ts
src/diff/format.ts
src/index.ts
src/init/picker.ts
src/init/templates.ts
src/parser/comment-strip.ts
src/parser/index.ts
src/parser/normalize.ts
src/parser/validate.ts
src/report/mermaid.ts
src/tui/format.ts
src/types/index.ts
🔒 Data & Boundaries
Trust Boundaries
Side ASide BDescriptionLocation
#agent-launcher AgentProcess Trust boundary at process spawn src/agents/launcher.ts:20
#llm-client LLMProvider Trust boundary at external API call src/analyze/llm.ts:22
#llm-client NVD Trust boundary at external API src/analyze/tools.ts:18
#cli UserInput Trust boundary at CLI argument parsing src/cli/index.ts:35
#diff GitRepo Trust boundary at git command execution src/diff/git.ts:15
#mcp MCPClient Trust boundary at MCP protocol src/mcp/index.ts:7
#mcp MCPClient Trust boundary at tool argument parsing src/mcp/server.ts:40
#parser FileSystem Trust boundary between parser and disk I/O src/parser/parse-project.ts:11
#tui UserInput Trust boundary at interactive input src/tui/index.ts:15
Data Classifications
ClassificationAssetDescriptionLocation
secrets #agent-launcher Processes and stores LLM API keys src/agents/config.ts:22
internal #agent-launcher Serializes threat model IDs and flows into prompt src/agents/prompts.ts:13
internal #llm-client Processes project dependencies, env examples, code snippets src/analyze/index.ts:17
secrets #llm-client Processes API keys for authentication src/analyze/llm.ts:23
secrets #cli Processes API keys via config commands src/cli/index.ts:36
internal #dashboard Processes and displays threat model data src/dashboard/generate.ts:15
internal #init Generates definitions and agent instruction content src/init/index.ts:17
internal #mcp Processes project annotations and threat model data src/mcp/server.ts:41
internal #parser Operates on project source files only src/parser/clear.ts:13
internal #cli Processes exposure metadata and user justification text src/review/index.ts:15
secrets #tui Processes and stores API keys via /model src/tui/commands.ts:21
secrets #tui API keys stored in .guardlink/config.json src/tui/config.ts:11
secrets #tui Displays LLM config including masked API keys src/tui/index.ts:16
Audit Items (19)
AssetDescriptionLocation
#agent-launcher Prompt content is opaque to agent binary; injection risk depends on agent implementation src/agents/launcher.ts:14
#agent-launcher Timeout intentionally omitted for interactive sessions; inline mode has implicit control src/agents/launcher.ts:16
#agent-launcher Prompt injection mitigated by agent's own safety measures; GuardLink prompt is read-only context src/agents/prompts.ts:7
#llm-client Threat model data intentionally sent to LLM for analysis src/analyze/index.ts:13
#llm-client Prompt injection mitigated by LLM provider safety; local code is read-only src/analyze/llm.ts:18
#sarif SARIF output intentionally reveals security findings for CI/CD integration src/analyzer/sarif.ts:16
#cli Child process spawning delegated to agents/launcher.ts with explicit args src/cli/index.ts:32
#diff Git commands use execSync; ref is validated with rev-parse before use src/diff/index.ts:5
#init Config file may contain API keys; .gitignore entry added automatically src/init/index.ts:13
#mcp All tool calls validated by server.ts before execution src/mcp/index.ts:5
#mcp User prompts passed to LLM; model context is read-only src/mcp/server.ts:31
#mcp Threat model data intentionally exposed to connected agents src/mcp/server.ts:35
#suggest File size is bounded by project scope; production use involves reasonable file sizes src/mcp/suggest.ts:17
#parser Destructive operation requires explicit user confirmation via dryRun flag src/parser/clear.ts:10
#parser Path validation delegated to callers (CLI/MCP validate root) src/parser/parse-file.ts:7
#cli Review decisions require human justification; no empty accepts allowed src/review/index.ts:12
#tui Child process spawning delegated to agents/launcher.ts src/tui/commands.ts:12
#tui User freeform text passed to LLM via cmdChat; model context is read-only src/tui/commands.ts:16
#tui API keys masked via maskKey() in banner display src/tui/index.ts:12
Shielded Regions (16)

Code regions where annotations are intentionally suppressed via @shield.

ReasonLocation
Example annotation block for reference, excluded from parsing src/agents/prompts.ts:148
No reason provided src/agents/prompts.ts:161
Description examples, excluded from parsing src/agents/prompts.ts:168
No reason provided src/agents/prompts.ts:178
Flow examples, excluded from parsing src/agents/prompts.ts:185
No reason provided src/agents/prompts.ts:194
Boundary examples, excluded from parsing src/agents/prompts.ts:201
No reason provided src/agents/prompts.ts:207
Placement examples, excluded from parsing src/agents/prompts.ts:214
No reason provided src/agents/prompts.ts:223
@accepts alternative examples, excluded from parsing src/agents/prompts.ts:250
No reason provided src/agents/prompts.ts:260
Definition syntax examples, excluded from parsing src/agents/prompts.ts:277
No reason provided src/agents/prompts.ts:281
Relationship syntax examples, excluded from parsing src/agents/prompts.ts:286
No reason provided src/agents/prompts.ts:299
Developer Comments (18)
CommentLocation
Agent binaries are hardcoded; no user-controlled binary names src/agents/index.ts:7
parseAgentFlag extracts flags from args; no injection risk src/agents/index.ts:8
Prompt templates are static; no user input interpolation in system prompts src/analyze/prompts.ts:7
customPrompt is appended to user message, not system prompt — bounded injection risk src/analyze/prompts.ts:8
SARIF generation is pure transformation; no I/O in this module src/analyzer/index.ts:4
File writes handled by CLI/MCP callers src/analyzer/index.ts:5
Pure function: transforms ThreatModel to SARIF JSON; no I/O src/analyzer/sarif.ts:17
Self-contained HTML; no external data injection after generation src/dashboard/index.ts:7
Detection is read-only; no file writes src/init/detect.ts:8
Pure function; no I/O; operates on in-memory ThreatModel src/mcp/lookup.ts:19
Skips node_modules and .guardlink directories src/mcp/suggest.ts:20
Regex patterns designed with bounded quantifiers and explicit structure src/parser/parse-line.ts:7
Report generation is pure transformation; no I/O in this module src/report/index.ts:4
File writes handled by CLI/MCP callers src/report/index.ts:5
Pure function: transforms ThreatModel to markdown string src/report/report.ts:6
No file I/O; caller (CLI/MCP) handles write src/report/report.ts:7
Raw mode enables full keystroke control for command palette src/tui/input.ts:19
Workspace module: config loading, merge engine, link-project setup src/workspace/index.ts:4
🗺 Asset Risk Heatmap

Assets sorted by risk level. Unmitigated exposures increase risk. Click an asset for details.

#mcp
⚠ 7 🛡 4 ↔ 6
internal
#parser
⚠ 7 🛡 4 ↔ 6
internal
#tui
⚠ 9 🛡 6 ↔ 10
secretssecretssecrets
#agent-launcher
⚠ 8 🛡 6 ↔ 10
secretsinternal
#llm-client
⚠ 9 🛡 7 ↔ 11
internalsecrets
#sarif
⚠ 1 🛡 0 ↔ 2
#cli
⚠ 5 🛡 4 ↔ 4
secretsinternal
#diff
⚠ 4 🛡 3 ↔ 4
#init
⚠ 4 🛡 3 ↔ 4
internal
#suggest
⚠ 3 🛡 2 ↔ 2
#dashboard
⚠ 3 🛡 3 ↔ 4
internal
GuardLink.Parser
⚠ 0 🛡 0 ↔ 0
GuardLink.CLI
⚠ 0 🛡 0 ↔ 0
GuardLink.TUI
⚠ 0 🛡 0 ↔ 0
GuardLink.MCP
⚠ 0 🛡 0 ↔ 0
GuardLink.LLM_Client
⚠ 0 🛡 0 ↔ 0
GuardLink.Dashboard
⚠ 0 🛡 0 ↔ 0
GuardLink.Init
⚠ 0 🛡 0 ↔ 0
GuardLink.Agent_Launcher
⚠ 0 🛡 0 ↔ 0
GuardLink.Diff
⚠ 0 🛡 0 ↔ 0
GuardLink.Report
⚠ 0 🛡 0 ↔ 0
GuardLink.SARIF
⚠ 0 🛡 0 ↔ 0
GuardLink.Suggest
⚠ 0 🛡 0 ↔ 0
Workspace.Link
⚠ 0 🛡 0 ↔ 0
Workspace.Merge
⚠ 0 🛡 0 ↔ 0
Workspace.Metadata
⚠ 0 🛡 0 ↔ 0
Workspace.Config
⚠ 0 🛡 0 ↔ 0
#merge-engine
⚠ 0 🛡 1 ↔ 2
#workspace-config
⚠ 0 🛡 1 ↔ 0
EnvVars
⚠ 0 🛡 0 ↔ 1
ConfigFile
⚠ 0 🛡 0 ↔ 5
UserPrompt
⚠ 0 🛡 0 ↔ 2
AgentProcess
⚠ 0 🛡 0 ↔ 2
ThreatModel
⚠ 0 🛡 0 ↔ 10
AgentPrompt
⚠ 0 🛡 0 ↔ 1
ProjectFiles
⚠ 0 🛡 0 ↔ 2
ReportFile
⚠ 0 🛡 0 ↔ 1
LLMConfig
⚠ 0 🛡 0 ↔ 1
LLMProvider
⚠ 0 🛡 0 ↔ 2
LLMToolCall
⚠ 0 🛡 0 ↔ 1
NVD
⚠ 0 🛡 0 ↔ 1
SarifLog
⚠ 0 🛡 0 ↔ 1
UserArgs
⚠ 0 🛡 0 ↔ 3
FileSystem
⚠ 0 🛡 0 ↔ 3
SourceFiles
⚠ 0 🛡 0 ↔ 3
HTML
⚠ 0 🛡 0 ↔ 1
GitRef
⚠ 0 🛡 0 ↔ 2
TempDir
⚠ 0 🛡 0 ↔ 1
ProjectRoot
⚠ 0 🛡 0 ↔ 4
AgentFiles
⚠ 0 🛡 0 ↔ 2
MCPClient
⚠ 0 🛡 0 ↔ 3
QueryString
⚠ 0 🛡 0 ↔ 1
FilePath
⚠ 0 🛡 0 ↔ 2
Suggestions
⚠ 0 🛡 0 ↔ 1
Annotations
⚠ 0 🛡 0 ↔ 1
#report
⚠ 0 🛡 0 ↔ 2
Markdown
⚠ 0 🛡 0 ↔ 1
UserInput
⚠ 0 🛡 0 ↔ 1
Commands
⚠ 0 🛡 0 ↔ 1
RawStdin
⚠ 0 🛡 0 ↔ 1
Terminal
⚠ 0 🛡 0 ↔ 1
#workspace-link
⚠ 0 🛡 0 ↔ 2
ReportJSON
⚠ 0 🛡 0 ↔ 1
MergedReport
⚠ 0 🛡 0 ↔ 1
GitRepo
⚠ 0 🛡 0 ↔ 1
#report-metadata
⚠ 0 🛡 0 ↔ 2

Details