T09 · Insecure Skill Coding Practices
Error
- Location
- acc-error-memory/scripts/haiku-screen.sh:26
- Finding
- Conversation Transcript Data Can Be Sent to Network-Backed Model CLIs Without Redaction<![CDATA[ ## Vulnerability Details **File Location**: `acc-error-memory/scripts/preprocess-errors.sh:14-17, 73-168`; `acc-error-memory/scripts/encode-pipeline.sh:121-124`; `acc-error-memory/scripts/haiku-screen.sh:26-101` **Vulnerability Type**: Sensitive-data exposure through external model invocation **Risk Level**: High ### Relevant Code From `acc-error-memory/scripts/preprocess-errors.sh`: ```bash WORKSPACE="${WORKSPACE:-$HOME/.openclaw/workspace}" AGENT_ID="${AGENT_ID:-main}" TRANSCRIPT_DIR="$HOME/.openclaw/agents/$AGENT_ID/sessions" OUTPUT="$WORKSPACE/memory/pending-errors.json" WATERMARK_FILE="$WORKSPACE/memory/acc-watcher-watermark.json" ``` ```python # Collect all messages from all sessions all_messages = [] session_files = glob(os.path.join(transcript_dir, '*.jsonl')) for session_file in session_files: session_name = os.path.basename(session_file) line_num = 0 try: with open(session_file, 'r', encoding='utf-8', errors='replace') as f: for line in f: line_num += 1 line = line.strip() if not line: continue try: data = json.loads(line) except json.JSONDecodeError: continue if data.get('type') != 'message': continue msg = data.get('message', {}) role = msg.get('role', '') if role not in ('user', 'assistant'): continue ts_str = data.get('timestamp', '') if not ts_str: continue try: ts = datetime.fromisoformat(ts_str.replace('Z', '+00:00')) except: continue if not full_mode and watermark_ts and ts <= watermark_ts: continue content = msg.get('content', []) text = '' if isi ...[truncated 6038 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Default `ACC_MODELS` to an explicitly local model rather than a potentially network-backed CLI. 2. Require affirmative, informed opt-in before any transcript is processed by a remote provider. 3. Detect whether a configured command is local or remote and block unknown providers by default. 4. Redact API keys, authorization headers, passwords, private keys, email addresses, account identifiers, and other sensitive patterns before constructing prompts. 5. Provide a dry-run mode showing exactly which redacted text and provider would be used. 6. Support per-session, per-directory, and per-message exclusion controls. 7. Process only the minimum text necessary for classification instead of fixed 500-character excerpts from both messages. 8. Avoid writing full candidate exchanges to plaintext intermediate files, or protect them with restrictive permissions and prompt deletion. 9. Document provider transmission, retention, and privacy consequences next to the cron and model configuration instructions. 10. Add automated tests confirming that representative credentials and personal data never reach `subprocess.run`. ]]>
