T09 · Insecure Skill Coding Practices
- Location
scripts/twitter_oauth_client.py:336- Finding
AISA API Key Exposed in OAuth and Posting Command Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its Twitter/X engagement purpose, but it exposes the full AISA API key in normal command output, which users should review before installing.
Install only if you trust AIsa with the Twitter/X actions, post content, attached media, and AISA_API_KEY. Treat the current version as review-needed because routine authorize/post commands can print the full API key into terminal output, agent transcripts, or logs; rotate any key used with this version if output may have been retained.
scripts/twitter_oauth_client.py:336AISA API Key Exposed in OAuth and Posting Command Output
The description claims the skill can run Twitter/X likes, follows, replies, and approved posting through AIsa. However, the code only exposes read APIs and uses GET requests throughout the feature methods. The only POST support is a generic branch in the internal request helper, but no command or method uses it. There are no endpoints or CLI commands for liking tweets, following accounts, replying, or creating posts, and no OAuth workflow appears in the code. The read-context portion of the description is accurate, but the primary declared engagement/posting purpose is not supported by the provided implementation.
The code substantially matches part of the description: it supports read context (list-tweets), engagement actions (like/unlike, follow/unfollow), and uses AIsa relay endpoints. However, the declared description explicitly includes replies and OAuth-gated posting, neither of which appears in the code chunk. The only supported endpoints are /like_twitter, /unlike_twitter, /follow_twitter, and /unfollow_twitter, and the supported commands confirm there is no reply or posting command. Because the description claims broader engagement/posting capabilities than the code actually provides, this is a description-to-behavior mismatch.
The description overstates the skill's capabilities. The supplied code only supports three concrete functions: obtaining a Twitter authorization URL via AIsa, publishing posts/replies/quote chains (with optional media and thread splitting), and printing local status/config information. There is no code for liking tweets, following accounts, or reading Twitter context. Replies and approved/OAuth-gated posting are represented, but the declared purpose claims a wider engagement suite than the code implements. This is a material description-behavior mismatch because several headline capabilities are absent.
The post/publish flow includes the raw AIsa API key in JSON output returned to the console. Console output is commonly captured in shell history, CI logs, agent transcripts, and telemetry, so this unnecessarily discloses a bearer credential that can be reused to call the remote API. In a Twitter-posting skill, revealing the backend API secret is not required for functionality and materially increases risk.
The authorize command prints the authorization URL together with the raw AIsa API key. This exposes a privileged credential during a routine OAuth bootstrap step, making accidental leakage through logs, screenshots, agent output, or terminal sharing very likely. Because the key is a bearer secret, anyone obtaining it may be able to invoke AIsa endpoints and perform actions beyond the intended user session.
The skill advertises networked, API-backed behavior and requires an API key, but it does not declare an explicit tool scope such as allowed-tools or permissions. That creates an authorization and review gap: an agent or runtime may permit broader environment and network use than operators expect, making outbound calls and secret handling less transparent.
The skill explicitly instructs the agent to send data, API credentials, OAuth requests, and user-approved media uploads to a fixed third-party endpoint. External transmission is expected for this skill category, but it still introduces confidentiality and supply-chain risk because user content and operational metadata leave the local environment and are sent to an external service.
- `AISA_API_KEY` is required for AIsa-backed API access.
- Use repo-relative `scripts/` paths from the shipped package.
- Twitter/X reads, OAuth requests, and user-approved media uploads use the fixed AIsa API endpoint `https://api.aisa.one/apis/v1/twitter`.
- Provide only `AISA_API_KEY`; do not use passwords, cookies, or browser credential export.
## Example Requests
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 module docstring says 'Twitter/X read APIs' and the usage/help text frames the tool as read-only. However, the core _request method explicitly supports POST bodies, which enables write actions if this client is extended or invoked against posting endpoints, so the documented intent is narrower than the implemented behavior.
The docstring states 'Twitter/X read APIs for autonomous agents' and specifically says 'Read operations use GET', creating a clear read-only expectation. The implementation contradicts that expectation by serializing request bodies for POST requests in the general request path, so the documentation actively misstates the code's capability.
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 optional uploaded media files to the AIsa service via HTTP requests. While this is functionally necessary, the code does not provide a clear disclosure at the point of transmission that local content and files are being uploaded to a remote service.
The main CLI entry point advertises 'Twitter/X read APIs', reinforcing a read-only contract to users and downstream agents. Yet the underlying client supports POST in _request, so the interface documentation understates the actual behavior available in code.
The code reads the AISA_API_KEY environment variable and uses it for authorization, but there is no comment, docstring, or user-facing notice explaining that a credential from the environment is required and will be used for outbound API calls. This qualifies as sensitive credential access lacking disclosure under the rule.
The status command itself only exposes a boolean, showing the code already has a safer pattern for credential handling. This highlights that full-key disclosure elsewhere is unjustified relative to the skill's declared Twitter workflow purpose and not required for client status reporting.
No suspicious patterns detected.