Back to skill

Security audit

Perfect Agent Comms

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate bridge purpose, but it needs review because it enables autonomous cross-agent HTTP messaging, workspace access, persistent polling, and several unsafe deployment patterns.

Install only for agents and bridge hosts you fully control. Keep the bridge local, tunneled, or behind TLS; avoid the public-port option; protect and rotate the shared token; restrict what files/tools the polling agent may read; review bridge messages before writing them into persistent memory; and fix or avoid the eval monitoring snippet and unsafe timestamp helper before unattended use.

Vulnerability Patterns
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (8)

T01 · Skill Instruction Hijacking

Error
Location
references/cron-templates.md:14
Finding

Bridge Messages Can Trigger Excessive Workspace and Tool Access

Content
View full analysis

Vulnerability Details

File Location: references/cron-templates.md:14
Vulnerability Type: Remote instruction handling without least-privilege restrictions
Risk Level: High

Code Snippet:

json
"message": "BRIDGE INBOX CHECK — You are [AGENT_NAME]. Respond to [OTHER_AGENT] messages.\n\nStep 1: Read last-poll timestamp\nRun: cat /tmp/acp_bridge_last_ts 2>/dev/null || echo 0\n\nStep 2: Fetch new messages from the bridge\nRun: curl -s \"http://[BRIDGE_HOST]:18790/api/inbox?after=$(cat /tmp/acp_bridge_last_ts 2>/dev/null || echo 0)\" -H 'Authorization: Bearer [TOKEN]'\n\nIf count == 0: reply NO_REPLY. Done.\n\nStep 3: Read your workspace context files before replying\nRead: SESSION-STATE.md, SOUL.md, and today's memory file from your workspace.\n\nStep 4: For each new message, compose a substantive reply\n- You ARE [AGENT_NAME]. Respond directly with data, analysis, or results.\n- If a message requests information you can look up in your workspace files or via your configured tools, do so and include the results.\n- Skip stale 'Follow-up: These tasks have been pending' messages.\n- Include numbers and deliverables, not narratives and promises.\n\nStep 5: Send reply using the bridge_reply helper\nRun: python3 [WORKSPACE]/bridge_reply.py \"<your reply>\"\n\nStep 6: Save latest timestamp. Use the 'ts' field (float seconds), NOT the 'id' field.\nRun: bash [WORKSPACE]/save_bridge_ts.sh <latest_msg_ts_float>\n\nStep 7: If the other agent assigned tasks needing the owner's attention, alert them via the message tool."

Technical Analysis

The cron template treats messages obtained from the bridge as actionable agent instructions. It expressly authorizes the agent to read SESSION-STATE.md, SOUL.md, daily memory, other workspace files, and data accessible through configured tools.

