T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:15
- Finding
- Process-Global Confirmation State Allows Cross-Session Data Contamination<![CDATA[ ## Vulnerability Details **File Location**: `index.js`, lines 15-16 and 113-140 **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: High ### Evidence ```js // Global state used for all callers let pendingState = null; let pendingArchiveState = null; ``` ```js async function main(input, context) { await ensureFiles(); // State machine 1: archive classification confirmation if (pendingArchiveState) { const reply = input.trim(); if (reply === '项目类' || reply === '其他类') { const res = await doArchive(pendingArchiveState.content, reply); pendingArchiveState = null; return res.msg; } else { pendingArchiveState = null; return '已取消归档操作。'; } } // State machine 2: content classification confirmation if (pendingState) { const reply = input.trim(); const valid = ['工作待办', '生活待办', '工作记录', '灵感']; if (valid.includes(reply)) { const fp = getFilePath(reply); await fs.appendFile(fp, formatContent(pendingState.content, reply)); pendingState = null; return `✅ 已成功记录到【${reply}】`; } else { pendingState = null; return '已取消操作。'; } } ``` ### Technical Analysis The pending confirmation state is stored in module-level variables shared by every invocation in the Node.js process. Although `main` receives a `context` parameter, that context is not used to associate pending content with a particular user, conversation, or authenticated session. In a multi-user or concurrently invoked agent runtime, one caller can therefore consume, classify, cancel, or archive content submitted by another caller. The check and subsequent state clearing are also not synchronized, which can produce race conditions during concurrent invocations. This violates session isolation and can cause private note content to cross trust boundaries. ### Attack Path 1. User A submits ambiguous or private content that receives a classification confidence below 90%. 2. Th ...[truncated 1110 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Replace module-level state with a map or persistent store keyed by a trusted conversation or session identifier from `context`. - Include the authenticated user identity in the key where multiple users can share a conversation namespace. - Reject confirmation messages when no pending operation exists for the current session. - Add short expiration times to all pending operations. - Clear state atomically only after the associated operation completes. - Use per-session locking or compare-and-swap semantics to prevent concurrent confirmations from consuming the same operation. - Avoid placing sensitive content in process-global mutable variables. - Add tests that interleave requests from multiple users and verify strict isolation. ]]>
