Back to skill

Security audit

Knowledge Graph - Multi Hop Reasoning Query Builder

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed graph-query helper, but users should review generated Cypher/SPARQL before running it on real databases.

Install only if you want graph-query templates and helper scripts. Treat all generated Cypher/SPARQL and index statements as drafts: validate labels, relationship types, property names, hop counts, and limits against a trusted schema; use EXPLAIN/PROFILE or staging data first; and avoid sensitive examples such as healthcare or finance unless you have proper authorization and privacy controls.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/multi_hop_query_builder.py:116
Finding

Graph Query Injection Through Unvalidated Structural Parameters

Content
View full analysis
(target{target_part}) RETURN DISTINCT target LIMIT {limit}""" ``` ```python path = f"ex:{relationship_type}" * num_hops query = f"""PREFIX ex: SELECT ?target WHERE {{ ex:{start_id_value} {path} ?target . }} LIMIT {limit}""" ``` ```python target_part = f":{target_label}" if target_label else "" query = f"""MATCH (start:{start_label})-[:{relationship_type}*{min_hops}..{max_hops}]->(target{target_part}) RETURN DISTINCT target LIMIT {limit}""" ``` ```python query = f"""PREFIX ex: SELECT ?target WHERE {{ ?start a ex:{start_label} ; ex:{relationship_type}+ ?target . }} LIMIT {limit}""" ``` ### Technical Analysis Query parameters can normally protect data values, but graph labels, relationship types, property names, SPARQL resource names, and query-language clauses generally cannot be safely treated as ordinary value parameters. These structural components require strict validation against the application schema. The following arguments are embedded directly into query syntax: - `start_ ...[truncated 2588 chars]
Remediation
View remediation
str: if not isinstance(value, str) or not IDENTIFIER.fullmatch(value): raise ValueError("Invalid graph identifier") return value ``` 2. Prefer explicit allowlists derived from the known graph schema: ```python ALLOWED_LABELS = {"Person", "Company", "Product"} ALLOWED_RELATIONSHIPS = {"FOLLOWS", "SUPPLIES", "PURCHASED"} ALLOWED_PROPERTIES = {"id", "name", "username"} ``` 3. Enforce runtime integer validation for all traversal and limit parameters. Reject booleans, negative values, zero where inappropriate, and oversized values: ```python def validate_positive_int(value, *, minimum=1, maximum=100): if isinstance(value, bool) or not isinstance(value, int): raise TypeError("Expected an integer") if not minimum <= value <= maximum: raise ValueError("Integer is outside the permitted range") return value ``` 4. Apply the safe-depth restriction consistently to fixed-depth, variable-depth, and path-discovery methods. 5. Parameterize every data value supported by the target database driver. Do not confuse value parameterization with identifier safety. 6. If the database supports identifier quoting, use the official driver or query-builder mechanism only after validation. Quoting alone should not replace schema allowlisting. 7. Treat generated statements as untrusted until validated. Document that callers must not directly execute queries created from arbitrary external input. 8. Add tests covering quotes, backticks, braces, parentheses, semicolons, comments, whitespace, newlines, clause keywords, booleans, negative depths, very large depths, and malformed limits. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/path_reasoner.py:283
Finding

Cypher DDL Injection Through Unvalidated Index Identifiers

Content
View full analysis
List[str]: """Recommend indexes for path traversal.""" indexes = [] # Index starting node if path.nodes: start_label = path.nodes[0].label indexes.append(f"CREATE INDEX ON :{start_label}(id)") # Index relationship types for edge in path.edges: indexes.append(f"CREATE RELATIONSHIP_INDEX ON :({edge.relationship_type})") # Index ending node for common filters if path.nodes and len(path.nodes) > 1: end_label = path.nodes[-1].label indexes.append(f"CREATE INDEX ON :{end_label}(active)") return indexes ``` ### Technical Analysis `PathNode.label` and `PathEdge.relationship_type` are unrestricted strings. `recommend_indexes()` embeds these values into administrative query text without validation or safe identifier handling. Because these are structural database identifiers, ordinary value parameters generally cannot secure them. A malicious label or relationship type may terminate the intended identifier context and append additional database syntax, depending on the target Cypher dialect. The function only returns strings and does not execute them. The vulnerability becomes exploitable when a consuming tool automatically applies the recommended index statements or presents them to an administrator as trusted output. ### Attack Path 1. An attacker controls or influences a `GraphPath`, including a node label or relationship type. 2. The attacker places database syntax, delimiters, or comments in the controlled identifier. 3. The application calls `recommend_indexes()`. 4. The function embeds the malicious identifier into ...[truncated 886 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description emphasizes query generation for multi-hop traversal and reasoning. The actual code is a path analysis/reasoning helper: it validates path structure, detects cycles, estimates complexity/cost/cardinality, provides optimization suggestions and warnings, explains paths in human-readable form, and recommends indexes. While this is related to graph traversal reasoning, the main advertised capability—generating graph queries—is absent. The included shortest-path function is only a stub returning a template GraphPath, not a real graph query. Therefore the declared description does not accurately represent the code's primary behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill encourages generation of potentially expensive multi-hop and variable-length graph traversals, including patterns like unbounded shortestPath and broad path expansion, but its summary/output framing lacks a prominent operational warning against running such queries on production datasets without review. In this context, users may over-trust generated queries and execute them directly, causing denial-of-service style performance degradation, timeouts, or heavy resource consumption on graph infrastructure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The healthcare example exposes a graph query pattern that returns patient identifiers, last known location, diagnosis-linked contact chains, and exposure distance without any privacy notice, minimization guidance, or access-control context. In a skill that teaches reusable query construction, this can normalize unsafe handling of protected health information and enable users to build high-sensitivity surveillance queries directly against patient datasets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Cypher queries are assembled with f-strings that interpolate labels and relationship types directly into the query text. Because schema identifiers are not parameterizable in Cypher, untrusted input here can lead to query injection or malformed queries unless the values are strictly allowlisted and validated against safe identifier patterns.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The SPARQL builder inserts user-controlled identifiers such as start_id_value and relationship_type directly into query text, including IRI/prefixed-name positions. In this skill's context, that makes injection particularly dangerous because the tool is expressly designed to generate executable graph queries, so unsafe interpolation can alter query semantics, access unintended data, or trigger expensive traversal behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The SPARQL variable-hop builder accepts min_hops and max_hops but emits an unbounded property path using '+', which means one-or-more hops with no upper bound. In a query-building skill, this can cause unexpectedly expansive traversals, denial-of-service style load, and results that violate caller assumptions about bounded search depth.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The section says it provides a relationship-property filtering pattern, but the Cypher shown binds only relationship variable 'r' while the predicate iterates over relationships(path). Because 'path' is never defined, the example does not actually implement the documented behavior and would not work as written.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documented intent is to filter nodes encountered along a multi-hop path. However, the query never defines a path variable and uses 'nodes(target)', which is inconsistent with Cypher's path-node semantics and does not evaluate the intermediate path nodes as described.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.