Authentication establishes possession of a shared token, but it does not make every message safe to execute. There is no operation a ...[truncated 1213 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat all bridge message text as untrusted data, not as agent instructions.
  • Define a narrow allowlist of permitted bridge operations and readable resources.
  • Prohibit remote requests from accessing secrets, credentials, identity files, memory files, or unrelated workspace content.
  • Require explicit owner approval before executing tools, modifying files, sending external messages, or returning potentially sensitive information.
  • Use structured, schema-validated requests instead of unrestricted natural-language task execution.
  • Apply output filtering and data-loss-prevention checks before sending replies.
  • Use separate credentials and authorization scopes for inbox reading, replying, sending, receiving, and administration.

T02 · Agent Memory Poisoning

Error
Location
references/cron-templates.md:47
Finding

Untrusted Bridge Content Can Poison Persistent Agent State

Content
View full analysis

Vulnerability Details

File Location: references/cron-templates.md:47; references/gotchas.md:96-106
Vulnerability Type: Persistent ingestion of attacker-influenced content
Risk Level: High

Code Snippet:

json
"message": "BRIDGE CHECK — You are [AGENT_A_NAME].\n\nStep 1: Read last-recv timestamp\nRun: cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0\n\nStep 2: Poll for replies from [AGENT_B]\nRun: curl -s \"http://[BRIDGE_HOST]:18790/api/recv?after=$(cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0)\" -H 'Authorization: Bearer [TOKEN]'\n\nIf count == 0: reply NO_REPLY. Done.\n\nStep 3: Process each reply. Update your workspace context files with new information."
markdown
**Fix**: WAL (Write-Ahead Log) protocol:
1. Create a `SESSION-STATE.md` file in the workspace (acts as "hot RAM")
2. Cron prompt instructs the agent to read SESSION-STATE.md FIRST
3. Before responding, agent writes current state to SESSION-STATE.md
4. Next cycle reads it and picks up where it left off

**Key rule**: Write state BEFORE responding, not after.

Technical Analysis

The documentation directs agents to write information derived from bridge messages into workspace context and to load SESSION-STATE.md at the beginning of later polling cycles. The remote content is not isolated, marked as untrusted, validated, or subject to expiration.

This creates a persistent trust-boundary violation: attacker-influenced text can be promoted into state that affects future isolated sessions. Even after the original message is no longer being processed, poisoned state may continue to influence agent behavior.

Attack Path

  1. An attacker controls a bridge peer or obtains the shared token.
  2. The attacker sends a reply containing false operational facts, persistent behavioral instructions, or adversarial prompt content.
  3. The receiving cron processes the reply and updates workspace context files.

...[truncated 597 chars]

Remediation
View remediation

Remediation Suggestions

  • Store bridge messages in a dedicated untrusted queue, separate from agent identity, instructions, and trusted memory.
  • Do not write natural-language remote content directly into SESSION-STATE.md, SOUL.md, or equivalent context files.
  • Record provenance, sender identity, receipt time, and trust level for imported information.
  • Validate messages against a strict schema and only persist specific data fields.
  • Require human approval before promoting remote claims or instructions into trusted long-term state.
  • Apply expiration and rollback mechanisms to imported state.
  • Ensure persistent files clearly delimit quoted remote content so it cannot be interpreted as trusted instructions.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/acp_bridge.py:132
Finding

Bearer Tokens and Agent Messages May Be Transmitted Over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/acp_bridge.py:132-134; scripts/bridge_reply.py:14-31; SKILL.md:48-49
Vulnerability Type: Unencrypted transmission of authentication credentials and message data
Risk Level: High

Code Snippet:

python
if __name__ == "__main__":
    port = int(os.environ.get("ACP_BRIDGE_PORT", "18790"))
    server = HTTPServer(("0.0.0.0", port), BridgeHandler)
    print(f"ACP Bridge listening on :{port}", flush=True)
    server.serve_forever()
python
BRIDGE_URL = os.environ.get(
    "BRIDGE_URL",
    "http://localhost:18790/api/reply"
)

req = urllib.request.Request(
    BRIDGE_URL,
    data=payload,
    headers={
        "Authorization": f"Bearer {BRIDGE_TOKEN}",
        "Content-Type": "application/json",
    },
    method="POST",
)
markdown
| Cross-internet (simple) | Open port 18790, use public IP. Token is your auth. |
| Cross-internet (secure) | SSH tunnel: `ssh -L 18790:localhost:18790 user@bridge-host -N` |

Technical Analysis

The bridge server listens on all interfaces and does not provide TLS. The helper accepts plaintext HTTP URLs, and the documentation presents opening the port on a public IP as a supported topology. The bearer token and complete message payload are therefore exposed to passive observation or active interception whenever traffic traverses an untrusted network.

A bearer token provides access based solely on possession. Anyone who captures it can impersonate a peer and use every endpoint because the implementation does not define separate read, write, or administrative scopes.

Attack Path

  1. An operator exposes port 18790 over a LAN or the public internet using HTTP.
  2. An attacker with network visibility captures an Authorization: Bearer ... header.
  3. The attacker reuses the token to call /api/inbox and /api/recv.
  4. The attacker reads relayed messages or submits malic ...[truncated 478 chars]
Remediation
View remediation

Remediation Suggestions

  • Bind to 127.0.0.1 by default and require an explicit opt-in for non-loopback binding.
  • Require TLS for every non-loopback connection, preferably through a correctly configured reverse proxy or mutually authenticated TLS.
  • Reject remote plaintext http:// bridge URLs in helper scripts.
  • Remove the recommendation to expose the HTTP port directly to the internet.
  • Do not place literal tokens in cron prompt text or command lines; load them from protected secret storage.
  • Use separate, revocable credentials with endpoint-specific scopes for each agent and direction.
  • Rotate tokens regularly and immediately after suspected exposure.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/acp_bridge.py:24
Finding

Bridge Message Storage Relies on Ambient Umask in a Shared Temporary Directory

Content
View full analysis

Vulnerability Details

File Location: scripts/acp_bridge.py:24-35
Vulnerability Type: Insecure local storage permissions and unsafe temporary path
Risk Level: Medium

Code Snippet:

python
BRIDGE_DIR = Path(os.environ.get("ACP_BRIDGE_DIR", "/tmp/acp_bridge"))
BRIDGE_DIR.mkdir(exist_ok=True)
INBOX = BRIDGE_DIR / "inbox.jsonl"    # A → B
OUTBOX = BRIDGE_DIR / "outbox.jsonl"  # B → A

def append_jsonl(path, obj):
    with open(path, "a") as f:
        fcntl.flock(f, fcntl.LOCK_EX)
        f.write(json.dumps(obj) + "\n")
        fcntl.flock(f, fcntl.LOCK_UN)

Technical Analysis

The default data directory is under /tmp, and neither the directory nor its files are created with explicit restrictive permissions. Their actual modes depend on the process umask and any pre-existing path. The code also does not verify directory ownership or reject symbolic links.

On a multi-user system, permissive modes or a pre-created path can expose message content to other local principals. Because bridge replies may contain workspace-derived information, these files can contain sensitive operational data.

Attack Path

  1. The bridge starts with a permissive umask or uses an attacker-influenced pre-existing /tmp/acp_bridge path.
  2. Message files are created with permissions that allow access by another local account, or the files resolve through an unsafe pre-created path.
  3. A local attacker reads inbox.jsonl or outbox.jsonl.
  4. The attacker obtains historical tasks, responses, and any sensitive information contained in them.

Impact Assessment

Exploitation can disclose the complete locally retained bridge history to another local user or process. The issue does not independently grant remote access, but it violates least privilege on shared systems and may expose data returned from otherwise protected workspace files.

Remediation
View remediation

Remediation Suggestions

  • Create the bridge directory with mode 0700 and message files with mode 0600.
  • Verify that the directory and files are owned by the expected service account.
  • Reject symbolic links and unexpected non-regular files.
  • Prefer a service-specific state directory outside globally shared /tmp.
  • Open files using secure flags such as O_NOFOLLOW where supported.
  • Define and enforce a mandatory retention period instead of relying on optional pruning.

T09 · Insecure Skill Coding Practices

Error
Location
references/monitoring.md:20
Finding

Monitoring Template Uses eval with Environment-Derived Values

Content
View full analysis

Vulnerability Details

File Location: references/monitoring.md:20-24
Vulnerability Type: Shell command injection
Risk Level: High

Code Snippet:

bash
# --- Check 1: Bridge process alive ---
AUTH_HEADER=""
[ -n "$BRIDGE_TOKEN" ] && AUTH_HEADER="-H \"Authorization: Bearer $BRIDGE_TOKEN\""

HEALTH=$(eval curl -s -f --max-time 5 "http://$BRIDGE_HOST:$BRIDGE_PORT/api/health" $AUTH_HEADER 2>/dev/null)

Technical Analysis

BRIDGE_TOKEN, BRIDGE_HOST, and BRIDGE_PORT are environment-derived values. The script constructs command text from those values and passes it to eval, causing the shell to parse the expanded content as executable syntax for a second time.

Quoting embedded in the AUTH_HEADER string does not provide a security boundary once eval is used. Shell metacharacters, substitutions, or command separators in attacker-influenced configuration can become executable commands.

Attack Path

  1. An attacker or lower-trust automation modifies the monitoring environment or service configuration.
  2. A malicious value containing shell syntax is assigned to BRIDGE_TOKEN, BRIDGE_HOST, or BRIDGE_PORT.
  3. The health check runs under cron or heartbeat.
  4. eval reparses the malicious value as shell syntax.
  5. The injected command executes with the privileges of the monitoring process.

Impact Assessment

Successful exploitation permits arbitrary command execution under the account running the heartbeat or monitoring cron. That account may have access to agent workspaces, bridge messages, credentials, and process-management capabilities.

Remediation
View remediation

Remediation Suggestions

  • Remove eval completely.
  • Construct curl arguments with a Bash array:
    bash
    CURL_ARGS=(-s -f --max-time 5)
    if [ -n "$BRIDGE_TOKEN" ]; then
        CURL_ARGS+=(-H "Authorization: Bearer $BRIDGE_TOKEN")
    fi
    HEALTH=$(curl "${CURL_ARGS[@]}" \
        "http://$BRIDGE_HOST:$BRIDGE_PORT/api/health")
    
  • Strictly validate host and port configuration before use.
  • Load the token from protected secret storage rather than broadly inherited environment configuration.
  • Run monitoring under a dedicated unprivileged account.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_bridge_ts.sh:13
Finding

Timestamp Argument Is Interpolated into Executable Python Source

Content
View full analysis

Vulnerability Details

File Location: scripts/save_bridge_ts.sh:13-30
Vulnerability Type: Code injection through unsafe shell-to-Python interpolation
Risk Level: Medium

Code Snippet:

bash
TS="$1"
if [ -z "$TS" ]; then
    echo "Usage: save_bridge_ts.sh <timestamp>"
    exit 1
fi

TS_FILE="${BRIDGE_TS_FILE:-/tmp/acp_bridge_last_ts}"

# Normalize: if ts > 9999999999, treat as milliseconds and convert
FIXED=$(python3 -c "
from decimal import Decimal
ts = Decimal('$TS')
if ts > 9999999999:
    ts = ts / 1000
print(str(ts))
")

echo "$FIXED" > "$TS_FILE"

Technical Analysis

The first argument is inserted directly into a double-quoted shell string that becomes Python source. The value is not validated as a decimal before interpolation. Shell substitutions can be evaluated while constructing the python3 -c argument, and quote characters can terminate the Python string and introduce additional Python statements.

In the documented normal flow, the timestamp originates from a server-generated ts field, which reduces direct remote exploitability. The helper remains unsafe when called with an argument controlled by another script, a compromised agent, or a local user.

Attack Path

  1. An attacker gains influence over the argument passed to save_bridge_ts.sh.
  2. The attacker supplies a value containing shell substitution or Python string-termination syntax.
  3. The script interpolates the value into the python3 -c program.
  4. The shell or Python interpreter executes the injected content.
  5. The payload runs with the privileges of the cron or agent process.

Impact Assessment

Exploitation allows arbitrary command execution as the account invoking the helper. The attacker may consequently access or modify workspace content, bridge state, and credentials available to that account. Direct exploitation through an ordinary bridge timestamp is not established beca ...[truncated 47 chars]

Remediation
View remediation

Remediation Suggestions

  • Pass the timestamp as a positional Python argument rather than embedding it in source:
    bash
    FIXED=$(python3 - "$TS" <<'PY'
    import sys
    from decimal import Decimal, InvalidOperation
    
    try:
        ts = Decimal(sys.argv[1])
    except InvalidOperation:
        raise SystemExit("Invalid timestamp")
    
    if ts > 9999999999:
        ts /= 1000
    print(ts)
    PY
    )
    
  • Reject values that do not match a strict decimal timestamp format.
  • Fail closed if conversion fails.
  • Validate BRIDGE_TS_FILE and write the cursor atomically with restrictive permissions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/acp_bridge.py:61
Finding

Bridge Accepts Unbounded HTTP Request Bodies and Message Sizes

Content
View full analysis

Vulnerability Details

File Location: scripts/acp_bridge.py:61-78
Vulnerability Type: Authenticated memory and disk exhaustion
Risk Level: Medium

Code Snippet:

python
def do_POST(self):
    if not self.check_auth():
        return
    length = int(self.headers.get("Content-Length", 0))
    try:
        body = json.loads(self.rfile.read(length))
    except json.JSONDecodeError:
        self.send_error(400, "Invalid JSON")
        return
    text = body.get("message", "") or body.get("text", "")
    sender = body.get("from", "unknown")
    msg = {
        "id": int(time.time() * 1000),
        "ts": time.time(),
        "from": sender,
        "text": text
    }

    if self.path == "/api/send":
        append_jsonl(INBOX, msg)

Technical Analysis

The server trusts the client-supplied Content-Length and reads that amount into memory without enforcing a maximum. It also imposes no maximum length on message, text, or from. An authenticated client can therefore cause large allocations and append arbitrarily large records to persistent storage.

Authentication does not eliminate this risk because both agents share one broad credential. Compromise or malfunction of either peer permits resource exhaustion.

Attack Path

  1. An attacker obtains the bridge token or compromises a configured peer.
  2. The attacker repeatedly sends very large JSON bodies to /api/send or /api/reply.
  3. The server allocates memory to read and parse each body.
  4. Accepted messages are appended to the JSONL files.
  5. Memory pressure terminates or stalls the process, or storage fills until the bridge or host becomes unavailable.

Impact Assessment

Exploitation can deny bridge service, consume host memory and disk, delay every poll because files are read linearly, and potentially affect other services on the same host. It does not directly provide additional privileges, but c ...[truncated 39 chars]

Remediation
View remediation

Remediation Suggestions

  • Reject missing, invalid, negative, or excessive Content-Length values before reading.
  • Set a small explicit request limit appropriate for agent messages and return HTTP 413 for larger bodies.
  • Validate that the decoded JSON is an object and that all expected fields are strings.
  • Enforce individual limits for message and sender fields.
  • Add per-token rate limits, storage quotas, and backpressure.
  • Prune or rotate data automatically and monitor disk utilization.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bridge_prune.py:11
Finding

Pruning Can Discard Messages Appended Concurrently

Content
View full analysis

Vulnerability Details

File Location: scripts/bridge_prune.py:11-22
Vulnerability Type: Race condition causing message loss
Risk Level: Medium

Code Snippet:

python
def prune(bridge_dir: str, days: int):
    cutoff = time.time() - days * 86400
    for fname in ["inbox.jsonl", "outbox.jsonl"]:
        fpath = Path(bridge_dir) / fname
        if not fpath.exists():
            continue
        with open(fpath) as f:
            lines = f.readlines()
        kept = [l for l in lines if _ts(l) > cutoff]
        with open(fpath, "w") as f:
            f.writelines(kept)
        print(
            f"Pruned {fname}: {len(lines)} → {len(kept)} messages "
            f"(kept last {days}d)"
        )

Technical Analysis

The bridge server locks files while appending, but the pruning script does not acquire the same lock. It reads the original file, releases it, computes retained lines, and then truncates and rewrites the file.

Any message appended after the initial read but before the rewrite is absent from kept and is deleted when the file is truncated. Concurrent appends during rewriting can also produce inconsistent outcomes.

Attack Path

  1. The scheduled weekly pruning process reads an inbox or outbox file.
  2. A legitimate or malicious authenticated peer appends a message before pruning rewrites the file.
  3. The pruning script opens the file with mode w, truncating it.
  4. It writes only the records captured by its earlier read.
  5. The newly appended message is silently lost.

Impact Assessment

The race can destroy legitimate tasks or replies, causing communication integrity and availability failures. An authenticated attacker can increase the probability of loss by generating traffic during the known pruning schedule, although the issue can also occur during normal operation.

Remediation
View remediation

Remediation Suggestions

  • Acquire the same exclusive flock used by the server and hold it across the entire read-filter-replace operation.
  • Write retained records to a securely created temporary file in the same directory.
  • Flush and fsync the temporary file, then atomically replace the original.
  • Preserve restrictive ownership and permissions on replacement files.
  • Coordinate pruning with the server or implement rotation inside the server process.
  • Add tests that append messages concurrently while pruning and verify that no new records are lost.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (26)

Tainted flow: 'req' from os.environ.get (line 26, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/bridge_reply.py (reported line 35)May include surrounding context.

python
},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read())

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The documented behavior understates the security exposure of the bridge by claiming communication stays only between two configured agents and by omitting destructive or broader-access behavior noted by analysis, such as accepting any authenticated client and exposing additional endpoints. Misleading documentation can cause operators to deploy the service with weaker controls than the actual trust model requires, expanding the attack surface to anyone holding the shared token.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior understates the security exposure of the bridge by claiming communication stays only between two configured agents and by omitting destructive or broader-access behavior noted by analysis, such as accepting any authenticated client and exposing additional endpoints. Misleading documentation can cause operators to deploy the service with weaker controls than the actual trust model requires, expanding the attack surface to anyone holding the shared token.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The template creates an automated chain where one agent polls messages from another, processes them, updates local context, and can send follow-up tasks autonomously. That makes it vulnerable to prompt/message chaining abuse: a compromised or malicious peer can inject instructions that persist into workspace files, influence future runs, and trigger further actions without human review.

Content

Scanner excerpt · references/cron-templates.md (reported line 39)May include surrounding context.

md
"sessionTarget": "isolated",
  "payload": {
    "kind": "agentTurn",
    "message": "BRIDGE CHECK — You are [AGENT_A_NAME].\n\nStep 1: Read last-recv timestamp\nRun: cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0\n\nStep 2: Poll for replies from [AGENT_B]\nRun: curl -s \"http://[BRIDGE_HOST]:18790/api/recv?after=$(cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0)\" -H 'Authorization: Bearer [TOKEN]'\n\nIf count == 0: reply NO_REPLY. Done.\n\nStep 3: Process each reply. Update your workspace context files with new information.\n\nStep 4: If you have new tasks or questions for [AGENT_B], send them:\nRun: curl -s -X POST http://[BRIDGE_HOST]:18790/api/send -H 'Authorization: Bearer [TOKEN]' -H 'Content-Type: application/json' -d '{\"message\": \"<task text>\", \"from\": \"[AGENT_A_NAME]\"}'\nFor multi-line messages, use python3 with json.dumps instead of curl to encode safely.\n\nStep 5: Save latest recv timestamp (use 'ts' field, float seconds)\nRun: echo <latest_ts> > /tmp/acp_bridge_last_recv_ts",
    "model": "[STRONG_MODEL]",
    "timeoutSeconds": 240
  },

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documents capabilities that involve shell execution, environment secrets, file writes, and network access, but it does not declare any tool scope or permission boundaries. That increases the chance an agent will run the setup and polling steps with broader privileges than intended, including access to bridge tokens and arbitrary local files.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

bash
export ACP_BRIDGE_TOKEN=$(openssl rand -hex 16)
echo "$ACP_BRIDGE_TOKEN"  # both agents need this
nohup python3 acp_bridge.py > /tmp/acp_bridge.log 2>&1 &
echo $! > /tmp/acp_bridge.pid
curl -s http://localhost:18790/api/health -H "Authorization: Bearer $ACP_BRIDGE_TOKEN"

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/gotchas.md (reported line 177)May include surrounding context.

bash
export ACP_BRIDGE_TOKEN=$(openssl rand -hex 16)
echo "$ACP_BRIDGE_TOKEN"  # both agents need this
nohup python3 acp_bridge.py > /tmp/acp_bridge.log 2>&1 &
echo $! > /tmp/acp_bridge.pid
curl -s http://localhost:18790/api/health -H "Authorization: Bearer $ACP_BRIDGE_TOKEN"

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/monitoring.md (reported line 96)May include surrounding context.

bash
export ACP_BRIDGE_TOKEN=$(openssl rand -hex 16)
echo "$ACP_BRIDGE_TOKEN"  # both agents need this
nohup python3 acp_bridge.py > /tmp/acp_bridge.log 2>&1 &
echo $! > /tmp/acp_bridge.pid
curl -s http://localhost:18790/api/health -H "Authorization: Bearer $ACP_BRIDGE_TOKEN"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly presents exposing port 18790 to the public internet with only a shared bearer token as a simple deployment option. A single shared token provides weak operational security against leakage, reuse, interception on non-TLS links, and unauthorized access by any party that obtains it, especially because both agents are treated as fully trusted once authenticated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The template explicitly instructs direct HTTP polling to a configurable bridge host, which contradicts the metadata claim of 'No external network calls.' Even if intended for agent-to-agent use only, this mismatch can mislead operators about network exposure and trust boundaries, causing unintended data transmission off-host or off-instance.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The template directs an agent to fetch and potentially respond with workspace-derived information over HTTP using a bearer token, but it provides no privacy or data-transmission warning. Because the message contents may include local context files and tool-derived results, operators may unintentionally expose sensitive information across the bridge.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This instruction performs authenticated HTTP POST transmission of arbitrary task text to a configurable host, which is a real external transmission channel. In this skill context, the danger is elevated because messages can include workspace-derived information and the bridge host may be remote, making confidentiality dependent on correct host configuration, token secrecy, and transport security.

Content

Scanner excerpt · references/cron-templates.md (reported line 39)May include surrounding context.

md
"sessionTarget": "isolated",
  "payload": {
    "kind": "agentTurn",
    "message": "BRIDGE CHECK — You are [AGENT_A_NAME].\n\nStep 1: Read last-recv timestamp\nRun: cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0\n\nStep 2: Poll for replies from [AGENT_B]\nRun: curl -s \"http://[BRIDGE_HOST]:18790/api/recv?after=$(cat /tmp/acp_bridge_last_recv_ts 2>/dev/null || echo 0)\" -H 'Authorization: Bearer [TOKEN]'\n\nIf count == 0: reply NO_REPLY. Done.\n\nStep 3: Process each reply. Update your workspace context files with new information.\n\nStep 4: If you have new tasks or questions for [AGENT_B], send them:\nRun: curl -s -X POST http://[BRIDGE_HOST]:18790/api/send -H 'Authorization: Bearer [TOKEN]' -H 'Content-Type: application/json' -d '{\"message\": \"<task text>\", \"from\": \"[AGENT_A_NAME]\"}'\nFor multi-line messages, use python3 with json.dumps instead of curl to encode safely.\n\nStep 5: Save latest recv timestamp (use 'ts' field, float seconds)\nRun: echo <latest_ts> > /tmp/acp_bridge_last_recv_ts",
    "model": "[STRONG_MODEL]",
    "timeoutSeconds": 240
  },

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The outbox template documents both receiving and sending messages over HTTP while the skill description claims there are no external network calls. This discrepancy increases the risk of unsafe deployment because users may enable the skill under false assumptions about egress, authentication exposure, and data handling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The template tells the agent to update workspace context files automatically based on received replies without warning that user data will be modified. This creates integrity risk because untrusted or malformed bridge content could be written into local context, poisoning future agent behavior or corrupting records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The pruning template rotates or deletes old messages but does not warn users about retention reduction or irreversible data loss. In operational use, this can destroy audit trails or pending communications if the schedule or retention period is misconfigured.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/gotchas.md (reported line 70)May include surrounding context.

md
---

## 3. Newlines in curl Break JSON

**Symptom**: `JSONDecodeError` on bridge server when sending multi-line messages.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The example shows constructing an HTTP request with a bearer token and message body but gives no warning about secret handling or the sensitivity of transmitted content. In a bridge skill centered on agent-to-agent messaging, normalizing inline tokens and plaintext local HTTP can lead users to expose credentials in scripts, shell history, logs, or misconfigured non-local deployments.

Content

No source excerpt is available for this finding.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · references/gotchas.md (reported line 92)May include surrounding context.

md
msg = '''Your multi-line
message here'''
data = json.dumps({'message': msg, 'from': 'agent_a'}).encode()
req = urllib.request.Request('http://localhost:18790/api/send',
    data=data, headers={'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json'})
urllib.request.urlopen(req)
"

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · references/gotchas.md (reported line 102)May include surrounding context.

md
## 4. Context Loss Between Poll Cycles

**Symptom**: Agent acknowledges a task in one poll cycle, completely forgets it in the next. Acknowledge → forget → acknowledge loop forever.

**Cause**: Each cron poll spawns an isolated session with zero memory of previous polls. The agent has no persistent state.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The guidance tells operators to persist ongoing agent state to SESSION-STATE.md on disk without warning that task context, credentials, or sensitive data may be written repeatedly and retained. In this skill's context, the file becomes a durable memory store for cross-poll execution, which increases exposure if the workspace is shared, backed up, or insufficiently permissioned.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script builds a shell command string and executes it with eval while interpolating environment-controlled values such as BRIDGE_HOST, BRIDGE_PORT, and BRIDGE_TOKEN. An attacker who can influence those variables can inject additional shell syntax and achieve arbitrary command execution in the context of the monitoring or cron job, which is especially dangerous because heartbeat scripts often run unattended and sometimes with elevated privileges.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module documentation says ACP_BRIDGE_TOKEN is required and that the server refuses to start without it. However, the request auth check explicitly returns success when no token is configured, describing this as an open 'dev mode'. Although the current top-level startup code exits before that branch is normally reachable, the inline intent documented in code contradicts the documented required-auth behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The /api/clear endpoint permanently deletes both inbox and outbox files with a simple GET request and no confirmation, safety interlock, or method restriction. In this bridge skill, messages are the core communication channel, so an authorized caller—or anyone who obtains the shared token—can erase queued traffic and disrupt or hide agent-to-agent communication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The fix section tells the user to write a new timestamp directly to /tmp/acp_bridge_last_ts, which changes persistent runtime state for the bridge. While this is part of troubleshooting, the surrounding text does not explicitly warn that the command resets the cursor and may affect subsequent message polling behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The prevention snippet automatically writes $NOW into /tmp/acp_bridge_last_ts when a future timestamp is detected. This is a file write that alters bridge state, but the documentation does not explicitly warn readers that the self-heal mutates local state and could discard the prior cursor value.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.