T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/openclaw-hybrid-audit-changeway.js:1146
- Finding
- Persistent Device Identifier Is Created During Offline Scans<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw-hybrid-audit-changeway.js`, lines 1146-1153 and 1254-1288 **Vulnerability Type**: Privacy boundary violation and unintended persistent state **Risk Level**: Medium ### Vulnerable Code ```javascript function generateAgentId() { const idPath = path.join(OC, '.agent-id'); if (fs.existsSync(idPath)) { return fs.readFileSync(idPath, 'utf-8').trim(); } const id = crypto.randomUUID(); try { fs.writeFileSync(idPath, id, { mode: 0o600 }); } catch (e) {} return id; } ``` ```javascript function finalizeAndPushData() { const agentId = generateAgentId(); const status = RED_COUNT > 0 ? "warning" : "success"; const checkedCount = ITEM_SEQ - SKIP_COUNT; const passCount = checkedCount - RED_COUNT; let outputObj = { report_time: REPORT_TIME, status, red_item: RED_COUNT, checkedCount: checkedCount, passCount: passCount, agent_id: agentId, data: JSON_DATA }; // ... fs.writeFileSync(JSON_OUT_FILE, JSON.stringify(outputObj, null, 2), { encoding: 'utf-8', mode: 0o600 }); // ... if (!PUSH_ENABLED) { SUMMARY += `${COLORS.dim}────────────────────────────────────────────────────────────────────────${COLORS.reset}\n`; console.log(SUMMARY); console.log(`${COLORS.dim}Detailed audit report saved to: \`${REPORT_FILE}\`${COLORS.reset}`); process.exit(0); return; } } ``` ### Technical Analysis `finalizeAndPushData()` invokes `generateAgentId()` before checking `PUSH_ENABLED`. Consequently, a normal offline scan creates or reuses the persistent file `~/.openclaw/.agent-id`, even though the Skill documentation states that this identifier is created only when the user explicitly selects `--push`. The identifier is also included in the locally persisted JSON report. A later network-enabled run reuses the same value, allowing sca ...[truncated 1286 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Move identifier generation entirely inside the `PUSH_ENABLED` branch: ```javascript function finalizeAndPushData() { const status = RED_COUNT > 0 ? "warning" : "success"; const checkedCount = ITEM_SEQ - SKIP_COUNT; const passCount = checkedCount - RED_COUNT; const outputObj = { report_time: REPORT_TIME, status, red_item: RED_COUNT, checkedCount, passCount, data: JSON_DATA }; if (!PUSH_ENABLED) { fs.writeFileSync( JSON_OUT_FILE, JSON.stringify(outputObj, null, 2), { encoding: 'utf-8', mode: 0o600 } ); // Finish without creating an agent identifier. return; } const agentId = generateAgentId(); outputObj.agent_id = agentId; // Continue with the consented upload. } ``` 2. Do not include `agent_id` in offline JSON reports. 3. Add a migration option that informs users about and, with confirmation, removes identifiers created by previous offline runs. 4. Add an automated test asserting that an offline execution does not create `.agent-id`. 5. Add a second test confirming that `--push` creates the identifier only after explicit mode selection. ]]>
