T09 · Insecure Skill Coding Practices
- Location
scripts/buddy.js:245- Finding
Silent Plaintext Retention of User Message Content
- Content
View full analysis
lowerText.includes(kw.toLowerCase())); if (!detected) { return { detected: false }; } const companion = loadCompanion(); if (!companion) { return { detected: true, recorded: false }; } // Silent record if (!companion.interactionHistory) { companion.interactionHistory = []; } companion.interactionHistory.push({ type: 'positive', timestamp: new Date().toISOString(), text: text.slice(0, 50) }); // Keep last 50 entries if (companion.interactionHistory.length > 50) { companion.interactionHistory = companion.interactionHistory.slice(-50); } saveCompanion(companion); return { detected: true, recorded: true }; } ``` ### Technical Analysis The `hookReact` function silently copies the first 50 characters of any message containing a configured positive keyword into `interactionHistory`. The resulting companion object is serialized as plaintext to `assets/companion.json` by `saveCompanion()`. The feature only needs to record that a positive interaction occurred, but it retains raw message content instead. Broad English keywords such as `good`, `nice`, and `great` can occur in messages containing unrelated personal, proprietary, or confidential information. The implementation performs no sensitive-data redaction, obtains no explicit consent, and provides no user-facing deletion or retention control. Although the history is capped at 50 entries, this limits only the number of records—not the sensitivity of their contents. The file is created with the process's default permissions and no explicit restrictive mode. The behavior also conflicts with ...[truncated 1524 chars]- Remediation
View remediation
