Back to skill

Security audit

Towns Protocol Skills

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent documentation for Towns bots, but it teaches unsafe payment-verification and setup patterns that deserve manual review before use.

Review and correct the payment-verification examples before using this skill for paid access or entitlements. Pin and verify the initializer package before running it, avoid exposing development webhooks without request verification, do not log raw user messages in production, and require explicit user confirmation for transfers, signatures, deployments, and message deletion.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:78
Finding

Unpinned Third-Party CLI Package Is Downloaded and Executed

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:78-80
Vulnerability Type: Supply-chain exposure through unpinned package execution
Risk Level: Medium

bash
bunx towns-bot init my-bot
cd my-bot
bun install

Technical Analysis

The initialization instructions use bunx to download and execute the currently resolved version of the unscoped towns-bot package. No exact version, integrity value, lockfile requirement, or package provenance check is specified.

This is particularly relevant because the Skill otherwise identifies @towns-protocol/bot as the SDK. The documentation does not establish whether the differently named towns-bot CLI package is an official and trusted component.

Package execution through bunx can run package entry points and potentially installation lifecycle scripts with the invoking developer's operating-system privileges. The effective code can therefore change after this Skill has been reviewed.

Attack Path

  1. An attacker compromises the referenced package, one of its dependencies, or its publisher account, or gains control of a package name that users incorrectly assume is official.
  2. The attacker publishes a malicious version that contains a hostile CLI entry point or lifecycle script.
  3. A developer follows the documented bunx towns-bot init my-bot instruction.
  4. Bun resolves and downloads the attacker-controlled version.
  5. The malicious package executes under the developer's account during project initialization.
  6. The package can access files, environment variables, source repositories, developer credentials, and network resources available to that account.

Impact Assessment

Successful exploitation permits arbitrary code execution with the privileges of the developer running the command. Depending on the environment, this may expose application credentials, wallet material, source code, package-registry tokens, SSH credentials, cloud credential ...[truncated 271 chars]

Remediation
View remediation

Remediation Suggestions

  1. Confirm and document the official publisher and exact package name for the CLI.
  2. Pin the CLI to a reviewed exact version, for example bunx towns-bot@X.Y.Z, rather than resolving the latest release.
  3. Provide the expected package integrity hash or a documented registry-signature verification procedure.
  4. Pin direct and transitive dependencies through a committed lockfile.
  5. Run initialization in a disposable, minimally privileged environment without production secrets or wallet credentials.
  6. Disable or review package lifecycle scripts where the package manager and workflow permit it.
  7. Add an explicit warning that users must verify the package owner and version before execution.

T09 · Insecure Skill Coding Practices

Error
Location
references/BLOCKCHAIN.md:42
Finding

Payment Authorization Relies Only on Transaction Receipt Success

Content
View full analysis

Vulnerability Details

File Location: references/BLOCKCHAIN.md:42-60
Related Location: references/INTERACTIVE.md:64-79
Vulnerability Type: Incomplete blockchain payment verification and transaction replay
Risk Level: High

Primary vulnerable example:

typescript
bot.onInteractionResponse(async (handler, event) => {
  if (event.response.payload.content?.case !== 'transaction') return
  const tx = event.response.payload.content.value

  if (tx.txHash) {
    const receipt = await waitForTransactionReceipt(bot.viem, {
      hash: tx.txHash
    })

    if (receipt.status !== 'success') {
      await handler.sendMessage(event.channelId, 'Transaction failed on-chain')
      return
    }

    // NOW safe to grant access
    await grantUserAccess(event.userId)
    await handler.sendMessage(event.channelId, 'Payment confirmed!')
  }
})

The related interactive example follows the same incomplete validation pattern:

