T09 · Insecure Skill Coding Practices
Warning
- Location
- src/core/lifecycle-monitor.js:129
- Finding
- Unredacted Lifecycle Payloads Are Persisted in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `src/core/lifecycle-monitor.js:129-141`, `src/core/lifecycle-monitor.js:194-199`, and `database/init.js:52-62` **Vulnerability Type**: Plaintext storage of potentially sensitive event data **Risk Level**: Medium ### Vulnerable Code ```javascript // src/core/lifecycle-monitor.js:129-141 if (this._shouldStoreL2(event, payload)) { clawMem.storeL2({ record_id: recordId, full_content: JSON.stringify(payload, null, 2), metadata: { event_type: event, session_id: payload.session_id, importance: this._calculateImportance(event, payload) }, token_cost: JSON.stringify(payload).length / 4 }); } ``` ```javascript // src/core/lifecycle-monitor.js:194-199 _shouldStoreL2(event, payload) { // Store only high-value events const highValueEvents = ['memory.write', 'tool.call']; return highValueEvents.includes(event); } ``` ```javascript // database/init.js:52-62 db.exec(` CREATE TABLE IF NOT EXISTS l2_details ( id INTEGER PRIMARY KEY AUTOINCREMENT, record_id TEXT UNIQUE NOT NULL, full_content TEXT, metadata TEXT, embeddings TEXT, token_cost INTEGER DEFAULT 0, created_at INTEGER DEFAULT (strftime('%s', 'now')) ) `); ``` ### Technical Analysis The lifecycle monitor treats every `tool.call` and `memory.write` event as sufficiently valuable for L2 retention. It serializes the complete event payload with `JSON.stringify(payload, null, 2)` and passes the result to `storeL2()`, which writes it to the SQLite `full_content` text column without redaction or encryption. Tool arguments and memory-write payloads can legitimately contain API tokens, passwords, authorization headers, personal information, private prompts, uploaded content, or other confidential data. The implementation has no recursive secret filtering, field allowlist, maximum payload size, retention period, encryption control, or caller-controlled consent flag. In addition, `src/index.js ...[truncated 1719 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace full-payload serialization with an explicit allowlist of fields that are necessary for memory functionality. 2. Implement recursive redaction for common sensitive keys, including `password`, `secret`, `token`, `api_key`, `authorization`, `cookie`, and private-key material. 3. Make L2 payload capture disabled by default and require an explicit opt-in configuration setting. 4. Allow callers to mark events or individual fields as non-persistable. 5. Encrypt sensitive L2 content at rest using a key stored separately from the database. 6. Create the database and its containing directory with owner-only permissions, such as `0600` for the database and `0700` for its directory. 7. Add configurable retention limits and secure deletion or expiration of historical details. 8. Enforce a maximum serialized payload size before enqueueing or storing an event. 9. Avoid starting lifecycle monitoring as an import-time side effect. Require an explicit `start()` call by the integrating application. 10. Document which data is captured and provide controls for consent, deletion, and inspection. ]]>
