Back to skill

Security audit

Clawbird

Security checks for vulnerabilities and agentic risk

Overview

This X/Twitter skill is mostly transparent, but it should be reviewed because unpinned npm code would receive powerful account and direct-message access.

Review or pin the exact @xonder/clawbird package version before installing, grant only the X API scopes you actually need, and require explicit approval for tweets, replies, likes, follows, and DMs. Treat DM-reading as sensitive, not as a generally safe autonomous read-only action.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:13
Finding
Unpinned Runtime Dependency Receives Sensitive X Account Credentials## Vulnerability Details **File Location**: `SKILL.md`, lines 13–16 **Vulnerability Type**: Unpinned third-party runtime dependency **Risk Level**: Medium ### Vulnerable Code Snippet ```yaml install: - id: "npm" kind: "node" package: "@xonder/clawbird" label: "Install clawbird plugin (npm)" ``` The associated trust statement at `SKILL.md`, lines 67–80, confirms that the executable implementation is obtained from npm at installation time rather than included in the reviewed artifact: ```markdown Clawbird is an npm-distributed skill — the runtime code is installed via `npm i -g @xonder/clawbird` and is not bundled in the ClawHub skill archive. The security properties below can be verified by auditing the source: - **Source:** https://github.com/xonder/clawbird (MIT) - **npm:** https://www.npmjs.com/package/@xonder/clawbird - Makes **no network requests** other than to `api.x.com` ([source: `src/client.ts`](https://github.com/xonder/clawbird/blob/main/src/client.ts)) - Reads and writes **one local file** (`clawbird-interactions.jsonl`) for session interaction logging — no other filesystem access ([source: `src/interaction-log.ts`](https://github.com/xonder/clawbird/blob/main/src/interaction-log.ts)) - Has **zero transitive dependencies** beyond the official `@xdevplatform/xdk` SDK and `@sinclair/typebox` - Includes a comprehensive test suite (200+ tests) verifiable via `npm test` Since this skill installs code from npm at runtime, **review the source or pin a specific version** (`npm i -g @xonder/clawbird@1.1.0`) before granting credentials. ``` ### Technical Analysis The installation metadata references `@xonder/clawbird` without an exact version or integrity constraint. Package resolution can therefore select a release published after this skill was audited. The runtime implementation is not bundled in the project, so its claimed network, filesystem, credential-handling, and dependency properti ...[truncated 2245 chars]
Remediation
## Remediation Suggestions 1. Replace the unversioned package declaration with an exact, reviewed version, such as `@xonder/clawbird@1.1.0`, after independently verifying that release. 2. Enforce package integrity using a trusted lockfile, cryptographic integrity hash, signed provenance, or registry signature mechanism where the installation platform supports it. 3. Prefer bundling the reviewed runtime source with the skill so the audited artifact matches the code that will execute. 4. Audit each dependency update before changing the pinned version, including package provenance, install scripts, transitive dependencies, network destinations, filesystem access, and credential handling. 5. Grant only the minimum OAuth scopes required for intended operations. Use separate credentials for read-only and write functionality where possible. 6. Require explicit user confirmation for tweets, replies, likes, follows, and direct messages. 7. Run the plugin in a restricted sandbox with minimal filesystem access, no unnecessary environment variables, and outbound network access limited to the required official X API endpoint. 8. Rotate and revoke X credentials promptly if package compromise is suspected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (12)

Credential Access

