Back to skill

Security audit

twitter-cli

Security checks for vulnerabilities and agentic risk

Overview

This is a real Twitter/X CLI skill, but it asks for and auto-extracts live browser session cookies in ways that are too risky for automatic agent use.

Install only if you are comfortable giving this skill effective control of the selected X/Twitter account. Do not paste full cookie strings into chat or shared logs; prefer a local, explicit credential setup, and avoid using the runtime browser-cookie extraction path in high-trust browser profiles. Review write actions carefully because the tool can post, delete, like, retweet, bookmark, follow, and unfollow as the authenticated account.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
twitter_cli/auth.py:114
Finding
Excessive Collection and Transmission of Complete Browser Cookie Sets## Vulnerability Details **File Location**: `SKILL.md:70-79`, `twitter_cli/auth.py:114-132`, `twitter_cli/auth.py:204-221`, `twitter_cli/auth.py:292-300`, `twitter_cli/client.py:878-882` **Vulnerability Type**: Excessive credential access and transmission beyond least privilege **Risk Level**: High ### Vulnerable Code `SKILL.md:77-80` instructs the Agent to place a user-provided complete cookie string into a shell variable: ```bash FULL_COOKIE="user-provided complete cookie string" export TWITTER_AUTH_TOKEN=$(echo "$FULL_COOKIE" | grep -oE 'auth_token=[a-f0-9]+' | cut -d= -f2) export TWITTER_CT0=$(echo "$FULL_COOKIE" | grep -oE 'ct0=[a-f0-9]+' | cut -d= -f2) twitter whoami ``` `twitter_cli/auth.py:114-132` collects every cookie associated with X or Twitter domains: ```python def _extract_cookies_from_jar(jar: Any, source: str = "unknown") -> Optional[Dict[str, str]]: """Extract Twitter cookies from a cookie jar.""" result: Dict[str, str] = {} all_cookies: Dict[str, str] = {} twitter_cookie_count = 0 for cookie in jar: domain = cookie.domain or "" if _is_twitter_domain(domain): twitter_cookie_count += 1 if cookie.name == "auth_token": result["auth_token"] = cookie.value elif cookie.name == "ct0": result["ct0"] = cookie.value if cookie.name and cookie.value: all_cookies[cookie.name] = cookie.value if "auth_token" in result and "ct0" in result: cookies = {"auth_token": result["auth_token"], "ct0": result["ct0"]} if all_cookies: cookies["cookie_string"] = "; ".join("%s=%s" % (k, v) for k, v in all_cookies.items()) logger.info("Extracted %d total cookies for full browser fingerprint", len(all_cookies)) return cookies ``` `twitter_cli/client.py:878-882` transmits the resulting complete cookie string in authenti ...[truncated 2821 chars]
Remediation
## Remediation Suggestions 1. Remove the instruction asking users to send complete cookie headers through an Agent conversation. 2. Accept credentials only through local, non-echoing input, a permission-restricted credential file, an operating-system secret store, or environment injection performed outside the conversation. 3. Replace the unrestricted `all_cookies` collection with an explicit allowlist of cookie names proven necessary for each API operation. 4. Default to transmitting only `auth_token` and `ct0`. If additional cookies are demonstrably required, document and allowlist each one individually. 5. Separate read-only and write-capable authentication modes where feasible, using the least privileged mode for status and read commands. 6. Ensure verbose logging never prints cookie names and values, request headers, or proxy URLs containing credentials. 7. Clear temporary secret variables immediately after use and document shell-history-safe credential setup. 8. Add tests asserting that unrelated browser cookies never appear in the generated `Cookie` request header.

T08 · Insecure Dependencies

