T09 · Insecure Skill Coding Practices
- Location
SKILL.md:58- Finding
Regex Injection in Peer Trust Evaluation
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 58-66
Vulnerability Type: Improper validation of attacker-influenced peer identifiers
Risk Level: MediumVulnerable Code
bash candidates=$(pilotctl --json peers --search "$requirements" | jq -r '.peers[].node_id') trusted=$(pilotctl --json trust | jq -r '.trusted[].node_id') for node_id in $candidates; do # Get metrics polo=$(pilotctl --json lookup "$node_id" | jq -r '.polo_score // 0') latency=$(pilotctl --json ping "$node_id" 2>/dev/null | jq -r '.avg_rtt_ms // 999') is_trusted=$(echo "$trusted" | grep -q "$node_id" && echo 1 || echo 0)Technical Analysis
Candidate node IDs originate from peer-discovery output and may therefore be influenced by remote peers. The workflow passes each node ID directly to
grepas a regular-expression pattern:bash grep -q "$node_id"Shell quoting prevents word expansion at this call site, but it does not make the pattern literal. Metacharacters such as
.*,^,$, or character classes retain their regular-expression meaning. A node ID beginning with-can also be interpreted as agrepoption because the command does not use--.Consequently, a crafted candidate ID can match an unrelated entry in the trusted-node list. The workflow would then assign the candidate a 30-point trust bonus even though its exact identifier is absent from that list.
The loop also uses
for node_id in $candidates, which applies shell whitespace splitting to values extracted from JSON rather than preserving each identifier as an exact array element.Attack Path
- An attacker advertises a peer whose node ID is a matching regular expression, such as
.*, assuming the protocol permits such characters or fails to validate identifiers upstream. pilotctl --json peers --searchreturns the attacker-controlled identifier as a candidate.- The unquoted array-style loop processes the extracted text using shell word splittin ...[truncated 1043 chars]
- An attacker advertises a peer whose node ID is a matching regular expression, such as
- Remediation
View remediation
Remediation Suggestions
Use exact, literal, whole-line matching, terminate command options explicitly, and preserve JSON values as shell array elements:
bash mapfile -t candidates < <( pilotctl --json peers --search "$requirements" | jq -r '.peers[].node_id' ) mapfile -t trusted < <( pilotctl --json trust | jq -r '.trusted[].node_id' ) for node_id in "${candidates[@]}"; do if printf '%s\n' "${trusted[@]}" | grep -Fqx -- "$node_id"; then is_trusted=1 else is_trusted=0 fi # Continue scoring with the validated identifier. doneFor stronger hardening:
- Compare candidate and trusted identifiers directly in
jqrather than converting structured JSON into shell-delimited text. - Validate every node ID against the protocol's canonical identifier format before using it in commands.
- Reject empty, malformed, option-like, or noncanonical identifiers.
- Treat trust as an exact identity assertion rather than a substring or pattern match.
- Fail closed when trust output is malformed or unavailable.
- Add regression tests covering regex metacharacters, leading hyphens, whitespace, empty identifiers, and identifiers that are prefixes of trusted IDs.
- Compare candidate and trusted identifiers directly in