High
Category
Privilege Escalation
Content
**Where credentials come from:** You must generate them at the [X Developer Portal](https://developer.x.com):
1. Create a Project and App at developer.x.com
2. Generate OAuth 1.0a keys: API Key, API Secret, Access Token, Access Token Secret
3. Optionally generate a Bearer Token for read-only operations

**How credentials are provided:** Credentials are passed to the plugin at runtime by the OpenClaw plugin config system (`pluginConfig`). The plugin never reads config files directly. Fallback: environment variables `X_API_KEY`, `X_API_SECRET`, `X_ACCESS_TOKEN`, `X_ACCESS_SECRET`, `X_BEARER_TOKEN`.
Confidence
74% confidence
Finding
The skill requires powerful OAuth credentials and bearer tokens that can post content, like, follow, and access private DMs on behalf of the user. Although credential use is necessary for the integration and the text does not indicate overt mishandling, granting these secrets to npm-installed runtime code materially increases account takeover, impersonation, and privacy risk if the package is compromised or behaves unexpectedly.

External Transmission

Medium
Category
Data Exfiltration
Content
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| Endpoint | Method | Tool(s) | Data Sent |
|----------|--------|---------|-----------|
| `https://api.x.com/2/tweets` | POST | x_post_tweet, x_post_thread, x_reply_tweet | Tweet text, reply metadata |
| `https://api.x.com/2/tweets/:id` | GET | x_get_tweet | Tweet ID |
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
Confidence
50% 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
| `https://api.x.com/2/tweets/search/recent` | GET | x_search_tweets | Search query string |
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
| `https://api.x.com/2/users/by/username/:username` | GET | x_get_user_profile, x_send_dm, x_follow_user | Username |
| `https://api.x.com/2/users/:id/likes` | POST | x_like_tweet | Tweet ID |
| `https://api.x.com/2/users/:id/mentions` | GET | x_get_mentions | User ID, pagination params |
| `https://api.x.com/2/users/:id/following` | POST | x_follow_user | Target user ID |
| `https://api.x.com/2/dm_conversations/with/:id/messages` | POST | x_send_dm | Message text, recipient ID |
Confidence
79% confidence
Finding
This endpoint sends direct message content to a third-party service, which is a meaningful privacy-sensitive transmission. In context it is intentional and disclosed, but DMs are high-sensitivity data and autonomous use could leak confidential information or send messages without adequate approval.

External Transmission

Medium
Category
Data Exfiltration
Content
| `https://api.x.com/2/users/me` | GET | x_like_tweet, x_get_mentions, x_follow_user | (auth headers only) |
| `https://api.x.com/2/users/by/username/:username` | GET | x_get_user_profile, x_send_dm, x_follow_user | Username |
| `https://api.x.com/2/users/:id/likes` | POST | x_like_tweet | Tweet ID |
| `https://api.x.com/2/users/:id/mentions` | GET | x_get_mentions | User ID, pagination params |
| `https://api.x.com/2/users/:id/following` | POST | x_follow_user | Target user ID |
| `https://api.x.com/2/dm_conversations/with/:id/messages` | POST | x_send_dm | Message text, recipient ID |
| `https://api.x.com/2/dm_conversations/with/:id/dm_events` | GET | x_get_dms (filtered) | Participant ID |
Confidence
76% confidence
Finding
Reading filtered DM events from X exposes private message content to the agent runtime, creating confidentiality risk if the agent is over-permissioned or logs outputs. This is expected for the feature, but it is still a real privacy-sensitive capability that can surface highly sensitive communications.

External Transmission

Medium
Category
Data Exfiltration
Content
| `https://api.x.com/2/users/by/username/:username` | GET | x_get_user_profile, x_send_dm, x_follow_user | Username |
| `https://api.x.com/2/users/:id/likes` | POST | x_like_tweet | Tweet ID |
| `https://api.x.com/2/users/:id/mentions` | GET | x_get_mentions | User ID, pagination params |
| `https://api.x.com/2/users/:id/following` | POST | x_follow_user | Target user ID |
| `https://api.x.com/2/dm_conversations/with/:id/messages` | POST | x_send_dm | Message text, recipient ID |
| `https://api.x.com/2/dm_conversations/with/:id/dm_events` | GET | x_get_dms (filtered) | Participant ID |
| `https://api.x.com/2/dm_events` | GET | x_get_dms (all) | Pagination params |
Confidence
76% confidence
Finding
Accessing all DM events increases the volume and sensitivity of private content exposed to the agent compared with narrower APIs. Even though this is disclosed and likely intended, broad DM retrieval can unnecessarily expand the blast radius of prompt leakage, logging, or unintended downstream disclosure.

Static analysis

No suspicious patterns detected.