Back to skill

Security audit

Perry Coding Agents

Security checks for vulnerabilities and agentic risk

Overview

This skill is for delegating coding work to remote agents, but it gives broad remote-execution guidance with weak scoping and unsafe credential and SSH patterns.

Review this skill carefully before installing. Use it only for trusted Perry workspaces and trusted task text, avoid copying untrusted issue or PR content into the shell templates, do not use long-lived bearer tokens in prompts or command lines, prefer strict SSH host-key validation, and reset or isolate remote agent sessions between unrelated tasks.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:20
Finding

SSH Host-Key Verification Is Disabled

Content
View full analysis
"cd ~/ && /home/workspace/.opencode/bin/opencode run 'task'" & ``` The same insecure option also appears in the dispatch pattern and full PR workflow: ```bash ssh -o StrictHostKeyChecking=no workspace@ "cd ~/ && /home/workspace/.opencode/bin/opencode run 'Your task. ``` ### Technical Analysis The documented SSH commands explicitly set `StrictHostKeyChecking=no`. This suppresses normal SSH host-key validation and automatically accepts an unknown host key. As a result, possessing or redirecting traffic associated with a workspace IP is treated as sufficient proof of the remote server's identity. Tailscale provides encrypted network transport and device identity controls, but disabling SSH host-key verification still removes an independent endpoint-authentication layer. If an address is stale, incorrectly selected, reassigned, or traffic is otherwise redirected to an unintended system, the workflow can send its remote command and sensitive task content to that system without detecting a host-key mismatch. ### Attack Path 1. An attacker gains control of, or causes the operator to select, an unintended endpoint reachable at the supplied workspace IP. 2. The operator runs the documented command with `StrictHostKeyChecking=no`. 3. SSH accepts the attacker's previously unknown host key without requiring verification. 4. The remote task command and its contents are sent to the attacker-controlled endpoint. 5. Where the task embeds a wake-hook bearer token, the attacker can capture that credential as well. 6. The endpoint can return deceptive command output or execute the requested coding-agent workload in a ...[truncated 507 chars]
Remediation
View remediation
... ``` - Validate that the selected Tailscale IP and device identity correspond to the intended workspace before connecting. - Establish a controlled host-key rotation process rather than bypassing verification when a key changes. - Treat unexpected host-key changes as security events and investigate them before continuing. - Avoid transmitting callback credentials until the remote endpoint has been strongly authenticated. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:18
Finding

Unescaped Task and Project Values Permit Remote Shell Command Injection

Content
View full analysis
"cd ~/ && /home/workspace/.opencode/bin/opencode run 'task'" & # Claude Code (needs TTY) ssh -t workspace@ "cd ~/ && /home/workspace/.local/bin/claude 'task'" ``` The expanded dispatch pattern likewise embeds task content inside a single-quoted argument nested within a double-quoted remote command: ```bash ssh -o StrictHostKeyChecking=no workspace@ "cd ~/ && /home/workspace/.opencode/bin/opencode run 'Your task. When done: curl -X POST http://${WAKE_IP}:18789/hooks/wake -H \"Content-Type: application/json\" -H \"Authorization: Bearer \" -d \"{\\\"text\\\": \\\"Done: summary\\\", \\\"mode\\\": \\\"now\\\"}\" '" & ``` ### Technical Analysis The templates construct an SSH remote command by directly interpolating the project path and task text into shell syntax. The task is surrounded by single quotes, but no escaping or argument-boundary enforcement is specified. A task containing a single quote can terminate that quoted argument. Shell operators following the quote can then be interpreted by the remote shell rather than passed as data to OpenCode or Claude Code. The project placeholder is also embedded directly after `cd ~/` without validation or shell-safe quoting. A value containing whitespace, command substitution, separators, redirection, or other shell metacharacters can modify the remote command. There are multiple parsing layers: the initiating shell processes the outer command, SSH transfers a command string, and the remote login shell parses that string again. Manual nested quoting is therefore fragile, and accepting task text from i ...[truncated 1742 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:27
Finding

Wake-Hook Bearer Token Is Exposed in Remote Prompt and Command-Line Material

