Back to skill

Security audit

X Twitter Command Center (Search + Post)

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims for Twitter/X reading and posting, but it exposes the AIsa API key in command output and can send that key to an arbitrary configured relay endpoint.

Review this carefully before installing. Use it only with a scoped, disposable AIsa key, avoid custom TWITTER_RELAY_BASE_URL values, rotate the key if command output has been logged, and require explicit approval of exact post text/media before letting an agent publish to a real Twitter/X account.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:338
Finding
API Key Disclosed in Command Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/twitter_oauth_client.py:338-354`, `scripts/twitter_oauth_client.py:470-475`, and `scripts/twitter_oauth_client.py:539-543` **Vulnerability Type**: Sensitive credential exposure through standard output **Risk Level**: High ### Vulnerable Code ```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, } ``` ```python 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)) ``` ```python response = { "ok": True, "relay_base_url": config["base_url"], "aisa_api_key": config["aisa_api_key"], "timeout": config["timeout"], "supported_commands": ["authorize", "post", "status"], "supported_endpoints": ["/twitter/auth_twitter", "/twitter/post_twitter"], ``` ### Technical Analysis The `authorize`, `post`, and `status` workflows include the complete `AISA_API_KEY` in objects serialized to standard output. This is unnecessary for authorization, publishing, status reporting, or error handling. Standard output from an agent skill may be retained in agent transcripts, CI logs, terminal captures, observability platforms, support bundles, or downstream automation. Consequently, a secret initially protected as an environment ...[truncated 1345 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `aisa_api_key` from every command response, success result, and error object. 2. Ensure that `status` reports only whether the credential is configured, for example: ```python "api_key_configured": bool(config.get("aisa_api_key")) ``` 3. If an identifier is operationally necessary, expose only a non-secret server-generated credential ID. Do not print any recoverable portion of the key. 4. Add automated tests asserting that command output never contains the configured key. 5. Apply centralized output redaction before serializing error objects. 6. Review agent transcripts, CI logs, and monitoring records for previous exposure, delete retained copies where possible, and rotate any key that may have been logged. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:43
Finding
Arbitrary Plaintext Relay Endpoint Can Receive API Credentials and User Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/twitter_oauth_client.py:43-104` **Vulnerability Type**: Unrestricted credential destination and plaintext sensitive-data transmission **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/json"}, ), method="POST", ) try: with urllib.request.urlopen(request, timeout= ...[truncated 2740 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS for all relay endpoints: ```python if parsed.scheme != "https": raise RelayConfigError("The relay URL must use HTTPS.") ``` 2. Restrict the production destination to an explicit allowlist, preferably only `api.aisa.one`. 3. Remove or disable `TWITTER_RELAY_BASE_URL` in production builds. If custom endpoints are required for development, require an explicit development-only flag and display a prominent warning. 4. Reject URLs containing user information, unexpected ports, fragments, or ambiguous hostnames. 5. Send the credential only through the `Authorization` header unless the server protocol strictly requires body duplication. Update the server contract to eliminate body transmission. 6. Ensure TLS certificate verification remains enabled and do not add certificate-bypass behavior. 7. Apply egress controls at the runtime level so the Skill can contact only documented service hosts. 8. Add tests confirming rejection of HTTP URLs and unapproved domains. 9. Rotate a credential if the Skill has ever been run with an untrusted or plaintext relay endpoint. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/twitter_oauth_client.py:466
Finding
Unvalidated Relay-Supplied Authorization URL Is Opened in the Browser<![CDATA[ ## Vulnerability Details **File Location**: `scripts/twitter_oauth_client.py:466-480` **Vulnerability Type**: Untrusted URL handling and browser navigation **Risk Level**: Medium ### Vulnerable Code ```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)) if output["ok"] and args.open_browser: webbrowser.open(auth_url) if not output["ok"]: sys.exit(1) ``` ### Technical Analysis The authorization URL is accepted directly from the relay response and passed to `webbrowser.open()` without validating its scheme, hostname, port, or expected OAuth path. A response code of 200 and a nonempty value are the only conditions required. A compromised, impersonated, or custom relay can therefore control the browser destination. This issue is more readily exploitable because the client separately permits arbitrary relay hosts through `TWITTER_RELAY_BASE_URL`. The most direct risk is OAuth phishing: an attacker can return a page that imitates Twitter/X or AIsa authorization and attempts to collect credentials or authorization information. Depending on local browser and operating-system URL-handler configuration, non-HTTPS custom schemes may also invoke registered applications. ### Attack Path 1. An attacker controls the configured relay, compromises the legitimate relay response, or causes the client to use an attacker-controlled `TWITTER_RELAY_BASE_URL`. 2. The user runs: ```bash python3 scripts/twitter_oauth_client.py authorize --open-browser ``` 3. The malicious relay returns a successful response containing an attacker-selected `auth_url`. 4. The client treats any nonempty URL as valid and passes it to `webbrowser.open()`. 5. The browser navigates to the attacker's page or invokes the relevant local UR ...[truncated 626 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse `auth_url` before displaying or opening it. 2. Require the `https` scheme. 3. Maintain an explicit allowlist of legitimate AIsa and Twitter/X OAuth hostnames. 4. Reject URLs containing embedded user information, unexpected ports, malformed hostnames, or unapproved redirect domains. 5. Validate that the URL path matches an expected authorization endpoint where the provider contract permits this. 6. Prefer displaying the validated URL and requiring deliberate user confirmation before opening it. 7. Bind authorization initiation and completion with an unpredictable OAuth `state` value and verify it server-side to prevent flow substitution. 8. Add tests using malicious values such as `file:`, custom application schemes, HTTP URLs, lookalike domains, and URLs with user-information hostname confusion. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code substantially matches the declared read/search portions: it supports user profiles/about info, timelines, mentions, followers/followings, tweet search, trends, lists, communities, and Spaces. However, the description also claims the skill can publish posts after the user completes OAuth in the browser. In the supplied code, there is no posting endpoint, no write operation, no OAuth flow, and no browser-based authentication despite importing webbrowser. Authentication is only via an AISA_API_KEY bearer token. Therefore the description overstates important write/auth capabilities that are not present in this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The description says this skill both reads/searches extensive Twitter/X data and publishes posts after OAuth. The supplied code only supports three commands: authorize, post, and status. The network endpoints used are /twitter/auth_twitter and /twitter/post_twitter; there are no endpoints or functions for fetching profiles, timelines, mentions, followers, searches, trends, lists, communities, or Spaces. The posting functionality is indeed present, including browser OAuth initiation, media uploads, quote/reply posting, and automatic splitting into threaded chunks. However, the major declared read/search functionality is not represented in this code chunk, making the description materially broader than the actual behavior.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README promotes the ability to write and post to Twitter/X, including media and threads, but does not clearly warn that these actions can publish publicly under the user's own account once OAuth is completed. In an autonomous agent context, this omission is risky because users may not fully appreciate that a natural-language request can trigger irreversible public actions, increasing the chance of accidental or unwanted posting.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill requires environment access to `AISA_API_KEY` and makes outbound network requests, but it does not declare an explicit tool scope such as `permissions` or `allowed-tools`. That omission weakens policy enforcement and makes it harder for a host to constrain what the skill is allowed to access, increasing the chance of unintended secret use or network egress.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
Conflicting statements about whether the skill can post to Twitter/X create ambiguity around real-world side effects. In agent contexts, ambiguity about write actions is dangerous because users and orchestrators may treat the skill as informational while it can initiate publishing workflows through referenced materials.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest markets the skill as 'Search + Post,' but the body explicitly states that publishing logic is not defined in this file and is handled elsewhere. This split can conceal where account-affecting actions occur, reducing reviewability and increasing the risk that users or hosts enable a skill with write capabilities they have not fully audited.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill description mentions publishing to a real Twitter/X account after OAuth but does not provide an explicit warning about account-affecting actions. In an autonomous-agent setting, omission of a clear warning increases the chance of unintended posts, replies, or reputation damage if the skill is invoked without strong user awareness.

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
88% confidence
Finding
This endpoint sends requests and the bearer API key to an external third-party service. External transmission is expected for this skill's purpose, but it still creates a real data-exposure surface because user queries, targeted account data, and credentials are sent off-platform.

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
88% confidence
Finding
This example transmits requests plus the `Authorization: Bearer $AISA_API_KEY` header to an external API. While functionally necessary, such transmission is security-relevant because misuse, overbroad permissions, or accidental logging could expose the secret or sensitive user activity.

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
88% confidence
Finding
The skill documents sending account identifiers and an authorization token to a third-party endpoint. Because the skill is intended for social intelligence, this transmission may include sensitive relationship or monitoring targets, making third-party handling and retention a meaningful risk.

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
88% confidence
Finding
This call externally transmits the requested username and bearer credential. Even for public Twitter data, the query itself can reveal user interests, monitoring targets, or business intelligence activity, so the network egress is a true exposure point.

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
88% confidence
Finding
The documented API usage sends monitoring requests and credentials to an external service. This is inherent to the skill design, but still expands the trust boundary and could expose sensitive watchlists or operator intent if the service or logs are compromised.

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
88% confidence
Finding
Requests for followers data are sent to a third-party API along with the API key. That creates a moderate confidentiality risk because relationship analysis and tracked accounts may be sensitive in enterprise or investigative contexts.

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
88% confidence
Finding
This endpoint call similarly exports query parameters and authorization material to AIsa. The skill context makes this expected, but not harmless: an agent using it may disclose business-sensitive research patterns to the external provider.

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
88% confidence
Finding
Verified-follower lookups transmit user IDs and API credentials off-platform. The behavior is consistent with the skill's purpose, yet it still constitutes a real external transmission risk because the service can observe who is being analyzed and when.

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
88% confidence
Finding
Checking follow relationships sends both source and target usernames plus the bearer token to the external API. Those relationship queries can be sensitive intelligence in some contexts, so this is a valid data egress concern rather than a false positive.

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
88% confidence
Finding
User-search requests transmit search terms and the API key to a third-party service. Search terms may encode confidential topics, making the external transmission moderately risky despite being necessary for function.

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
88% confidence
Finding
Advanced tweet-search requests send potentially sensitive search queries and credentials externally. In a social-listening use case, those queries can reveal product strategy, investigations, or reputational concerns, so the egress is security-relevant.

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
88% confidence
Finding
Top-search requests have the same exposure pattern: query terms and a bearer token are transmitted to a third-party service. The skill context makes this common, but it still increases confidentiality risk for the operator's research intent.

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 send identifiers and credentials to an external API. Even if tweet content is public, the set of IDs queried can expose what content the operator is investigating or tracking.

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
88% confidence
Finding
Reply-thread requests transmit the target tweet ID and authorization token to the third-party provider. This is expected functionality, but still represents a real trust-boundary crossing with potential exposure of analyst interests and secret material.

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
88% confidence
Finding
Quote-tweet lookups send request metadata and a bearer secret to an external provider. Because the skill is aimed at monitoring and intelligence gathering, these lookups may reveal sensitive internal priorities or investigations.

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
88% confidence
Finding
Retweeter lookups similarly involve external transmission of identifiers and credentials. The data requested may be public, but the analysis targets and frequency of access can still be sensitive operational metadata.

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
88% confidence
Finding
Thread-context retrieval sends tweet identifiers and credentials outside the local environment. This widens the trust boundary and can leak what conversations an analyst is examining, which matters in enterprise or investigative settings.

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 lookups require third-party egress with the bearer token. That is operationally normal here, but it remains a moderate risk because external providers can observe access patterns and any mishandling of secrets would compromise the integration.

Static analysis

No suspicious patterns detected.