T09 · Insecure Skill Coding Practices
- Location
plugin/index.mjs:157- Finding
Unnecessary Plaintext Storage of Complete AI Responses and Session Identifiers
- Content
View full analysis
Vulnerability Details
File Location:
plugin/index.mjs, lines 157-178; invoked at line 339
Vulnerability Type: Plaintext storage of sensitive conversation data
Risk Level: MediumVulnerable Code
js function logAIReply(sessionKey, output, success, messages) { try { let logs = []; if (fs.existsSync(DATA_FILE)) { logs = JSON.parse(fs.readFileSync(DATA_FILE, "utf-8")); } const entry = { timestamp: new Date().toISOString(), sessionKey, outputLength: output.length, outputPreview: output.substring(0, 200), fullOutput: output, success, isQuotaError: isQuotaError(output), }; logs.push(entry); // 保留最近 200 条 if (logs.length > 200) { logs = logs.slice(-200); } fs.writeFileSync(DATA_FILE, JSON.stringify(logs, null, 2), "utf-8");The function is called for every completed agent interaction:
js // 记录所有 AI 回复 logAIReply(sessionKey, lastOutput, success, messages);Technical Analysis
The plugin writes the complete output of every AI response to
~/.openclaw/skills/model-fallback-retry/ai_replies_log.json. Each record includes the full response, a preview, the session identifier, and interaction metadata.Full response storage is not required for the plugin's core retry function. Retryable conditions can be recorded using an error classification, timestamp, and queue identifier without retaining complete conversation content. Because
fs.writeFileSync()is called without an explicit restrictive mode, the code relies on ambient process and directory permissions. It also provides no content redaction, encryption, diagnostic-logging opt-in, or immediate deletion policy.The file retains up to 200 complete responses. These responses may contain credentials, personal data, internal business information, source code, system details, or other confidential material returne ...[truncated 1788 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove
fullOutputandoutputPreviewfrom persistent logs by default. - Record only the minimum metadata required for retry diagnostics, such as timestamp, generated queue ID, normalized error category, HTTP status, and retry count.
- Make detailed diagnostic logging explicitly opt-in and display a warning that conversation content may be stored.
- Apply redaction before persistence, including removal of access tokens, API keys, passwords, cookies, personal identifiers, and other configurable sensitive patterns.
- Create log and queue files with owner-only permissions, such as mode
0600, and ensure the containing directory is mode0700. - Use atomic file creation and replacement so existing file permissions are not unintentionally widened.
- Define a short, configurable retention period based on time rather than retaining a fixed number of complete responses.
- Delete retry records immediately after completion unless minimal audit metadata is explicitly required.
- Consider encryption at rest when original user messages must be retained for delayed replay.
- Avoid storing raw session identifiers when a one-way hash or random internal correlation identifier is sufficient.
- Remove
