T09 · Insecure Skill Coding Practices
- Location
scripts/twitter_oauth_client.py:337- Finding
AISA API Key Is Exposed in Command Output and Redundantly Transmitted in Request Bodies
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its Twitter/X relay purpose, but it exposes the AIsa API key in normal command output and can directly post or change account engagement.
Review before installing. Use this only if you trust AIsa and api.aisa.one with your Twitter/X relay access, and avoid using a sensitive account until the skill stops printing the full AISA_API_KEY. Treat any existing logs or transcripts from authorize/post runs as potentially containing the key and rotate it if exposed.
scripts/twitter_oauth_client.py:337AISA API Key Is Exposed in Command Output and Redundantly Transmitted in Request Bodies
The code clearly matches the Twitter/X research and search portion of the description: it queries profiles, tweets, trends, communities, lists, and spaces via the AIsa relay using an API key. However, the description also states support for 'approved engagement actions' and says to use it for 'posting, likes, follows, or related workflows.' No such action methods or CLI commands exist in this chunk. All exposed operations are read-oriented GET endpoints, plus a generic internal POST path that is not used by any implemented feature. Therefore the description materially overstates the available capabilities, making it a mismatch.
The description partially matches the code because the code does support Twitter/X engagement actions through an AIsa relay, specifically likes, unlikes, follows, unfollows, and listing recent tweets after resolving a user. However, the declared purpose also claims capabilities for searching trends and posting, which are not implemented in this code chunk. The code’s primary behavior is narrower: local engagement operations plus limited lookup of users/tweets to support those actions. It also includes a status command that reveals relay base URL, API key presence, timeout, and supported endpoints, which is not reflected in the description. Because the declared description materially overstates implemented capabilities, this is a mismatch.
The description suggests a broader Twitter/X skill covering research/search across profiles, tweets, and trends, plus approved engagement actions such as posting, likes, and follows. The supplied code only supports three commands: authorize, post, and status. Its network interactions are limited to /twitter/auth_twitter and /twitter/post_twitter on the AIsa API. The posting logic includes media uploads, quote/reply handling, tweet URL parsing, and splitting long text into multiple threaded chunks. Because core declared capabilities like search, trends, likes, and follows are absent, and the implemented behavior is narrower and differently focused on OAuth plus publishing, this is a material description-behavior mismatch.
The client includes the full AIsa API key in user-visible JSON output from posting/thread publishing flows, which exposes a bearer secret unrelated to the user’s need to authorize or publish tweets. Anyone with access to terminal logs, captured stdout, CI logs, or chat-transcribed command output could reuse that key to access the relay API with the same privileges.
The authorize command prints the raw AIsa API key together with the authorization URL and raw response, unnecessarily disclosing a credential during a flow that should only return a link for the user to open. This is especially risky because authorization steps are commonly copied into logs, notebooks, support tickets, or agent transcripts.
The skill declares required environment access and relies on relay-based network calls, but it does not declare any explicit tool scope such as permissions or allowed-tools. That weakens least-privilege enforcement and makes it easier for an agent runtime to grant broader capabilities than users expect, especially for a user-invocable skill that can access an API key and external network.
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.
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.
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.
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.
The guidance describes how to publish to X/Twitter but does not clearly warn that the action will post publicly from the user's authorized account. That omission can cause users to authorize or trigger posting without fully understanding the visibility and reputational consequences, especially in an autonomous-agent workflow that attempts posting first.
The top-level docstring and CLI description present this as a read-only Twitter/X client. That intent is contradicted by the generic _request implementation, which contains explicit POST request support and JSON body handling, indicating write-capable behavior in the code path despite read-only documentation.
The module docstring explicitly describes 'Twitter/X read APIs' and says read operations use GET, suggesting a read-only client. However, the shared _request method serializes request bodies for POST and constructs requests with an arbitrary method, which goes beyond the documented read-only behavior and could support engagement/write actions if invoked or extended.
This code file sends usernames, tweet IDs, search queries, and other user-provided parameters to a remote API via HTTP requests. Although the module docstring mentions read APIs and bearer authentication, there is no runtime notice, confirmation, or explicit user-facing disclosure in the command execution path that entered values will be transmitted to an external service.
This client exposes follow, unfollow, like, and unlike operations as direct command handlers and executes them immediately once arguments are provided, with no built-in confirmation prompt, dry-run mode, or explicit acknowledgement for state-changing actions. In an agent-skill context, that increases the risk of unintended social-account manipulation from ambiguous prompts, prompt injection in upstream workflow steps, or operator error, because the code itself provides no last-mile safeguard before making the outbound action request.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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) "
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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) "
The API key is sent over the network as expected for authentication, but the dangerous part is that the same secret is also echoed back into user-visible output without warning or redaction. This creates unnecessary credential propagation across logs and interfaces, increasing the chance of accidental disclosure and subsequent abuse of the relay account.
The status command discloses relay base URL, supported endpoints, media upload behavior, and operational configuration details that are not necessary for normal Twitter engagement use. While less severe than credential leakage, this gives an attacker reconnaissance about reachable services and expected request structure.
The code places the AIsa API key into the JSON request body for outbound relay calls, which increases exposure to accidental disclosure through application logs, debug captures, downstream error reporting, or intermediary request inspection. Although service credentials must be transmitted somehow, embedding them in the payload rather than a dedicated authorization header and doing so without minimizing exposure makes credential leakage more likely in operational environments.