Back to skill

Security audit

AIsa Twitter Research Engage Relay

Security checks for vulnerabilities and agentic risk

Overview

The skill’s Twitter/X posting and engagement purpose is mostly disclosed, but it exposes the AIsa API key in command output and allows media uploads from arbitrary readable local paths.

Install only if you are comfortable giving this skill an AIsa API key that can drive Twitter/X account actions. Avoid using it in environments where command output is logged until the raw API-key output is fixed, and only pass media files you intentionally selected from a safe workspace path.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/twitter_oauth_client.py:334
Finding

AISA API Key Exposed in Command Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/twitter_oauth_client.py:78
Finding

API Key Redundantly Transmitted in Both Authorization Headers and Request Bodies

Content
View full analysis
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", ) ``` Posting also inserts the same key into the request body: ```python payload: Dict[str, Any] = { "aisa_api_key": config["aisa_api_key"], } if content: payload["content"] = content if post_type: payload["type"] = post_type if media_ids: payload["media_ids"] = media_ids if parent_tweet_id: parent_key = "in_reply_to_tweet_id" if post_type == "reply" else "quote_tweet_id" payload[parent_key] = parent_tweet_id endpoint = f"{config['base_url']}/twitter/post_twitter" if media_files: return send_multipart_request( endpoint, payload, media_files, timeout=config["timeout"], aisa_api_key=config["aisa_api_key"], ) return send_json_request( endpoint, payload, timeout=config["timeout"], ...[truncated 2863 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/twitter_oauth_client.py:412
Finding

Media Upload Can Read Arbitrary Local Paths Without Workspace or Size Restrictions

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() media_files.append( { "field_name": "media_files", "filename": os.path.basename(resolved_path), "content_type": mime_type, "content": content, } ) if len(media_kinds) > 1: raise RelayConfigError("Do not mix image and video files in a single post request.") return media_files ``` ### Technical Analysis The documented guardrail states that only local files explicitly attached by the user should be uploaded. The imple ...[truncated 2583 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 (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the implementation performs media upload and threaded posting while the skill description emphasizes reads, likes, follows, replies, and approved posting, the mismatch can conceal higher-risk content transmission and publication behavior. In a social-media skill, undocumented posting or upload features are materially more dangerous because they can expose local files or publish content under the user's identity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the implementation performs media upload and threaded posting while the skill description emphasizes reads, likes, follows, replies, and approved posting, the mismatch can conceal higher-risk content transmission and publication behavior. In a social-media skill, undocumented posting or upload features are materially more dangerous because they can expose local files or publish content under the user's identity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the implementation performs media upload and threaded posting while the skill description emphasizes reads, likes, follows, replies, and approved posting, the mismatch can conceal higher-risk content transmission and publication behavior. In a social-media skill, undocumented posting or upload features are materially more dangerous because they can expose local files or publish content under the user's identity.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script prints the raw AIsa API key in multiple command outputs, including status, authorize, and publish results. This unnecessarily exposes a bearer credential to terminals, logs, shell history capture, CI output, or calling tools, enabling unauthorized use of the AIsa account if observed or collected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises likes, follows, replies, and OAuth-gated posting but does not warn that the skill can perform account-affecting actions or transmit user-authorized data to an external platform. In an agent setting, missing disclosure increases the risk of unintended social actions, reputation damage, or accidental use of privileged credentials because operators may treat the skill as informational rather than action-capable.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares access to an API key and directs use of network-capable scripts, but it does not define an explicit tool scope such as allowed-tools or permissions. In an agent environment, that omission weakens least-privilege controls and can allow broader-than-expected execution or data egress paths during use of the skill.

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/engage_twitter.md (reported line 27)May include surrounding context.

md
When the user asks to like, unlike, follow, or unfollow on X/Twitter:

1. Do not ask the user to manually paste tweet links or IDs.
2. If the user first asked to query tweets, keep the returned `tweets[]` structure in the current agent context.
3. Map ordinal follow-up requests to remembered tweet or author context.
4. If multiple user candidates match a natural-language name, stop and ask the user to confirm the account.

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
When the user asks to like, unlike, follow, or unfollow on X/Twitter:

1. Do not ask the user to manually paste tweet links or IDs.
2. If the user first asked to query tweets, keep the returned `tweets[]` structure in the current agent context.
3. Map ordinal follow-up requests to remembered tweet or author context.
4. If multiple user candidates match a natural-language name, stop and ask the user to confirm the account.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring and CLI both present this file as supporting only read APIs, and every exposed command maps to GET-based retrieval endpoints. That behavior falls short of the manifest's claimed scope of engagement actions and OAuth-gated posting, creating a semantic mismatch between the skill's stated behavior and the actual code in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI directly performs state-changing social actions (follow/unfollow/like/unlike) as soon as the corresponding command is invoked, with no explicit confirmation gate, dry-run mode, or user re-authorization step in this file. In an agentic context, that increases the risk of unintended or prompt-manipulated actions being executed against the wrong account or tweet, especially because the skill is specifically designed to operationalize engagement workflows.

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 63)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) "

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The manifest describes read context, engagement actions, and approved posting through AIsa, but does not mention local filesystem access. This file implements arbitrary path resolution and file reading for --media-file, which adds a local data access capability not clearly justified by the declared purpose as written.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The post command sends tweet text, media IDs, and uploaded media files to the remote AIsa service via HTTP requests, but the execution path only prints results after submission and does not provide a confirmation prompt or explicit runtime disclosure before transmitting user data. Although the CLI help says it publishes through the AIsa service, this code path lacks a direct user warning at the point of action for potentially privacy-impacting network transfer.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The inline documentation actively characterizes the client as read-only, while the broader skill description says it performs likes, follows, replies, and OAuth-gated posting. This is not just incomplete documentation in this file; it directly frames the implementation as read-only, contradicting the advertised engagement intent for the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code sends usernames, tweet IDs, search queries, and similar inputs to https://api.aisa.one via network requests, but the CLI provides no runtime notice that user-provided data is being transmitted to a third-party service. Although the module docstring mentions read APIs and bearer authentication, it does not clearly warn users about external data transmission or privacy implications when invoking commands.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring advertises authorize [--callback-url <url>] [--open-browser], implying a browser-assisted local authorization flow. In implementation, --callback-url does not exist at all, and --open-browser only prints that browser auto-open is disabled rather than opening anything, which directly contradicts the documented behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The configuration loader requires AISA_API_KEY from the environment, and later request builders place it into the Authorization header and request payload. There is no user-facing disclosure in the code flow that the script will consume this credential and send it to the configured remote service.

Content

No source excerpt is available for this finding.