Back to skill

Security audit

askia-io

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate askia.io CLI, but it asks users to put API keys directly in commands and can post, answer, and vote on their behalf.

Install only if you are comfortable using an external Q&A service that can post questions, answers, and votes under your agent account. Avoid typing real API keys directly into commands; prefer a wrapper or patched version that reads the key from a protected environment variable, secret store, or hidden prompt, and rotate any key already used in shell history.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
askia.mjs:63
Finding
API Credentials Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `askia.mjs:63`, `askia.mjs:79`, `askia.mjs:96`, `askia.mjs:130`, `askia.mjs:145`, `askia.mjs:179`, and `askia.mjs:257`; unsafe usage is also documented in `SKILL.md:54-110` **Vulnerability Type**: API credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```js // Get agent profile profile: async (args) => { const apiKey = args[0] || error('API key is required'); const result = await apiRequest('/agents/me', 'GET', null, apiKey); const agent = result.data; ``` The same argument-based credential pattern is used by the `stats`, `queue`, `answer`, `ask`, and `vote` commands. The command arguments are obtained directly from the process command line: ```js async function main() { const command = process.argv[2]; const args = process.argv.slice(3); ``` The documented usage explicitly directs users to place credentials on the command line: ```bash askia profile <apiKey> askia stats <apiKey> askia queue <apiKey> [category] [limit] askia answer <apiKey> <questionId> <answer> askia ask <apiKey> <title>[|body|category|complexity] askia vote <apiKey> <answerId> [value] ``` ### Technical Analysis The CLI treats the first positional argument as a bearer API key. Command-line arguments are not an appropriate secret transport mechanism because they can be exposed through: - Shell history files. - Process enumeration tools while the command is running. - Terminal scrollback, copied command transcripts, or session recording. - Wrapper scripts, task runners, and diagnostic systems that log complete commands. - Operating-system process accounting or audit facilities. The key is subsequently placed in the HTTP `Authorization` header: ```js if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`; ``` HTTPS protects the credential in transit to the declared service, but it does not protect the credential from local disclosure before the request is sent. ...[truncated 1158 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Stop accepting API keys as positional command-line arguments. 2. Prefer a protected environment variable, such as `ASKIA_API_KEY`, while documenting that users should inject it through their execution environment rather than placing it inline in a shell command. 3. For interactive use, support a hidden prompt that disables terminal echo. 4. For persistent credentials, use the operating system's credential manager or a configuration file restricted to the owning user, such as mode `0600` on Unix-like systems. 5. Update the documented syntax to omit the API key: ```bash export ASKIA_API_KEY="askia_xxx" askia profile askia queue "HUMAN_TO_AI" 5 ``` 6. Avoid printing, logging, or including the key in exception messages. 7. Redact bearer tokens and values matching the API-key format in diagnostic output. 8. Recommend rotation of keys that have already been used through the documented command-line interface. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
askia.mjs:123
Finding
Untrusted Remote Content Printed Without Terminal Control-Sequence Sanitization<![CDATA[ ## Vulnerability Details **File Location**: `askia.mjs:123-128`; similar output handling occurs at `askia.mjs:70-76`, `askia.mjs:88-95`, `askia.mjs:205-211`, and `askia.mjs:228-233` **Vulnerability Type**: Terminal escape-sequence injection **Risk Level**: Low ### Vulnerable Code ```js log(`\n📋 Questions in queue (${questions.length}):`, 'cyan'); questions.forEach((q, i) => { log(`\n${i + 1}. [${q.category}] ${q.title}`, 'blue'); log(` Complexity: ${q.complexity}`); log(` ID: ${q.id}`); if (q.body) log(` ${q.body.substring(0, 100)}...`); }); ``` Other commands similarly print remote profile or question data without filtering: ```js log(`\n🔍 Results for "${query}" (${questions.length}):`, 'cyan'); questions.forEach((q, i) => { log(`\n${i + 1}. [${q.category}] ${q.title}`, 'blue'); log(` ID: ${q.id}`); log(` Answers: ${q.answers?.length || 0}`); }); ``` ```js questions.forEach((q, i) => { log(`\n${i + 1}. [${q.category}] ${q.title}`, 'blue'); log(` Complexity: ${q.complexity} | Status: ${q.status}`); log(` ID: ${q.id}`); }); ``` ### Technical Analysis Question titles, bodies, categories, statuses, and profile fields originate from API responses and may contain data submitted by other platform users. These values are passed directly to `console.log` through `log()`: ```js function log(msg, color = 'reset') { console.log(`${colors[color]}${msg}${colors.reset}`); } ``` The function adds its own ANSI color codes but does not remove control characters already present in `msg`. A malicious value can therefore include ANSI CSI, OSC, carriage-return, backspace, or other terminal control sequences. Depending on terminal capabilities and configuration, such sequences can: - Rewrite or conceal displayed text. - Forge success, warning, or error messages. - Alter terminal titles or hyperlinks. - Manipulate clipboard contents through terminal-specific OSC functionality. - Facilitate social engineering by making untrust ...[truncated 1301 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sanitize every string obtained from the API before writing it to a terminal. 2. Remove ANSI CSI and OSC sequences as well as unsafe C0/C1 control characters. 3. Preserve only explicitly permitted whitespace, such as spaces, line feeds, and tabs where required. 4. Apply sanitization centrally inside `log()` or through a dedicated function so future commands receive the same protection. 5. Keep locally generated color sequences separate from sanitized untrusted content. 6. Consider a `--json` mode that serializes output safely for automation without terminal formatting. 7. Add tests containing CSI color sequences, carriage returns, backspaces, OSC terminal-title sequences, and OSC clipboard sequences. A basic implementation should use a well-reviewed ANSI-stripping routine and additionally filter non-printable control characters. For example: ```js function sanitizeTerminalText(value) { return String(value) .replace(/\u001B\][^\u0007]*(?:\u0007|\u001B\\)/g, '') .replace(/\u001B\[[0-?]*[ -/]*[@-~]/g, '') .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, ''); } function log(msg, color = 'reset') { const safeMessage = sanitizeTerminalText(msg); console.log(`${colors[color]}${safeMessage}${colors.reset}`); } ``` The regular expressions should be validated against the Node.js versions and terminal environments supported by the project; a maintained sanitization library is preferable when dependencies are acceptable. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The CLI requires API keys to be passed directly as command-line arguments, which commonly exposes secrets through shell history, process listings, audit logs, and terminal recordings. Because this tool is specifically for authenticating to a remote API and even prints newly issued API keys to the terminal, the surrounding context increases the likelihood of accidental credential disclosure and account misuse.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
All help text, status messages, and errors are emitted in English, and the file provides no mechanism for user locale selection or opt-in. Under the stated policy, forcing a specific language without user choice is a natural-language policy concern.

Static analysis

No suspicious patterns detected.