Error
Location
twitter_cli/auth.py:276
Finding
Unpinned Runtime Installation of a Browser-Credential Dependency## Vulnerability Details **File Location**: `twitter_cli/auth.py:276-289` **Vulnerability Type**: Unpinned runtime dependency resolution in a credential-sensitive execution path **Risk Level**: High ### Vulnerable Code ```python data, retry_with_uv = _run_extract_command( [sys.executable, "-c", extract_script], timeout=15, label="current env", ) if data is None and retry_with_uv: data, _ = _run_extract_command( ["uv", "run", "--with", "browser-cookie3", "python", "-c", extract_script], timeout=30, label="uv fallback", ) ``` ### Technical Analysis When `browser-cookie3` is unavailable in the current environment, the authentication flow invokes `uv run --with browser-cookie3` without an exact version or hash. This causes a package-index resolution and execution at runtime. The dependency is particularly sensitive because the executed extraction script immediately imports `browser_cookie3` and asks it to access Arc, Chrome, Edge, Firefox, and Brave cookie stores. Any malicious or compromised package release selected by the resolver would execute with the current user’s privileges and in a process specifically intended to access browser credentials. The project declares `browser-cookie3>=0.19`, but no reviewed lockfile or hash constraints were present in the supplied directory structure. A lower-bound constraint does not guarantee that the same audited dependency version will execute in future runs. This is not a confirmed malicious dependency. The vulnerability is the unsafe, mutable runtime installation channel combined with access to high-value credentials. ### Attack Path 1. The installed environment does not contain an importable `browser_cookie3` package. 2. Cookie extraction in the current Python environment returns the retry condition. 3. The program automatically launches `uv run --with browser-cookie3`. 4. `uv` resolves a currently available packag ...[truncated 1010 chars]
Remediation
## Remediation Suggestions 1. Remove automatic dependency installation from the authentication path. 2. Fail closed with a clear installation error when `browser-cookie3` is unavailable. 3. Install dependencies during a controlled build or deployment phase from a committed lockfile. 4. Pin exact dependency and transitive dependency versions and verify package hashes. 5. Use a trusted, explicitly configured package index and enforce repository integrity controls. 6. Generate and review a software bill of materials for releases. 7. Add dependency vulnerability and provenance checks to continuous integration. 8. If browser extraction must run in a subprocess, use the already installed and verified package in an isolated environment rather than dynamically resolving code. 9. Restrict the extraction process to the minimum filesystem and network permissions supported by the operating system.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (69)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
json
twitter delete 1234567890
twitter like 1234567890
twitter like 1234567890 --yaml
twitter unlike 1234567890
twitter retweet 1234567890
twitter unretweet 1234567890
twitter bookmark 1234567890
twitter unbookmark 1234567890
twitter follow elonmusk --json
```

### Authentication

twitter-cli uses this auth priority:

1. **Environment variables**: `TWITTER_AUTH_TOKEN` + `TWITTER_CT0`
2. **Browser cookies** (recommended): auto-extract from Arc/Chrome/Edge/Firefox/Brave

Browser extraction is recommended — it forwards ALL Twitter cookies (not just `auth_token` + `ct0`) and aligns request headers with your local runtime, which is closer to normal browser traffic than minimal cookie auth.

After loading cookies, the CLI performs lightweight verification. Commands that require account access fail fast on clear auth errors (`401/403`).

### Proxy Support

Set `TWITTER_PROXY` to route all requests through a proxy:

```bash
# HTTP proxy
export TWITTER_PROXY=http://127.0.0.1:7890

# SOCKS5 pr
Confidence
95% confidence
Finding
The YARA hit is justified by the README's recommendation to auto-extract browser cookies from installed browsers and forward all Twitter cookies, which matches credential-harvesting/stealer-adjacent behavior patterns even if framed as convenience. In the context of an agent skill, harvesting browser session material is especially sensitive because the operator may not realize the tool is using live browser-derived credentials rather than narrowly scoped tokens.

Intent-Code Divergence