Content
View full analysis
"cd ~/ && /home/workspace/.opencode/bin/opencode run 'Your task. When done: curl -X POST http://${WAKE_IP}:18789/hooks/wake -H \"Content-Type: application/json\" -H \"Authorization: Bearer \" -d \"{\\\"text\\\": \\\"Done: summary\\\", \\\"mode\\\": \\\"now\\\"}\" '" & ``` The full PR example repeats the same pattern: ```bash When finished: curl -X POST http://${WAKE_IP}:18789/hooks/wake -H \"Content-Type: application/json\" -H \"Authorization: Bearer \" -d \"{\\\"text\\\": \\\"Done: Auth PR created\\\", \\\"mode\\\": \\\"now\\\"}\" ``` ### Technical Analysis The workflow embeds a bearer token directly into the natural-language prompt sent to a remote coding agent. The token consequently becomes visible to the delegated agent and may also appear in process arguments, task transcripts, debugging output, audit logs, shell history, terminal capture, or agent context retained under `~/.opencode/`. Bearer credentials generally grant access based solely on possession. Any remote process or user capable of reading the prompt or associated process data may therefore be able to replay the token. The example uses HTTP for the callback. Although the shown endpoint is a Tailscale IP and the overlay normally encrypts network transport, application-layer TLS is not used, and endpoint authentication depends on surrounding network controls. ### Attack Path 1. A real hook token is substituted for the placeholder in the dispatch command. 2. The complete token is sent to the remote coding agent as part of its prompt and may be exposed in command-line or agent-session records. 3. A malicious or compromised de ...[truncated 892 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description says to use the skill for "development work, PR reviews, or any coding task," which is extremely broad and overlaps with many ordinary coding requests. It does not define clear activation boundaries or exclusions, making unintended invocation more likely.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill explicitly encourages long-running background jobs and session reuse ('same session continues until done', 'OpenCode keeps context'), which increases the chance that sensitive context, prior prompts, secrets, or unintended instructions persist across tasks. In combination with remote dispatch, persistent agent state can amplify mistakes and make subsequent actions less auditable or predictable.

Content

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

md
Dispatch tasks to OpenCode/Claude Code on Perry workspaces.

## Rules
- **Always create dex task FIRST** — before any dispatch, no exceptions
- **No hard timeouts** — background dispatch, let agent run
- **Use IPs** — MagicDNS broken in containers (`tailscale status` for IPs)
- **One task per PR** — same session continues until done

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs the remote agent to send an HTTP callback with a bearer token and task status, but it does not provide a clear user-facing warning that data will be transmitted over the network. In a prompt-driven skill, hidden or implicit exfiltration paths are dangerous because task details, completion summaries, and credentials may be sent off-host without explicit consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This command causes the remote workspace to issue an outbound HTTP POST containing a bearer token and status text to a callback endpoint. That creates a concrete exfiltration mechanism and additionally uses plain HTTP, exposing the token and payload to interception or misuse on the network path.

Content

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

ssh -o StrictHostKeyChecking=no workspace@ "cd ~/ && /home/workspace/.opencode/bin/opencode run 'Your task.

When done: curl -X POST http://${WAKE_IP}:18789/hooks/wake -H "Content-Type: application/json" -H "Authorization: Bearer " -d "{\"text\": \"Done: summary\", \"mode\": \"now\"}" '" &

text

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This example repeats the same risky pattern: a remote agent is instructed to POST completion data with an authorization bearer token to an external endpoint. Because the callback is embedded in the dispatched task text, it normalizes remote-controlled data transmission and may leak workflow details or reusable credentials.

Content

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

md
# 3. Dispatch (background, no timeout)
ssh -o StrictHostKeyChecking=no workspace@100.109.173.45 "cd ~/perry && /home/workspace/.opencode/bin/opencode run 'Add bearer token auth to all API endpoints. Create PR when done.

When finished: curl -X POST http://${WAKE_IP}:18789/hooks/wake -H \"Content-Type: application/json\" -H \"Authorization: Bearer <token>\" -d \"{\\\"text\\\": \\\"Done: Auth PR created\\\", \\\"mode\\\": \\\"now\\\"}\"
'" &

# 4. Wake received → check CI

Static analysis

No suspicious patterns detected.