T09 · Insecure Skill Coding Practices
- Location
scripts/export_grok_items_capture.js:31- Finding
Plaintext Persistence of Private Grok Conversation Data in Browser Storage
- Content
View full analysis
Vulnerability Details
File Location:
scripts/export_grok_items_capture.js, lines 31–44 and 359–372
Vulnerability Type: Plaintext storage of sensitive information
Risk Level: MediumVulnerable Code:
javascript const saveCheckpoint = (targets, currentIndex, pass) => { try { const cp = { version: 1, savedAt: new Date().toISOString(), pass, currentIndex, targets, captured: [...captured.values()].map(x => ({ restId: x.restId, requestUrl: x.requestUrl, source: x.source, data: x.data })), rateLimitHits, }; localStorage.setItem(CHECKPOINT_KEY, JSON.stringify(cp)); } catch {} };javascript // final checkpoint save before download saveCheckpoint(targets, targets.length - 1, 3); const blob = new Blob([JSON.stringify(out, null, 2)], { type: 'application/json' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `grok-conversation-history-${Date.now()}.json`; a.click(); // completed successfully; clear resume state clearCheckpoint();Technical Analysis
The checkpoint mechanism serializes complete captured API response objects into plaintext
localStorageunder the X origin. These objects may contain private conversation messages, reasoning traces, conversation metadata, and request URLs.Browser
localStorageis persistent and is not automatically cleared when the tab closes or the browser restarts. The script removes the checkpoint only after reaching its successful completion path. If execution is interrupted by tab termination, browser failure, navigation, an unhandled exception, or manual cancellation, the captured information may remain stored indefinitely.Any JavaScript that subsequently gains execution capability in a context permitted to access the same origin storage can retrieve the checkpoint through its fixed key,
xgrok_capture_checkpoint_v1. This ...[truncated 1570 chars]- Remediation
View remediation
Remediation Suggestions
-
Store only nonsensitive resume metadata in
localStorage, such as conversation IDs, the current index, pass number, and completion status. Keep message bodies and complete response objects in memory. -
If payload persistence is operationally required, obtain explicit user consent and use a safer user-controlled export mechanism instead of origin-wide plaintext storage.
-
Add a short expiration timestamp to checkpoints and delete expired data automatically when the script starts.
-
Provide and document a manual cleanup command:
javascript localStorage.removeItem('xgrok_capture_checkpoint_v1'); -
Wrap the main workflow with robust cleanup handling where appropriate. Distinguish resumable interruptions from terminal failures, and delete sensitive payloads when continuation is not intended.
-
Minimize checkpoint contents by excluding full API responses, reasoning traces, citations, and request URLs unless strictly necessary for resume functionality.
-
Clearly warn users that interrupted runs may leave sensitive data in browser storage and explain how to remove it.
-