High
Confidence
95% confidence
Finding
The README gives conflicting assurances: it says cookies are only used locally and not uploaded, while elsewhere saying all Twitter cookies are forwarded in requests. That contradiction can mislead users and agent operators about where sensitive browser-derived credentials are sent, increasing the risk of unsafe deployment decisions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents this skill as an operational Twitter/X integration for user-requested Twitter actions. However, the supplied code is only testing support code: pytest fixtures that generate mock Tweet objects and load local fixture data. It neither invokes twitter-cli for live Twitter interactions nor implements the listed capabilities like posting, searching, replying, or following. This is a materially different primary purpose, so the description does not accurately represent the actual code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a broad end-user Twitter/X interaction skill covering essentially all Twitter operations. However, the provided code chunk does not implement or expose those operations. It is a test module validating authentication internals, specifically cookie acquisition from environment variables or browsers, verification of cookies, fallback/retry logic, and logging. While authentication is a supporting detail for a Twitter client, this chunk’s actual purpose is materially narrower and different from the declared primary purpose. Therefore the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code does not implement or exercise Twitter/X operations like reading tweets, posting, searching, or user interactions. Instead, it contains unit tests for local configuration handling in the twitter_cli package. While configuration support could be related to a Twitter CLI project, this specific chunk’s primary purpose is testing config loading behavior, which is materially different from the declared end-user Twitter interaction capability.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should perform Twitter/X operations through twitter-cli. However, the actual code shown does not interact with Twitter/X at all. It is a unit test focused on configuration normalization, checking how invalid config values are sanitized and defaults applied. This is a materially different primary purpose from executing Twitter actions, so the description does not accurately represent the behavior of this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
There is a clear mismatch between the declared description and the provided code. The description claims a broad Twitter/X operations skill using twitter-cli for all interactions. However, the code shown is only a unit test for a filtering utility (`filter_tweets`) and does not demonstrate Twitter/X API or CLI operations such as reading, posting, replying, or searching. Its primary purpose is validating tweet filtering logic, specifically immutability and language/retweet filtering. That is materially different from the declared end-user capability.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This code chunk does not expose or implement the broad Twitter/X functionality described. Instead, it is a test module verifying that internal client methods correctly parse fixture payloads and extract tweets, cursors, media, quoted tweets, and follower data. While the tested methods relate to Twitter data structures, the chunk itself is not a general Twitter operations skill and does not perform the declared read/write actions for users. Therefore the description materially overstates and misrepresents the behavior of the supplied code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
There is a clear description-behavior mismatch. The description presents this skill as the general mechanism for all Twitter/X interactions via twitter-cli, implying operational capabilities against Twitter data and actions. However, the provided code chunk is limited to unit tests for serialization behavior: converting tweet objects to/from dictionaries and JSON, and generating a compact serialized representation. These are supporting internal utilities, not the declared end-user Twitter operations. While serialization may be related to a Twitter client library, this specific code does not implement or expose the declared primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
There is a meaningful description-behavior mismatch. The declared purpose says this skill should be used for all Twitter/X interactions, including writes such as posting, replying, liking, retweeting, and following. However, the provided code chunk is not implementing a general Twitter operations skill; it is a smoke-test file for the CLI. Its actual purpose is validating that selected commands work end-to-end against the live API using local browser cookies. It checks auth status and a handful of read-only commands, and the file explicitly states that no writes are tested. While the tested commands overlap partially with the declared read/search/lookup capabilities, the primary function of this code is integration testing, which is materially different from the declared operational skill behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a broad Twitter/X action skill, but this specific code chunk does not perform tweet reading/posting or other user-facing Twitter operations. Instead, it focuses on authentication and credential acquisition, including extracting cookies from local browsers and environment variables, then verifying them with Twitter endpoints. Browser cookie extraction and full-cookie fingerprint forwarding are sensitive capabilities not mentioned in the declared purpose. While authentication can be a supporting detail for Twitter operations, the implementation here includes materially undeclared access to local browser-stored cookies and auth secrets, so the description does not accurately represent this code's behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
There is a clear description-behavior mismatch. The declared purpose says this skill should handle all Twitter/X interactions via twitter-cli, but the supplied code chunk is a configuration utility only. Its behavior is limited to locating config.yaml, reading it from disk, parsing YAML, deep-merging defaults, and normalizing numeric and list values. These are supporting internals at best, but this chunk by itself does not implement the declared Twitter capabilities. Because the actual code’s primary purpose is config handling rather than Twitter interaction, the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description claims a broad Twitter/X command capability covering essentially all platform interactions. This code chunk does not perform any direct Twitter operations at all; it is a utility module for computing engagement scores and filtering/ranking already-available Tweet objects. That is a materially different primary purpose from the declared all-purpose Twitter CLI behavior. While such filtering could support a Twitter tool, this chunk by itself is not accurately represented by the declared description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code is a presentation/formatting module, not an operational Twitter/X client. Its functions build terminal tables and panels from already-supplied Tweet and UserProfile objects and format counts with K/M suffixes. It does not make network requests, invoke twitter-cli commands, authenticate, search, fetch tweets, or execute any write actions like posting, liking, retweeting, or following. While formatting output can be a supporting part of a Twitter CLI, the declared description claims the skill should be used for all Twitter/X operations. That materially overstates what this code chunk actually does, so the description does not accurately represent the supplied code behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code chunk’s primary purpose is output serialization and formatting for a CLI, not Twitter/X interactions. While such helpers could support a Twitter CLI, the supplied code does not read tweets, post content, search users, or access Twitter resources at all. Therefore the declared description does not accurately represent what this specific code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code chunk is narrowly focused on transforming already-obtained GraphQL response data into model objects. It includes helpers for nested extraction, integer parsing, media extraction, author extraction, article parsing, tweet parsing, user parsing, and timeline parsing. There are no functions that make network requests, invoke a CLI, authenticate, post content, like/retweet/follow users, search, or otherwise carry out the broad Twitter/X operations promised by the description. While parsing tweet/user/timeline data supports read-oriented Twitter functionality, the declared purpose materially overstates the implemented capabilities and primary purpose of this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code chunk is a utility module for converting tweet and user profile model objects to and from JSON-safe dictionaries and compact JSON formats. It does not perform any network calls, CLI invocation, authentication, or direct Twitter/X interactions. Because the declared description claims the skill should handle all Twitter/X operations via twitter-cli, while the actual code only supports serialization helpers, the code's actual behavior is materially narrower and different from the declared purpose.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The skill first instructs the agent to ask the user to paste a full Twitter cookie string into chat, then later says not to ask users to share raw cookie values in chat logs. That contradiction is dangerous because operators may follow the earlier collection flow and expose live session credentials that allow account takeover.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill explicitly tells the agent to request the user's full Twitter cookie string, which is a live authentication secret. Transmitting that secret in chat creates immediate privacy and account-compromise risk because anyone with the cookie can impersonate the user until it expires or is revoked.

