Back to skill

Security audit

Pilot Map Reduce

Security checks for vulnerabilities and agentic risk

Overview

This skill is a transparent map-reduce recipe for pilot-protocol swarms, with notable data-handling and robustness cautions but no hidden or purpose-incompatible behavior.

Install only if you already trust the pilot-protocol peers and daemon environment. Avoid sending confidential or regulated data unless the peer identities, message access controls, and result handling are appropriate; harden the examples before production use by validating senders and job IDs, encoding JSON safely, adding timeouts, and using private temporary storage.

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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:95
Finding

Unauthenticated Distributed Results Can Poison Map-Reduce Aggregation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 95–99
Vulnerability Type: Untrusted message processing and insufficient result validation
Risk Level: Medium

Vulnerable Code

bash
MAP_RESULTS=$(pilotctl --json received \
  | jq '[.messages[] | select(.payload.type == "map_result")]')

FINAL=$(echo "$MAP_RESULTS" | jq 'map({(.payload.word): .payload.count}) | add')
echo "$FINAL"

Technical Analysis

The workflow accepts every received message whose self-declared payload type is map_result. It does not verify the current job_id, authenticate the sender, confirm that the sender belongs to the assigned mapper set, reject duplicate submissions, or validate the payload schema and size.

Because the message type is controlled by the sender, an unauthorized or compromised peer can submit a forged result that passes the filter. The forged word and count fields are then incorporated directly into the final aggregation. Duplicate keys may also overwrite or otherwise interfere with legitimate results according to the aggregation behavior.

Attack Path

  1. An attacker gains the ability to send messages to the receiving agent, such as through a malicious, compromised, or unauthorized peer.
  2. The attacker sends a message with .payload.type set to map_result.
  3. The attacker supplies arbitrary .payload.word and .payload.count values.
  4. The type-only jq filter accepts the forged message.
  5. The forged values are included in FINAL, poisoning the output. An oversized payload could additionally consume excessive memory or processing time.

Impact Assessment

The attacker does not obtain additional operating-system privileges from this flaw. However, within the distributed job's scope, the attacker can corrupt computed results, introduce cross-job data, cause legitimate values to be replaced or misrepresented, and potentially trigger resource exhaustion with excessively large ...[truncated 26 chars]

Remediation
View remediation

Remediation Suggestions

  • Filter every result by the exact current job identifier.
  • Authenticate messages and allow only addresses assigned to the current job.
  • Maintain an expected-worker set and accept at most one valid result from each worker.
  • Validate payload fields against a strict schema, including types, permitted key formats, numeric ranges, and maximum message sizes.
  • Reject malformed, duplicate, unauthorized, stale, and cross-job messages.
  • Apply bounded input and aggregation limits to prevent memory and CPU exhaustion.
  • Prefer protocol-level message authentication or signatures where supported.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:40
Finding

Unsafe Runtime-Value Interpolation into JSON and jq Programs

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 40–42, 55–57, and 66–70
Vulnerability Type: JSON and jq expression injection
Risk Level: Medium

Vulnerable Code

bash
pilotctl --json send-message "$WORKER" \
  --data "{\"type\":\"map_task\",\"job_id\":\"$JOB_ID\",\"chunk_start\":$((i * 1000)),\"chunk_end\":$(((i + 1) * 1000))}"
bash
RESULTS=$(pilotctl --json received \
  | jq '[.messages[] | select(.payload.type == "map_result" and .payload.job_id == "'$JOB_ID'")] | length')
bash
MAP_RESULTS=$(cat /tmp/map-results-$JOB_ID.json)
KEYS=$(echo "$MAP_RESULTS" | jq -r '.[].payload.results | to_entries | .[].key' | sort -u)

for key in $KEYS; do
  VALUES=$(echo "$MAP_RESULTS" | jq -r '[.[].payload.results."'$key'" // empty] | flatten')

  pilotctl --json send-message "$REDUCER" \
    --data "{\"type\":\"reduce_task\",\"job_id\":\"$JOB_ID\",\"key\":\"$key\",\"values\":$VALUES}"
done

Technical Analysis

Runtime values are concatenated directly into JSON documents and jq source code instead of being passed as data through safe encoding mechanisms. A job identifier containing quotes, backslashes, or jq syntax can terminate the intended string and modify the filter. Likewise, mapper-controlled result keys are inserted into a jq property expression and later into outbound JSON.

This creates JSON-structure and jq-expression injection risks. The shown code does not directly demonstrate shell-command execution because the values are expanded inside quoted shell arguments, but crafted values can alter message fields, change filter semantics, break processing, or manipulate reducer input. The unquoted for key in $KEYS loop also applies shell word splitting and pathname expansion, so keys containing whitespace or wildcard characters may be transformed before processing.

Attack Path

  1. An attacker influences JOB_ID or causes a mapper to return a crafted result key.

...[truncated 872 chars]

Remediation
View remediation

