T09 · Insecure Skill Coding Practices
- Location
scripts/twitter_oauth_client.py:342- Finding
Plaintext AISA API Key Disclosed in CLI Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Twitter/X skill is mostly coherent, but it needs review because it exposes the relay API key in command output and can upload any readable image or video path supplied to it.
Review before installing. Use it only if you are comfortable routing Twitter/X queries, draft post text, OAuth authorization, and selected media through api.aisa.one. Do not run it in shared terminals, CI, or logged agent sessions until the API key is redacted from output, and only pass media files you explicitly intend to upload. Rotate AISA_API_KEY if it has already appeared in logs or transcripts.
scripts/twitter_oauth_client.py:342Plaintext AISA API Key Disclosed in CLI Output
scripts/twitter_oauth_client.py:377AISA API Key Is Redundantly Transmitted in Request Bodies
scripts/twitter_oauth_client.py:419Unrestricted Local File Paths Can Be Read and Uploaded to the Relay
If the advertised read/research capabilities are absent while the actual implementation is concentrated on authorization and posting, the skill is materially misrepresented. In security-sensitive agent workflows, this can induce users or orchestration systems to invoke a write-capable external-posting skill under the assumption that it is primarily read-only research tooling, raising the chance of unintended external actions.
If the advertised read/research capabilities are absent while the actual implementation is concentrated on authorization and posting, the skill is materially misrepresented. In security-sensitive agent workflows, this can induce users or orchestration systems to invoke a write-capable external-posting skill under the assumption that it is primarily read-only research tooling, raising the chance of unintended external actions.
The API key is emitted in cleartext without masking or warning in normal command output. In the context of a Twitter posting skill, that secret is a sensitive capability token; exposing it makes downstream compromise more dangerous because an observer can post or act via the AIsa relay without needing the user's password.
The authorize command prints the bearer token alongside the authorization URL and raw response. Authorization flows are especially likely to be copied into tickets, chats, or logs, so including the key materially increases the risk of credential leakage and unauthorized use of the relay-backed Twitter capability.
The skill declares required environment access and relay-based network use, but does not explicitly scope or constrain those capabilities with a permissions or allowed-tools declaration. In an agent ecosystem, missing tool-scope metadata can cause the runtime or reviewer to underestimate what the skill can access, increasing the risk of overbroad secret exposure or unintended outbound requests.
The document explains that local workspace media and user-provided post content are sent to a relay backend and then to Twitter/X, but it does not prominently warn users at the point of use that invoking the skill transmits potentially sensitive local files and text off-box to external services. In an agent setting, unclear disclosure can lead to unintended exfiltration of local media or sensitive draft content, especially when users may assume attachments remain local unless explicitly told otherwise.
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 and CLI description repeatedly describe this client as providing only "Twitter/X read APIs". However, the shared _request helper explicitly implements POST request support and JSON request bodies, which enables write-capable API calls if endpoints are added or invoked through this client, making the documented scope broader in code than advertised.
The module docstring says "Twitter/X read APIs for autonomous agents" and specifically states that "Read operations use GET," while the central request routine contains logic to send POST requests with serialized JSON bodies. That is an active contradiction between the documented intent and the implemented transport behavior.
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 script includes the raw AIsa API key in user-visible JSON output from posting/status flows. Exposing a bearer token in stdout is dangerous because terminals, shell history, CI logs, chat transcripts, or calling agents may capture it, allowing anyone with the key to reuse the Twitter-posting capability through the relay API.
The module docstring states that authorize supports --callback-url <url>, but build_parser() defines only --open-browser for that subcommand and the authorization command never handles a callback URL. This is a direct contradiction between documentation and code behavior, not merely an omitted detail.
The CLI interface and module docstring present local authorization behavior and import webbrowser, suggesting browser-assisted authorization, but the actual code explicitly refuses to perform the browser action. This is an intent-level mismatch in exposed capability: the skill advertises a local browser-open flow that is not actually implemented.