Ssd 3

High
Confidence
99% confidence
Finding
Soliciting and processing a full Twitter cookie string in natural-language chat is direct secret exfiltration. These cookies function as bearer credentials, so exposure can enable unauthorized access, posting, deletion, following, data access, and persistent session hijacking.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The skill is designed to automatically read authentication cookies from local browsers, including 'ALL Twitter cookies for full browser-like fingerprint'. That is privileged credential access unrelated to a minimal Twitter-operation interface and creates a clear risk of unauthorized account takeover or misuse of the user's active web session.

Credential Access

High
Category
Privilege Escalation
Content
1. Environment variables: TWITTER_AUTH_TOKEN + TWITTER_CT0
2. Auto-extract from browser via browser-cookie3
   Extracts ALL Twitter cookies for full browser-like fingerprint.
   Prefers in-process extraction (required on macOS for Keychain access),
   falls back to subprocess if in-process fails (e.g. SQLite lock).
"""
Confidence
99% confidence
Finding
The docstring explicitly advertises automatic extraction of all Twitter cookies from the browser and notes macOS Keychain-related handling, indicating intent to access locally protected session material. Accessing browser-stored auth cookies is credential harvesting and can enable full account impersonation.

Credential Access

High
Category
Privilege Escalation
Content
from .client import _get_cffi_session

    urls = [
        "https://api.x.com/1.1/account/verify_credentials.json",
        "https://x.com/i/api/1.1/account/settings.json",
    ]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from .client import _get_cffi_session

    urls = [
        "https://api.x.com/1.1/account/verify_credentials.json",
        "https://x.com/i/api/1.1/account/settings.json",
    ]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _extract_in_process() -> Optional[Dict[str, str]]:
    """Extract cookies in the main process (required on macOS for Keychain access).

    On macOS, Chrome encrypts cookies using a key stored in the system Keychain.
    Child processes do NOT inherit the parent's Keychain authorization, so
Confidence
99% confidence
Finding
This function is dedicated to extracting cookies in-process specifically because that is required to decrypt browser cookies protected by macOS Keychain. Purpose-built logic to bypass normal app boundaries and read stored session credentials materially increases the risk of unauthorized account access.

Static analysis

No suspicious patterns detected.