T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/cache-manager.js:8
- Finding
- Sensitive Agent State Persisted in a Predictable Plaintext Cache<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cache-manager.js:8-68` **Vulnerability Type**: Plaintext storage of sensitive Agent state **Risk Level**: Medium ### Vulnerable Code ```javascript const WORKSPACE = process.env.OPENCLAW_WORKSPACE || process.cwd(); const CACHE_DIR = path.join(WORKSPACE, 'cache'); const CACHE_FILE = path.join(CACHE_DIR, 'memory-cache.json'); const LAST_REFRESH_FILE = path.join(CACHE_DIR, '.last-refresh'); const LAST_MESSAGE_FILE = path.join(CACHE_DIR, '.last-message'); ``` ```javascript function loadCache() { console.log('🔄 加载记忆文件到缓存...\n'); // 确保缓存目录存在 initCache(); const cache = { timestamp: Date.now(), files: {} }; // 核心记忆文件 const files = { 'SOUL.md': path.join(WORKSPACE, 'SOUL.md'), 'USER.md': path.join(WORKSPACE, 'USER.md'), 'MEMORY.md': path.join(WORKSPACE, 'MEMORY.md'), 'AGENTS.md': path.join(WORKSPACE, 'AGENTS.md'), 'SESSION-STATE.md': path.join(WORKSPACE, 'SESSION-STATE.md'), 'HEARTBEAT.md': path.join(WORKSPACE, 'HEARTBEAT.md'), 'WORKING.md': path.join(WORKSPACE, 'WORKING.md') }; for (const [name, filePath] of Object.entries(files)) { const content = readFileSafe(filePath); if (content) { cache.files[name] = { content: content.substring(0, 5000), // 限制大小 size: content.length, mtime: fs.statSync(filePath).mtime.getTime() }; console.log(`✅ 缓存: ${name} (${content.length} 字符)`); } else { console.log(`⚠️ 跳过: ${name} (不存在)`); } } // 保存缓存 fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2)); fs.writeFileSync(LAST_REFRESH_FILE, Date.now().toString()); console.log(`\n✅ 缓存已保存: ${CACHE_FILE}`); console.log(`📊 共缓存 ${Object.keys(cache.files).length} 个文件`); return cache; } ``` ### Technical Analysis The cache manager collects up to 5,000 characters from each of several potentially sensitive OpenClaw files, including user data, long-term memory, system instruct ...[truncated 2249 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Adopt a default-deny cache policy and require an explicit allowlist of files that are safe and necessary to cache. 2. Do not persist `USER.md`, `MEMORY.md`, `SOUL.md`, `AGENTS.md`, or session-state files unless the user explicitly enables that behavior. 3. Prefer an in-memory cache so sensitive content is removed when the process exits. 4. If disk persistence is required, create the cache directory with mode `0700` and the cache file with mode `0600`, for example: ```javascript fs.mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 }); fs.writeFileSync(CACHE_FILE, JSON.stringify(cache), { encoding: 'utf8', mode: 0o600 }); ``` 5. Validate existing cache and directory ownership and permissions before reading or overwriting them. 6. Minimize cached content by storing only required derived metadata rather than raw file contents. 7. Define a retention period and securely delete stale cache files. 8. Clearly document the actual cache location and the categories of information copied into it. ]]>