Remediation Suggestions

  • Construct outbound JSON with jq -n, using --arg for strings and --argjson for validated JSON values.
  • Pass the job identifier to jq through --arg job_id "$JOB_ID" and compare against $job_id inside a static jq program.
  • Pass dynamic keys through --arg key "$key" and access properties as .payload.results[$key].
  • Validate job identifiers and result keys against strict length and character constraints.
  • Avoid for key in $KEYS; read records safely with a newline- or NUL-delimited loop and disable pathname expansion where appropriate.
  • Validate that VALUES is valid JSON of the expected type before adding it to an outbound message.
  • Treat all peer-supplied keys and result values as untrusted data.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:63
Finding

Predictable and Unquoted Temporary Result Path

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 63
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Low

Vulnerable Code

bash
MAP_RESULTS=$(cat /tmp/map-results-$JOB_ID.json)

Technical Analysis

The result file uses a predictable name in the shared /tmp directory and incorporates JOB_ID without validation or shell quoting. In a multi-user environment, another local user may be able to create the expected path or a symbolic link before it is read. The unquoted expansion also permits shell word splitting and pathname expansion when the job identifier contains whitespace or wildcard characters.

Although this line only reads the path, an attacker can substitute arbitrary content for the expected map results or redirect the read to another file accessible to the process.

Attack Path

  1. An attacker predicts or learns the job identifier.
  2. Before the workflow reads the result path, the attacker creates /tmp/map-results-<JOB_ID>.json or a symbolic link with that name.
  3. The workflow executes cat against the attacker-prepared path.
  4. Attacker-selected content is assigned to MAP_RESULTS.
  5. The poisoned content is parsed and may be forwarded to reducers, or malformed content causes job failure.

Impact Assessment

A local attacker can compromise the integrity of map results and cause denial of service. If a symbolic link targets another file readable by the agent, its contents may be ingested into the workflow and potentially disclosed to a reducer or peer. The flaw does not independently grant access to files that the executing process lacks permission to read.

Remediation
View remediation

Remediation Suggestions

  • Create a private working directory with mktemp -d and restrictive permissions.
  • Store all job files beneath that private directory rather than directly under shared /tmp.
  • Quote every path expansion, for example cat "$workdir/map-results.json".
  • Validate job identifiers and never use untrusted identifiers directly as path components.
  • Reject symbolic links and verify file ownership and type before reading where local adversaries are in scope.
  • Register a cleanup trap to remove the private directory after success, failure, or interruption.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:53
Finding

Unbounded Result-Collection Loop Allows Indefinite Denial of Service

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 53–60
Vulnerability Type: Missing timeout and distributed-worker failure handling
Risk Level: Low

Vulnerable Code

bash
EXPECTED_RESULTS=$TOTAL_WORKERS
RECEIVED=0

while [ $RECEIVED -lt $EXPECTED_RESULTS ]; do
  RESULTS=$(pilotctl --json received \
    | jq '[.messages[] | select(.payload.type == "map_result" and .payload.job_id == "'$JOB_ID'")] | length')
  RECEIVED=$RESULTS
  sleep 1
done

Technical Analysis

The collection loop has no deadline, retry limit, cancellation path, worker-health check, or partial-failure policy. It terminates only when the counted number of matching messages reaches the original worker count.

A failed or malicious worker can therefore prevent completion by withholding its response. Network partitions, peer removal, malformed results, or inaccurate worker counts produce the same behavior. Polling the complete received-message collection every second may also create increasing resource usage as the inbox grows.

Attack Path

  1. A worker is assigned a map task.
  2. The worker fails, disconnects, or intentionally withholds its result.
  3. RECEIVED remains below EXPECTED_RESULTS.
  4. The loop continues polling once per second without a termination condition.
  5. The job remains occupied indefinitely and repeatedly consumes local and daemon resources.

Impact Assessment

Exploitation affects availability rather than privileges. A malicious or unavailable worker can indefinitely block job completion, consume agent execution time, and repeatedly invoke pilotctl and jq. Multiple stalled jobs could amplify resource consumption and reduce service capacity.

Remediation
View remediation

Remediation Suggestions

  • Add a configurable absolute deadline and bounded retry count.
  • Track expected workers individually instead of relying only on a message count.
  • Detect disconnected or unhealthy workers and support reassignment or explicit partial failure.
  • Add cancellation and interrupt handling.
  • Apply exponential backoff or event-driven receipt handling instead of polling the entire inbox every second.
  • Return a clear failure state when the required result threshold is not reached within the deadline.
  • Bound the number and size of messages inspected during each polling cycle.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill demonstrates sending structured job data to peer workers across a distributed swarm without any warning, trust-boundary discussion, or guidance on data sensitivity. In this context, users may transmit proprietary or regulated data to remote peers they do not control, creating confidentiality and data-governance risk even if the transport works as intended.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The example is presented as a distributed MAP phase over multiple workers, but MAPPERS=$(...) stores newline-delimited text, while ${MAPPERS[$i]} is array-style indexing that does not work as implied in POSIX shell/bash for this assignment form. This means the documented example does not actually implement the worker-by-worker dispatch pattern it describes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The collection and aggregation examples read from shared message/state sources and process results without warning that those sources may contain sensitive job outputs from distributed workers. In a multi-peer or shared daemon environment, this can expose processed data or metadata to unintended readers and encourages unsafe handling of aggregated results.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.