Back to skill

Security audit

AIsa Twitter

Security checks for vulnerabilities and agentic risk

Overview

This Twitter/X skill is mostly purpose-aligned, but it exposes the AIsa API key in normal command output and has loosely scoped local media upload behavior.

Install only if you trust AIsa with your Twitter/X research queries, tweet content, IDs, and uploaded media. Avoid using a valuable production AISA_API_KEY until the skill stops printing the raw key, and only pass media files that you explicitly intend to upload.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:335
Finding

Plaintext AIsa API Key Disclosed Through Command Output

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/twitter_oauth_client.py:415
Finding

Arbitrary Process-Readable Local Files Can Be Uploaded as Media

Content
View full analysis
list[Dict[str, Any]]: if not paths: return [] media_files: list[Dict[str, Any]] = [] media_kinds: set[str] = set() seen_paths: set[str] = set() for raw_path in paths: resolved_path = os.path.abspath(os.path.expanduser(raw_path)) normalized_path = os.path.normcase(resolved_path) if normalized_path in seen_paths: continue seen_paths.add(normalized_path) if not os.path.exists(resolved_path): raise RelayConfigError(f"Media file does not exist: {raw_path}") if not os.path.isfile(resolved_path): raise RelayConfigError(f"Media path is not a file: {raw_path}") mime_type = mimetypes.guess_type(resolved_path)[0] or "application/octet-stream" media_kind = mime_type.split("/", 1)[0] if media_kind not in {"image", "video"}: raise RelayConfigError( f"Unsupported media type for {raw_path}: {mime_type}. Only image and video files are supported." ) media_kinds.add(media_kind) with open(resolved_path, "rb") as file_handle: content = file_handle.read() ``` The loaded bytes are subsequently transmitted to the AIsa endpoint: ```python media_files = load_media_files(getattr(args, "media_file", None)) ``` ```python return send_multipart_request( endpoint, payload, media_files, timeout=config["timeout"], aisa_api_key=config["aisa_api_key"], ) ``` ### Technical Analysis The documented guardrail states that only local files explicitly attached by the user should be uploaded. The implementation does not technically enforce that restriction. The `--media-file` option accepts ...[truncated 2226 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code accurately supports Twitter/X research and discovery features such as search, trends, user lookup, tweet details, list/community/space reads, and relationship/follower inspection. However, it is explicitly read-only: the module docstring says 'Twitter/X read APIs', the request helper only sends POST generically but no posting methods are implemented, and there are no endpoints for composing/publishing tweets or any OAuth authorization flow beyond using a static AISA_API_KEY bearer token. The declared description materially overstates capabilities by claiming OAuth-gated posting and approved posting workflows, and by implying watchlists/monitoring support that is not implemented beyond reading existing Twitter lists and related data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is narrowly focused on Twitter OAuth authorization and publishing through AIsa. It exposes only three commands: authorize, post, and status, and only calls two Twitter-related AIsa endpoints: /twitter/auth_twitter and /twitter/post_twitter. It includes tweet-length calculation, splitting long text into chunks, quote/reply handling, and multipart media upload for images/videos. There is no code for Twitter/X research, search, trend tracking, competitor monitoring, or watchlists. Since the declared description presents a broader all-in-one Twitter skill centered on research/monitoring/watchlists plus posting, while the supplied code only implements OAuth-gated posting support, the description materially overstates the actual behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script includes the raw AIsa API key in command outputs, including status and posting-related results. Exposing credentials in stdout is dangerous because terminal logs, shell history capture, CI logs, agent transcripts, or downstream tooling may retain and leak the key, enabling unauthorized use of the AIsa account and any Twitter posting capability behind it.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The authorize flow prints a JSON object containing the raw AIsa API key along with the authorization URL and raw response. This unnecessarily discloses a bearer credential during a sensitive OAuth-related workflow, increasing the chance of credential theft through console capture, logs, or agent output replay.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares access to environment secrets and a fixed external network target but does not define an explicit tool scope such as permissions or allowed-tools. That creates ambiguity for runtime policy enforcement and increases the chance the skill is granted broader capabilities than users or hosts expect, especially since it handles an API key and can transmit user content externally.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/post_twitter.md (reported line 86)May include surrounding context.

md
## Guardrails

- Do not ask the user for their Twitter password.
- Do not use cookie-based login or proxy-based login unless the user explicitly asks for legacy behavior.
- Do not default to `--open-browser`; return the authorization link unless the user explicitly wants local browser launch.
- Do not invent remote URLs for attachments; always use the provided local workspace file path with `--media-file`.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring says this is for 'Twitter/X read APIs' and specifically describes read operations using GET. However, the shared _request method explicitly supports POST bodies, which enables write-style API calls if additional endpoints are added or invoked through this helper. That exceeds the behavior implied by the file-level description of a read-only client.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The client sends user-provided queries, usernames, tweet IDs, and related identifiers to the third-party service at api.aisa.one without any explicit consent, minimization, or warning boundary in the tool itself. In an agent setting, this can cause unintentional disclosure of sensitive research targets, internal watchlists, or investigator interests to the external provider.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The CLI description states 'Twitter/X read APIs,' reinforcing a read-only intent, while the underlying _request implementation conditionally serializes request bodies for POST requests. This is not merely incomplete documentation; it directly conflicts with the stated read-only characterization of the client.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 68)May include surrounding context.

md
DEFAULT_TIMEOUT = 30
DEFAULT_BASE_URL = "https://api.aisa.one/apis/v1"
DEFAULT_CHROME_USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/twitter_client.py (reported line 35)May include surrounding context.

python
DEFAULT_TIMEOUT = 30
DEFAULT_BASE_URL = "https://api.aisa.one/apis/v1"
DEFAULT_CHROME_USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/twitter_oauth_client.py (reported line 29)May include surrounding context.

python
DEFAULT_TIMEOUT = 30
DEFAULT_BASE_URL = "https://api.aisa.one/apis/v1"
DEFAULT_CHROME_USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The post flow sends user-provided tweet text, media IDs, and optionally local media files to the AIsa service via HTTP requests, but the code does not provide a user-facing disclosure at execution time about this outbound transmission. Although posting is the stated purpose, the code lacks an explicit warning that local media files and content are sent to a third-party endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The configuration loader reads a credential from the environment and uses it for authorization, but this file provides no user-facing note, comment, or warning that the skill depends on sensitive credentials. Under the rule, access to credentials should include some disclosure unless already clearly documented elsewhere.

Content

No source excerpt is available for this finding.