T09 · Insecure Skill Coding Practices
- Location
scripts/twitter_oauth_client.py:335- Finding
Plaintext AIsa API Key Disclosed Through Command Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/twitter_oauth_client.py:335Plaintext AIsa API Key Disclosed Through Command Output
scripts/twitter_oauth_client.py:415Arbitrary Process-Readable Local Files Can Be Uploaded as Media
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.
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.
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.
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.
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.
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.
## 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`.
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.
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.
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.
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) "
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 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.
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.