Back to skill

Security audit

Pilot S3 Bridge

Security checks for vulnerabilities and agentic risk

Overview

This skill documents a public cloud-storage bridge that could let remote callers use the installer’s cloud permissions without clear access controls.

Review before installing or using. Do not run the public bridge example as written on real cloud accounts. Use private networking, authenticated requesters, per-action and per-bucket authorization, least-privilege short-lived credentials, safe per-request temporary files, logging, and explicit approval for sensitive downloads or presigned URLs.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:71
Finding

Public Cloud Storage Bridge Lacks Requester Authentication and Authorization

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 71-99
Vulnerability Type: Missing authentication and authorization for privileged cloud operations
Risk Level: High

Vulnerable Code

bash
pilotctl --json daemon start --hostname s3-agent --public
pilotctl --json listen 1008

export AWS_ACCESS_KEY_ID="your_key"
export AWS_SECRET_ACCESS_KEY="your_secret"

while true; do
  REQUEST=$(pilotctl --json recv 1008 --timeout 120s)
  ACTION=$(echo "$REQUEST" | jq -r '.action')
  SENDER=$(echo "$REQUEST" | jq -r '.sender')
  BUCKET=$(echo "$REQUEST" | jq -r '.bucket')
  KEY=$(echo "$REQUEST" | jq -r '.key')

  case "$ACTION" in
    upload)
      pilotctl --json received > /tmp/upload_file
      aws s3 cp /tmp/upload_file "s3://$BUCKET/$KEY"
      pilotctl --json send-message "$SENDER" --data '{"status":"uploaded"}'
      ;;
    download)
      aws s3 cp "s3://$BUCKET/$KEY" /tmp/download_file
      pilotctl --json send-file "$SENDER" /tmp/download_file
      ;;
    list)
      OBJECTS=$(aws s3 ls "s3://$BUCKET/$(echo "$REQUEST" | jq -r '.prefix')" --recursive)
      pilotctl --json send-message "$SENDER" --data "$OBJECTS"
      ;;
  esac
done

Technical Analysis

The example starts the bridge with the --public option and processes messages received on the listener without performing an explicit authentication or authorization check. The requester controls the operation, bucket, object key, prefix, and response recipient through message fields.

Each accepted request is executed by the AWS CLI under the bridge process's AWS credentials. Consequently, the effective permissions available to a remote request are the permissions assigned to the bridge's AWS identity rather than permissions independently granted to the requester. There is no bucket or prefix allowlist, per-sender access policy, action-level authorization, or validation that the supplied sender is the authen ...[truncated 1653 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not expose the bridge with --public unless remote access is explicitly required and protected.
  • Require cryptographically authenticated requester identities before accepting any storage operation.
  • Bind the response recipient to the authenticated connection identity instead of trusting a requester-controlled sender field.
  • Implement authorization checks for every action, bucket, key, and prefix.
  • Maintain explicit allowlists of permitted buckets and prefixes; reject requests outside those boundaries.
  • Separate read, list, and write capabilities and grant each bridge deployment only the operations it requires.
  • Configure the cloud identity with least-privilege IAM policies, resource restrictions, and explicit deny rules for sensitive locations.
  • Validate the type, length, and permitted character set of all request fields before invoking cloud tools.
  • Add request identifiers, authenticated audit logs, rate limits, and alerts for denied or anomalous operations.
  • Prefer a private network listener, mutually authenticated transport, and short-lived cloud credentials.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:86
Finding

Predictable Shared Temporary Files Enable Local Data Exposure and File Manipulation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 86-92
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Medium

Vulnerable Code

bash
upload)
  pilotctl --json received > /tmp/upload_file
  aws s3 cp /tmp/upload_file "s3://$BUCKET/$KEY"
  pilotctl --json send-message "$SENDER" --data '{"status":"uploaded"}'
  ;;
download)
  aws s3 cp "s3://$BUCKET/$KEY" /tmp/download_file
  pilotctl --json send-file "$SENDER" /tmp/download_file
  ;;

Technical Analysis

