Back to skill

Security audit

X Twitter Automataion (Search + Post)

Security checks for vulnerabilities and agentic risk

Overview

This Twitter/X skill has a coherent purpose, but it needs review because its posting helper can expose the AISA API key and can send credentials or post content to an arbitrary relay URL.

Review before installing. Use only a dedicated, revocable AISA API key, avoid sensitive searches or media unless you accept disclosure to AIsa, do not set TWITTER_RELAY_BASE_URL to untrusted or HTTP destinations, and avoid running the status/authorize/post helper until the API-key output issue is fixed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:45
Finding
Arbitrary relay URL permits API key, post content, and media disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/twitter_oauth_client.py:45-57`, `scripts/twitter_oauth_client.py:78-104`, `scripts/twitter_oauth_client.py:168-184`, `scripts/twitter_oauth_client.py:373-406` **Vulnerability Type**: Unrestricted sensitive-data destination and plaintext transport **Risk Level**: High ### Vulnerable Code ```python def normalize_base_url(base_url: str) -> str: value = base_url.strip().rstrip("/") if not value: raise RelayConfigError("TWITTER_RELAY_BASE_URL is required.") parsed = urllib.parse.urlparse(value) if parsed.scheme not in {"http", "https"} or not parsed.netloc: raise RelayConfigError("TWITTER_RELAY_BASE_URL must be a valid http(s) URL.") return value def load_config(args: argparse.Namespace) -> Dict[str, Any]: base_url = normalize_base_url( get_env("TWITTER_RELAY_BASE_URL", DEFAULT_BASE_URL) ) aisa_api_key = getattr(args, "aisa_api_key", None) or get_env("AISA_API_KEY") timeout = getattr(args, "timeout", None) or int(get_env("TWITTER_RELAY_TIMEOUT", str(DEFAULT_TIMEOUT))) if not aisa_api_key: raise RelayConfigError("AISA_API_KEY is required.") return { "base_url": base_url, "aisa_api_key": aisa_api_key, "timeout": timeout, } ``` ```python def build_auth_headers(aisa_api_key: str, extra_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]: headers = { "Authorization": f"Bearer {aisa_api_key}", "User-Agent": DEFAULT_CHROME_USER_AGENT, } if extra_headers: headers.update(extra_headers) return headers def send_json_request( url: str, payload: Dict[str, Any], timeout: int, aisa_api_key: str, ) -> Dict[str, Any]: request = urllib.request.Request( url, data=json.dumps(payload).encode("utf-8"), headers=build_auth_headers( aisa_api_key, {"Content-Type": "application/json", "Accept": "application ...[truncated 3781 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `TWITTER_RELAY_BASE_URL` if custom relay deployments are not an explicitly supported requirement. 2. Otherwise, enforce an exact allowlist of trusted HTTPS origins, including the expected hostname and port: ```python TRUSTED_RELAY_ORIGINS = { ("https", "api.aisa.one", 443), } ``` 3. Reject: - Plaintext HTTP. - Embedded URL credentials. - Unexpected ports. - IP literals and unapproved subdomains. - URL fragments or malformed origins. 4. Ensure redirects cannot move a request to a different origin or downgrade it from HTTPS to HTTP. 5. Send the API key in only one authenticated channel. Remove the redundant `aisa_api_key` request-body field if the server supports bearer authentication. 6. Add tests confirming that malicious hosts, HTTP URLs, deceptive subdomains, embedded credentials, and cross-origin redirects are rejected. 7. Document every external destination and the exact data categories transmitted to it. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:336
Finding
API key is disclosed through command output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/twitter_oauth_client.py:336-366`, `scripts/twitter_oauth_client.py:469-477`, `scripts/twitter_oauth_client.py:529-551` **Vulnerability Type**: Sensitive credential exposure through standard output **Risk Level**: High ### Vulnerable Code The publishing function includes the complete credential in successful and failed results: ```python if result.get("ok") is False or result.get("code") != 200: return { "ok": False, "aisa_api_key": config["aisa_api_key"], "is_thread": should_thread, "total_chunks": len(chunks), "failed_at_chunk": index + 1, "results": publish_results, } latest_tweet_id = extract_tweet_id(result) if not latest_tweet_id: return { "ok": False, "aisa_api_key": config["aisa_api_key"], "is_thread": should_thread, "total_chunks": len(chunks), "failed_at_chunk": index + 1, "error": "Missing tweet_id in relay response.", "results": publish_results, } previous_tweet_id = latest_tweet_id return { "ok": True, "aisa_api_key": config["aisa_api_key"], "is_thread": should_thread, "total_chunks": len(chunks), "results": publish_results, } ``` The authorization command also prints the credential: ```python auth_url = (result.get("data") or {}).get("auth_url") output = { "ok": result.get("code") == 200 and bool(auth_url), "aisa_api_key": config["aisa_api_key"], "authorization_url": auth_url, "raw_response": result, } print(json.dumps(output, indent=2, ensure_ascii=False)) ``` The `status` command exposes the credential directly: ```python def command_status(args: argparse.Namespace) -> None: config = load_config( ...[truncated 2725 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every `aisa_api_key` field from command responses and publishing result objects. 2. Change the status response to indicate only whether a key is configured: ```python "api_key_configured": bool(config.get("aisa_api_key")) ``` 3. If operator identification is necessary, show a nonreversible fingerprint or a heavily redacted value, such as the final four characters, rather than the secret. 4. Centralize output sanitization so keys, authorization headers, tokens, and cookies are redacted before serialization or logging. 5. Ensure HTTP error bodies and raw server responses are checked for reflected credentials before printing them. 6. Rotate any API key that may already have appeared in agent transcripts, terminal captures, CI logs, or monitoring systems. 7. Add automated tests that insert a sentinel secret and verify it never appears in stdout, stderr, returned result objects, or exception messages. ]]>
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill is presented as a generic Twitter/X integration, but the implementation depends on a third-party relay service and an AISA API key, which is not clearly surfaced as a privacy/security boundary in the behavior description. Users may believe queries go directly to Twitter/X when in fact all targets, search terms, and results transit an external provider.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill is presented as a generic Twitter/X integration, but the implementation depends on a third-party relay service and an AISA API key, which is not clearly surfaced as a privacy/security boundary in the behavior description. Users may believe queries go directly to Twitter/X when in fact all targets, search terms, and results transit an external provider.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The instruction to default to `--type quote` conflicts with multiple nearby rules stating relationship fields should not be used for normal standalone posts and quote mode should only be used when explicitly requested. In a posting skill, this can cause unintended inclusion of quote-post semantics, misroute user content, or attach content to external tweets in ways the user did not authorize, increasing the risk of integrity and privacy-impacting misposts.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README explicitly promotes capabilities to write and post text and media to Twitter/X, but it does not clearly warn users that these actions cause real external side effects on a public platform and can affect the user's account, reputation, or data. In an autonomous agent context, omission of a prominent warning increases the risk of unintended posting, especially when users may assume the skill is informational rather than account-affecting.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares environment and network capabilities through metadata and documented curl/Python usage, but does not explicitly constrain tool scope with permissions or allowed-tools. In an agent setting, missing capability boundaries can cause the skill to be invoked with broader execution than users expect, increasing the chance of unintended outbound requests or secret access.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The invocation guidance is broad enough that the skill may activate for many ordinary Twitter-related requests without clear boundaries, potentially sending user prompts, search terms, handles, or monitoring targets to an external API service automatically. In agent environments, over-broad routing increases the risk of unintended external disclosure and action selection.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill does not clearly warn that user-supplied search terms, usernames, community IDs, tweet IDs, and other query targets are transmitted to a third-party API. This creates a real privacy risk because users may share sensitive monitoring topics, internal product names, or investigative targets under the assumption the request stays local or goes directly to Twitter/X.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Get user info
curl "https://api.aisa.one/apis/v1/twitter/user/info?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user profile about (account country, verification, username changes)
Confidence
90% confidence
Finding
This endpoint sends usernames and an authorization bearer token to an external service. External transmission is expected for this skill, but it is still a security-relevant behavior because it exposes user queries and account targets to a third party and depends on proper handling of the API key.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user profile about (account country, verification, username changes)
curl "https://api.aisa.one/apis/v1/twitter/user_about?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Batch get user info by IDs
Confidence
90% confidence
Finding
This call transmits account lookup parameters and a bearer token to api.aisa.one. While aligned with the skill’s purpose, it still creates privacy and secret-handling risk because the request contents and authentication material leave the local environment.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Batch get user info by IDs
curl "https://api.aisa.one/apis/v1/twitter/user/batch_info_by_ids?userIds=44196397,123456" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user's latest tweets
Confidence
90% confidence
Finding
Batch user lookup sends multiple target identifiers and the authorization token to an external relay. This can reveal monitoring targets or relationship mapping at scale, increasing privacy sensitivity compared with a single lookup.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user's latest tweets
curl "https://api.aisa.one/apis/v1/twitter/user/last_tweets?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user mentions
Confidence
90% confidence
Finding
Fetching recent tweets requires outbound transmission of the target username and bearer token to the third-party API. This is expected functionality but remains a meaningful external data-sharing path that should be treated as security-relevant.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user mentions
curl "https://api.aisa.one/apis/v1/twitter/user/mentions?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user followers
Confidence
90% confidence
Finding
User mention lookups send monitored account identifiers to a third party and could reveal whom the operator is tracking. The security issue is not the request itself, but the lack of clear privacy boundaries around this external transmission.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user followers
curl "https://api.aisa.one/apis/v1/twitter/user/followers?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user followings
Confidence
90% confidence
Finding
Follower queries expose the target handle and use an external authenticated service. Such social graph queries can be sensitive in investigative, corporate, or personal contexts and should not be treated as risk-free background traffic.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user followings
curl "https://api.aisa.one/apis/v1/twitter/user/followings?userName=elonmusk" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get user verified followers (requires user_id, not userName)
Confidence
90% confidence
Finding
Following-list queries reveal interests and relationships of the queried account to an external provider, along with the bearer token. This is a legitimate feature, but it still presents privacy and credential-handling risk.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get user verified followers (requires user_id, not userName)
curl "https://api.aisa.one/apis/v1/twitter/user/verifiedFollowers?user_id=44196397" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Check follow relationship between two users
Confidence
90% confidence
Finding
Verified-follower lookup sends a user ID and authentication token to the external API. Relationship and audience data can be sensitive, especially when used for profiling or monitoring, so the transmission should be treated as a real security concern.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Check follow relationship between two users
curl "https://api.aisa.one/apis/v1/twitter/user/check_follow_relationship?source_user_name=elonmusk&target_user_name=BillGates" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Search users by keyword
Confidence
91% confidence
Finding
Checking follow relationships between two users reveals an explicit association query to the third-party service. In some contexts this can disclose investigative interest, business intelligence activity, or personal relationship analysis.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Search users by keyword
curl "https://api.aisa.one/apis/v1/twitter/user/search?query=AI+researcher" \
  -H "Authorization: Bearer $AISA_API_KEY"
```
Confidence
91% confidence
Finding
User search transmits arbitrary user-provided search terms to an external API, which may include confidential projects, names, or internal topics. The risk is heightened because free-form queries are more likely to contain sensitive material than fixed identifiers.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Advanced tweet search (queryType is required: Latest or Top)
curl "https://api.aisa.one/apis/v1/twitter/tweet/advanced_search?query=AI+agents&queryType=Latest" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Search top tweets
Confidence
92% confidence
Finding
Advanced tweet search sends arbitrary free-text queries and credentials to api.aisa.one. This is a true privacy/security concern because search strings can encode confidential strategy, investigations, or personal interests, and all of that is exposed to a third-party processor.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Search top tweets
curl "https://api.aisa.one/apis/v1/twitter/tweet/advanced_search?query=AI+agents&queryType=Top" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get tweets by IDs (comma-separated)
Confidence
92% confidence
Finding
Top-tweet search has the same external-transmission risk as other free-text search operations: user intent and potentially sensitive query terms are sent to a third party along with authentication. The functionality is expected, but the privacy boundary is not sufficiently emphasized.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get tweets by IDs (comma-separated)
curl "https://api.aisa.one/apis/v1/twitter/tweets?tweet_ids=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get tweet replies
Confidence
88% confidence
Finding
Tweet ID lookups transmit target identifiers and the bearer token externally. Even identifier-based lookups can reveal what content a user is investigating, especially when performed repeatedly or in bulk.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get tweet replies
curl "https://api.aisa.one/apis/v1/twitter/tweet/replies?tweetId=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get tweet quotes
Confidence
89% confidence
Finding
Reply retrieval sends a target tweet ID and credentials to the external API, disclosing interest in a specific conversation. While normal for the skill, it is still a genuine external data-sharing path with privacy implications.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get tweet quotes
curl "https://api.aisa.one/apis/v1/twitter/tweet/quotes?tweetId=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get tweet retweeters
Confidence
89% confidence
Finding
Quote-tweet retrieval exposes the investigated tweet ID and authorization token to the external provider. This can reveal targeted monitoring of particular narratives or posts.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get tweet retweeters
curl "https://api.aisa.one/apis/v1/twitter/tweet/retweeters?tweetId=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get tweet thread context (full conversation thread)
Confidence
89% confidence
Finding
Retweeter lookup transmits an interaction-analysis request to a third party, potentially revealing social amplification analysis or investigative targeting. The risk is contextual but real in enterprise or investigative settings.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get tweet thread context (full conversation thread)
curl "https://api.aisa.one/apis/v1/twitter/tweet/thread_context?tweetId=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"

# Get article by tweet ID
Confidence
89% confidence
Finding
Thread-context retrieval sends a conversation target externally, which may disclose what discourse or controversy the operator is examining. The external relay model makes this more sensitive than a direct local-only operation.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: Bearer $AISA_API_KEY"

# Get article by tweet ID
curl "https://api.aisa.one/apis/v1/twitter/article?tweet_id=1895096451033985024" \
  -H "Authorization: Bearer $AISA_API_KEY"
```
Confidence
88% confidence
Finding
Article-by-tweet lookup still transmits the target tweet ID and bearer token externally. This is expected behavior, but it remains a genuine privacy and dependency risk tied to a third-party processor.

Static analysis

No suspicious patterns detected.