Back to skill

Security audit

Twitter Query

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent read-only Twitter/X query helper, but it can send the user’s API key to an arbitrary API base set in the environment.

Review before installing. Use this only with a trusted environment, leave `TWITTER_API_BASE` unset or set it exactly to `https://api.twitterapi.io`, and prefer a pinned installer command if available. Treat search terms, usernames, and the API key as data that leaves your machine for the external API service.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/query_by_user.py:103
Finding

Configurable API Base Can Exfiltrate the API Key in User Timeline Queries

Content
View full analysis

Vulnerability Details

File Location: scripts/query_by_user.py:22-29, 103-119
Vulnerability Type: Unrestricted credential destination and potentially plaintext credential transmission
Risk Level: Medium

Vulnerable Code

python
def _request(url: str, api_key: str) -> dict:
    req = urllib.request.Request(
        url,
        headers={
            "X-API-Key": api_key,
            "User-Agent": "twitter-query-skill/1.0",
        },
        method="GET",
    )
python
api_key = os.environ.get("TWITTER_API_KEY", "").strip()
if not api_key:
    print("Missing TWITTER_API_KEY", file=sys.stderr)
    sys.exit(1)

base = os.environ.get("TWITTER_API_BASE", DEFAULT_BASE).rstrip("/")
user = args.userName.lstrip("@")

all_raw: list[dict] = []
cursor = ""
pages = 0
meta_pages: list[dict] = []

while pages < args.max_pages:
    q = urllib.parse.urlencode(
        {
            "userName": user,
            "cursor": cursor,
            "includeReplies": "true" if args.include_replies else "false",
        }
    )
    url = f"{base}/twitter/user/last_tweets?{q}"
    data = _request(url, api_key)

Technical Analysis

The script accepts TWITTER_API_BASE from the process environment without validating its URL scheme, hostname, port, or user-information component. It then attaches the sensitive TWITTER_API_KEY value to the resulting request as an X-API-Key header.

Consequently, an environment value such as https://attacker.example causes the credential to be sent directly to an attacker-controlled server. An http:// endpoint can expose the credential and requested username to passive or active network attackers. Redirect behavior is delegated to urllib.request.urlopen without an explicit same-origin policy, creating an additional area where credential forwarding behavior should be hardened and tested.