typescript
bot.onInteractionResponse(async (handler, event) => {
  if (event.response.payload.content?.case !== 'transaction') return

  const tx = event.response.payload.content.value

  if (tx.txHash) {
    // IMPORTANT: Always verify on-chain before granting access
    // See BLOCKCHAIN.md for full verification pattern
    const receipt = await waitForTransactionReceipt(bot.viem, {
      hash: tx.txHash
    })

    if (receipt.status === 'success') {
      await handler.sendMessage(event.channelId,
        'Payment confirmed: https://basescan.org/tx/' + tx.txHash)
    } else {
      await handler.sendMessage(event.channelId, 'Transaction failed on-chain')
    }
  } else if (tx.error) {
    await handler.sendMessage(event.channelId, 'Transaction rejected: ' + tx.error)
  }
})

Technical Analysis

A successful transaction receipt proves only that a transaction was included and did not revert. It does not prove that the transa ...[truncated 2260 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a server-side payment record before sending the transaction request. Store the expected user, chain ID, token, amount, recipient, request ID, expiration time, and status.
  2. Bind each request to a cryptographically unpredictable nonce or unique order identifier.
  3. Retrieve the full transaction and receipt from a trusted RPC endpoint.
  4. Verify the chain ID and require the configured network.
  5. Verify that the transaction sender corresponds to the expected user or authorized smart account.
  6. Verify the exact destination contract and expected function selector or native-value transfer.
  7. For token payments, decode and validate the relevant transfer logs, including token contract, sender, recipient, and amount.
  8. Require the exact expected amount and asset; do not infer payment solely from receipt success.
  9. Enforce transaction-hash uniqueness with an atomic database constraint so a hash cannot satisfy multiple requests.
  10. Mark the payment consumed and grant access in an idempotent, transactional operation.
  11. Require an appropriate confirmation depth or finalized state based on the value and threat model.
  12. Reject expired, mismatched, already-used, or unverifiable responses and log them for investigation.
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 (9)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly enables blockchain operations, transfers, and deployment, but does not present a prominent warning that these actions can be irreversible, cost real funds, or affect production systems. In this context, omission of safety guidance increases the chance that an agent or developer will initiate state-changing or costly actions without confirmation, especially because the skill includes wallet, transaction, and deployment workflows.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The critical rules explicitly state that interactive forms use a type property and not case. Later, the example handler inspects event.response.payload.content?.case and nested c.component.case, which directly contradicts that guidance and can mislead developers into implementing the wrong event parsing logic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file includes sample code that executes a blockchain transaction calling transfer, which can move assets and is irreversible. While the file explains how to verify payments afterward, this section does not warn users that executing the example submits a real transaction or may spend funds.

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/DEBUGGING.md (reported line 11)May include surrounding context.

bash
# Your bot should log incoming requests
curl -X POST https://your-webhook-url/webhook \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The debugging example logs user-controlled message content directly to console without any warning, redaction guidance, or scope limitation. In a bot platform, messages can contain sensitive personal data, secrets, or private channel content, so enabling this pattern in production or shared logging systems can create unintended data exposure and retention risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The deployment guide explicitly recommends exposing the bot's local webhook endpoint through a public tunnel (Tailscale Funnel or ngrok) but does not mention authentication, request signature verification, IP allowlisting, or the risks of exposing a development service to the internet. In the context of a webhook-driven bot that may process messages and trigger blockchain actions, this omission can lead developers to deploy an internet-reachable endpoint with weak or no request validation, increasing the chance of spoofed webhook requests or unintended data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The transaction and signature examples initiate wallet-affecting actions without showing an explicit user-facing warning or consent language in the example itself. In a bot-building reference, developers often copy patterns verbatim, so this omission can normalize ambiguous prompts and increase the risk of users approving token transfers or signatures without understanding the consequences.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The sample health endpoint returns the bot gas wallet address, which unnecessarily exposes an operational identifier to any party that can reach the health check. While a wallet address is not a secret by itself, publishing it via a standard liveness endpoint can aid reconnaissance by linking infrastructure to on-chain activity and making the bot easier to profile or target.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file describes how to delete a bot's own message via handler.removeEvent(channelId, eventId) but provides no warning about the destructive nature of the operation or its effect on message history. Under the markdown-specific missing-warning rule, behaviors affecting user-visible data should include a caution or usage note.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.