The workflow uses the fixed paths /tmp/upload_file and /tmp/download_file in a shared temporary directory. It does not create a private working directory, generate unique names, enforce restrictive permissions, verify file ownership or type, reject symbolic links, or remove files after use.

Predictable names can cause requests to overwrite one another and allow a local attacker to pre-create or replace the referenced paths. Shell redirection to /tmp/upload_file may follow a pre-existing symbolic link, while the cloud CLI may interact with an attacker-controlled destination at /tmp/download_file. Reuse also leaves downloaded cloud data at a known location after transmission.

Concurrent requests can overwrite the same files, producing cross-request data corruption or causing one requester to receive content associated with another request.

Attack Path

  1. A local attacker with access to the shared temporary directory predicts the fixed filename used by the bridge.
  2. The attacker creates the target path or a symbolic link before the bridge handles a request, or monitors the known path while the operation is running.
  3. During upload processing, shell redirection writes received data through the attacker-prepared path; the bridge then uploads content from that path.
  4. During download processing, the AWS CLI writes cloud data to the predictable path, after which the bridge sends whatever content is presen ...[truncated 876 chars]
Remediation
View remediation

Remediation Suggestions

  • Create a private per-process or per-request directory using mktemp -d.
  • Set umask 077 before creating files so only the bridge account can access them.
  • Generate a unique temporary filename for every request rather than reusing global paths.
  • Install an EXIT, INT, and TERM trap to securely remove temporary files and directories.
  • Refuse symbolic links and verify that each path is a regular file owned by the bridge account before reading or sending it.
  • Avoid check-then-use sequences; create files atomically with exclusive creation semantics where possible.
  • Keep request-specific files isolated to prevent concurrent operations from overwriting one another.
  • Stream data directly between trusted processes where supported, eliminating persistent temporary files.
  • Run the bridge under a dedicated, unprivileged operating-system account with a private runtime directory.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (5)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises bridge-mediated access, but the presign action creates direct access URLs that bypass the bridge's control plane and any downstream monitoring or approval checks. If exposed to untrusted requesters, presigned URLs can be used to distribute object access outside the intended trust boundary until expiration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The example instructs users to export long-lived cloud credentials directly in the shell and implements a long-running service that uses them, without warnings about secret handling, credential rotation, role-based auth, or host hardening. This increases the risk of credential leakage through shell history, process inspection, logs, screenshots, or accidental reuse in insecure environments.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented workflow starts a public bridge agent and then processes arbitrary inbound requests to perform cloud actions using the agent's own credentials, with no authentication, authorization, requester allowlist, or operation scoping. In context, this effectively exposes a remotely reachable cloud proxy that can be abused by any party who can message the agent to list buckets, upload attacker-supplied content, or retrieve objects from cloud storage.

Content

No source excerpt is available for this finding.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The upload path copies received files into an S3 bucket selected from untrusted request data, allowing the bridge to write arbitrary content to cloud storage using its own credentials. In this skill's context, that is dangerous because the agent is intended as a remote bridge, so the operation can become an unauthorized exfiltration or staging channel if the requester is not strictly authorized.

Content

Scanner excerpt · SKILL.md (reported line 91)May include surrounding context.

md
case "$ACTION" in
    upload)
      pilotctl --json received > /tmp/upload_file
      aws s3 cp /tmp/upload_file "s3://$BUCKET/$KEY"
      pilotctl --json send-message "$SENDER" --data '{"status":"uploaded"}'
      ;;
    download)

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The download path retrieves arbitrary objects from cloud storage based on requester-controlled bucket/key values and sends them back to the requester, with no access control or content restrictions. In context, this exposes the bridge as a data exfiltration service for any cloud object the agent credentials can read.

Content

Scanner excerpt · SKILL.md (reported line 95)May include surrounding context.

md
pilotctl --json send-message "$SENDER" --data '{"status":"uploaded"}'
      ;;
    download)
      aws s3 cp "s3://$BUCKET/$KEY" /tmp/download_file
      pilotctl --json send-file "$SENDER" /tmp/download_file
      ;;
    list)

Static analysis

No suspicious patterns detected.