T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:20
- Finding
- Unrestricted Plaintext Logging of Sensitive LLM Requests and Responses<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 20–37, 84–89, and 146–157 **Vulnerability Type**: Sensitive data exposure through unrestricted plaintext logging **Risk Level**: Medium ### Vulnerable Code The guide identifies prompts, system prompts, and conversation history as data available to the input hook, and stores the complete input event: ```typescript const inFlightRequests = new Map<string, RequestData>(); api.on("llm_input", (event: any) => { const runId = event.runId; inFlightRequests.set(runId, { timestamp: Date.now(), input: event }); }); api.on("llm_output", (event: any) => { const runId = event.runId; const request = inFlightRequests.get(runId); // Successfully paired, record the complete request-response inFlightRequests.delete(runId); }); ``` It then recommends serializing log entries directly into date-based plaintext JSONL files: ```typescript // JSONL format, split files by date const logPath = path.join(basePath, `${new Date().toISOString().split('T')[0]}.jsonl`); fs.appendFileSync(logPath, JSON.stringify(entry) + "\n"); ``` The referenced example is explicitly described as having the following behavior: ```text Features: - Log all LLM API requests and responses - JSONL formatted logs, split by date - Correlate requests and responses using runId - Record metrics such as durationMs and usage ``` ### Technical Analysis The documented pattern captures complete LLM input and output events and recommends writing serialized entries to plaintext JSONL files. The document states that input events may contain prompts, system prompts, and historical messages. These fields can include credentials, API tokens, personal information, proprietary content, hidden system instructions, and other confidential conversation data. The guidance does not include: - A field allowlist limiting collection to operational metadata. - Redaction of passwords, tokens, or personally identifiable information. - Explicit us ...[truncated 2211 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Use metadata-only logging by default** - Record request identifiers, timestamps, latency, token usage, model names, and status codes. - Do not record prompts, system prompts, message history, tool arguments, or complete responses unless explicitly required. 2. **Require explicit opt-in for content logging** - Keep content logging disabled by default. - Display a clear warning that logged content may contain confidential information. - Obtain authorization from the system owner and, where applicable, affected users. 3. **Apply field-level filtering and redaction** - Use an allowlist rather than serializing complete event objects. - Redact authorization headers, API keys, passwords, access tokens, cookies, and known secret formats. - Provide configurable redaction for personal and organization-specific sensitive data. 4. **Protect files at creation time** - Create the log directory with owner-only permissions. - Create files with restrictive permissions such as `0600`. - Reject symlinked log paths and validate that the configured destination is an expected local directory. 5. **Implement retention controls** - Set maximum file sizes and retention periods. - Rotate files and securely delete expired records. - Avoid indefinite accumulation merely by creating a new file each day. 6. **Protect stored content** - Use encryption at rest when logging content is genuinely necessary. - Keep encryption keys separate from the log directory. - Restrict log access to the minimum set of authorized operators and processes. 7. **Document operational safeguards** - Warn administrators not to include raw logs in public bug reports or diagnostic bundles. - Document incident-response procedures for accidental secret logging. - Test redaction and access controls before enabling the plugin in production. ]]>