This behavior exceeds the disclosed destina ...[truncated 1455 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove TWITTER_API_BASE configurability if custom endpoints are not essential and always use https://api.twitterapi.io.
  2. If custom endpoints are required, parse the URL with urllib.parse.urlsplit and enforce:
    • The https scheme.
    • An explicit allowlist of trusted hostnames.
    • No embedded username or password.
    • Only approved ports, normally port 443.
    • No fragments or other unexpected URL components.
  3. Do not attach X-API-Key until the final request destination has passed validation.
  4. Implement a redirect handler that rejects redirects or permits only same-origin HTTPS redirects to approved hosts.
  5. Fail closed when the URL is malformed or outside the allowlist.
  6. Update documentation and privacy metadata so that the declared destination rules exactly match implementation behavior.
  7. Add tests confirming rejection of http://, look-alike domains, embedded credentials, unexpected ports, and cross-origin redirects.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/query_by_keyword.py:102
Finding

Configurable API Base Can Exfiltrate the API Key in Keyword Searches

Content
View full analysis

Vulnerability Details

File Location: scripts/query_by_keyword.py:22-29, 102-118
Vulnerability Type: Unrestricted credential destination and potentially plaintext credential transmission
Risk Level: Medium

Vulnerable Code

python
def _request(url: str, api_key: str) -> dict:
    req = urllib.request.Request(
        url,
        headers={
            "X-API-Key": api_key,
            "User-Agent": "twitter-query-skill/1.0",
        },
        method="GET",
    )
python
api_key = os.environ.get("TWITTER_API_KEY", "").strip()
if not api_key:
    print("Missing TWITTER_API_KEY", file=sys.stderr)
    sys.exit(1)

base = os.environ.get("TWITTER_API_BASE", DEFAULT_BASE).rstrip("/")

all_raw: list[dict] = []
cursor = ""
pages = 0
meta_pages: list[dict] = []

while pages < args.max_pages:
    q = urllib.parse.urlencode(
        {
            "query": args.query,
            "queryType": args.query_type,
            "cursor": cursor,
        }
    )
    url = f"{base}/twitter/tweet/advanced_search?{q}"
    data = _request(url, api_key)

Technical Analysis

The keyword-search implementation trusts the environment-controlled TWITTER_API_BASE value and sends the API key to the constructed destination. There is no enforcement that the destination is api.twitterapi.io, no HTTPS requirement, and no explicit control over cross-origin redirects.

In addition to the API credential, advanced search expressions are placed in the URL query string. These expressions may reveal sensitive research topics, account names, hashtags, cashtags, dates, or other user interests. Although transmitting searches to TwitterAPI.io is necessary for the declared functionality, transmitting them and the credential to an unrestricted destination is not.

The implementation therefore conflicts with the project disclosure that the API key is sent only to TwitterAPI.io.

Att

...[truncated 1071 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use the fixed https://api.twitterapi.io base unless endpoint customization is a documented functional requirement.
  2. If customization must remain, enforce HTTPS and an explicit destination-host allowlist before constructing the request.
  3. Reject embedded credentials, nonstandard ports, malformed URLs, IP-literal alternatives, and unapproved domains.
  4. Disable redirects or validate every redirect target before forwarding any sensitive header.
  5. Add the API key only after the final destination is verified.
  6. Consider minimizing URL exposure in diagnostics and avoid logging complete search URLs.
  7. Add automated negative tests for attacker-controlled hosts, plaintext HTTP destinations, hostname confusion, and cross-origin redirects.

T08 · Insecure Dependencies

Note
Location
SKILL.md:22
Finding

Documented Installation Uses an Unpinned Third-Party npm CLI

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:22-26, README.md:28-32, PUBLISH.md:43-47
Vulnerability Type: Unpinned executable dependency in the installation procedure
Risk Level: Low

Vulnerable Code

SKILL.md:

bash
npx skills add alexander10011/twitter-query

README.md:

bash
npx skills add alexander10011/twitter-query

PUBLISH.md:

bash
npx skills add <owner>/twitter-query
export TWITTER_API_KEY="..."
python3 scripts/query_by_user.py elonmusk --max-pages 1

Technical Analysis

The installation instructions invoke the skills npm package through npx without specifying a reviewed package version or integrity value. Depending on local npm state and npx behavior, this can download and execute the current package release from the configured npm registry.

The effective installer can therefore change independently of the audited Skill repository. If the package, publisher account, registry resolution, or user registry configuration is compromised, the command may execute code that was not included in this audit.

This is a supply-chain hardening issue rather than evidence that the current skills package is malicious.

Attack Path

  1. A user follows the documented installation command.
  2. npx resolves an unpinned release of the skills package through the user’s configured npm registry.
  3. The resolved package has changed since the Skill audit, or its publisher account, distribution channel, or registry path has been compromised.
  4. npx downloads and executes that package.
  5. Malicious package lifecycle or CLI code runs with the privileges of the installing user.

Impact Assessment

A compromised executable dependency could run arbitrary code with the current user’s permissions. Depending on the user’s environment, this could expose accessible files and environment variables, modify user-owned configuration, install additiona ...[truncated 191 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the installer to a reviewed version, for example by documenting npx skills@<reviewed-version> ....
  2. Verify and document the expected npm publisher, registry, and package provenance.
  3. Use package-lock or integrity verification where the installation workflow supports it.
  4. Prefer an installation mechanism that can verify signed or checksummed artifacts.
  5. Review new installer versions before updating the documented pin.
  6. Warn users not to approve execution when npm resolves an unexpected package, publisher, registry, or version.
  7. Keep the same pinned and verified command consistent across SKILL.md, README.md, and PUBLISH.md.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file contains end-user/maintainer instructions exclusively in Chinese, and it does not provide an opt-in, alternative language, or justification that the skill is intended only for a Chinese-speaking audience. That can violate a language/locale policy requiring neutral language support or explicit user choice.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The README instructs users to run npx skills add alexander10011/twitter-query without pinning the package or tool version. This can cause users to execute a newer or compromised version of the skills package than the maintainer tested, creating a supply-chain risk during installation. In this skill context, the risk is somewhat elevated because installation commands are copied directly from documentation and executed locally.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents use of environment secrets and outbound network access, but does not declare any explicit tool scope or permissions boundary. In skill ecosystems that rely on manifest-declared capabilities, this weakens reviewability and can allow broader-than-expected execution behavior or secret exposure if the skill is invoked automatically.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Most of the visible user-facing documentation and operational guidance is written in Chinese, and the skill does not state that this locale choice is optional or region-specific. Under the policy, imposing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation explains the API mechanics but does not clearly warn users that their search terms, handles, and related query data are sent to a third-party service (twitterapi.io). This can lead to privacy and data-handling surprises, especially if users submit sensitive topics, internal account names, or investigative queries assuming local-only processing.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

The installation instruction uses npx skills without a pinned version, which creates a supply-chain risk because the fetched package may change over time or be replaced by a malicious publication. Users following the docs could execute unintended code during installation before they inspect the skill contents.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file is primarily written in English, but L60 switches to Chinese for release instructions without indicating that the user can choose a language or that the content is region-specific. This can violate a language/locale policy requiring user-facing documentation to avoid forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest says to use the skill when the user asks for tweets from a handle, a user timeline, or keyword/hashtag/cashtag search, but it does not define explicit trigger phrases, exclusions, or boundaries. This broad natural-language scope could cause unintended invocation for general Twitter-related requests that are not specifically asking to run this skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code sends the provided search query to a remote third-party API and includes the TWITTER_API_KEY in the request headers. Although network access is central to the script's purpose, there is no visible runtime disclosure, confirmation, or warning that user-supplied query content will be transmitted externally.

Content

No source excerpt is available for this finding.