# Data Handling, File I/O, Privacy & Encryption Audit

**Audit Date:** 2026-04-28  
**Codebase:** scorpiox/clang (C)  
**Auditor:** Security Audit Agent  
**Scope:** File I/O, PII, credential management, encryption, temporary files, logging, data retention

---

## 1. Executive Summary

The scorpiox codebase is a large C project (~100+ non-vendor source files) implementing an AI coding assistant with TUI, multiplexer, email server, DNS server, container runtime, and SDK components. The audit identified **several critical findings** around hardcoded credentials in the WASM embedded config, plaintext config files storing API keys and SSH passwords, and unsalted SHA256 password hashing in the email module. Traffic logging correctly redacts authorization headers in most providers, but the OpenAI provider logs request URLs without API key redaction when keys are passed via URL. Session data (conversations, traces, events) is stored unencrypted on the local filesystem.

**Risk Rating: HIGH** — Primarily due to hardcoded secrets in compiled binaries and weak password hashing.

---

## 2. Data Flow Summary

```
User Input → TUI (sx.c)
    ├→ Configuration (sx_config.c) ← scorpiox-env.txt (3 cascade levels)
    ├→ Provider (sx_provider_*.c) → HTTP/TLS → External API
    │     ├→ Traffic Logs (.scorpiox/sessions/<id>/traffic/)
    │     └→ API Keys from config / env vars / embedded config
    ├→ Session Manager (sx_session.c)
    │     ├→ conversation.json (full history)
    │     ├→ session.log (debug output)
    │     ├→ events.jsonl (structured events)
    │     ├→ trace.jsonl (data flow trace)
    │     ├→ config-snapshot.txt (frozen config)
    │     └→ meta.json (metadata)
    ├→ Conversation Store (.scorpiox/conversations/*.json)
    ├→ Email Server (sxmail_*.c) → Maildir format
    │     ├→ Auth accounts file (user:hash)
    │     └→ TLS via mbedTLS
    ├→ Multiplexer (sxmux_*.c) → Unix domain sockets in /tmp/sxmux/
    ├→ Usage Tracking → POST to code.scorpiox.net/usage-send
    └→ Session Emit → POST to code.scorpiox.net/sessions-send
```

---

## 3. File I/O Inventory

### 3.1 Configuration Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| `exe_dir/scorpiox-env.txt` | Read | Global config (API keys, SSH creds, URLs) | **CRITICAL** — contains plaintext secrets |
| `~/.claude/scorpiox-env.txt` | Read | User-level config override | **CRITICAL** — may contain API keys |
| `CWD/.scorpiox/scorpiox-env.txt` | Read/Write | Project-level config override | **HIGH** — may contain API keys |
| `sx_config_embedded.c` | Compiled-in | WASM binary embedded config | **CRITICAL** — hardcoded secrets |

### 3.2 Session & Conversation Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| `.scorpiox/sessions/<id>/conversation.json` | Read/Write | Full conversation history | **HIGH** — may contain user secrets shared in chat |
| `.scorpiox/sessions/<id>/session.log` | Append | Debug/info/error logging | **MEDIUM** — may contain API error details |
| `.scorpiox/sessions/<id>/events.jsonl` | Append | Structured event log | **MEDIUM** |
| `.scorpiox/sessions/<id>/trace.jsonl` | Append | Data flow trace | **MEDIUM** — tool inputs/outputs |
| `.scorpiox/sessions/<id>/config-snapshot.txt` | Write | Config dump at session start | **HIGH** — may contain API keys |
| `.scorpiox/sessions/<id>/meta.json` | Write | Session metadata | LOW |
| `.scorpiox/sessions/<id>/traffic/raw/*.txt` | Write | Raw HTTP request/response | **HIGH** — API payloads |
| `.scorpiox/conversations/<id>.json` | Read/Write | Persistent conversation storage | **HIGH** |

### 3.3 Email Server Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| Email accounts file (configurable) | Read | `user:sha256_hash` pairs | **HIGH** — password hashes |
| Maildir `{cur,new,tmp}/` | Read/Write | Email storage (Maildir format) | **HIGH** — email contents |
| `~/.scorpiox/server-email.log` | Append | Email server daemon log | **MEDIUM** |
| TLS cert/key files (configurable) | Read | TLS certificates and private keys | **CRITICAL** |
| DKIM private key (configurable) | Read | DKIM signing key | **CRITICAL** |

### 3.4 Multiplexer Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| `/tmp/sxmux/sxmux-<name>.sock` | Create/Delete | Unix domain socket for session | LOW |
| `/tmp/sxmux/sxmux-<name>.pid` | Read/Write/Delete | PID file for session | LOW |

### 3.5 WhatsApp Bridge Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| `.scorpiox/whatsapp/auth/creds.json` | Read/Write | WhatsApp auth credentials | **CRITICAL** |
| `.scorpiox/whatsapp/inbox/` | Write | Incoming messages | **HIGH** — message contents |

### 3.6 Other Files

| File | Operation | Purpose | Sensitivity |
|------|-----------|---------|-------------|
| `.scorpiox/sessions/<id>/required_skills.txt` | Read/Write | Agent skill requirements | LOW |
| `/tmp/sx_emit_*_*.txt` | Write | Temporary session emit files | **MEDIUM** — session data |
| `/tmp/sx-edit-*.txt` | Create/Read/Delete | Temporary editor files | **MEDIUM** — user input |
| `.scorpiox/traffics/<timestamp>/` | Write | Traffic capture output | **HIGH** |
| `.gitignore` | Read/Append | Git ignore management | LOW |
| `/var/log/scorpiox-dns/` | Append | DNS audit logs | **MEDIUM** — query data |

---

## 4. PII Assessment

### 4.1 Data Collected and Transmitted

The **usage tracking** system (`scorpiox-usage.c`) sends the following to `code.scorpiox.net/usage-send`:

| Field | Type | PII Risk |
|-------|------|----------|
| `hostname` | Machine identifier | **MEDIUM** — correlatable |
| `username` | OS username | **HIGH** — direct PII |
| `os`, `arch`, `os_version` | System info | LOW |
| `session_id` | Session identifier | LOW |
| `provider`, `model` | Service info | LOW |
| `project`, `branch` | Development context | **MEDIUM** — business context |
| `scorpiox_version` | Version string | LOW |
| `input_tokens`, `output_tokens` | Usage metrics | LOW |

**Mitigation:** Usage tracking is configurable (`USAGE_TRACKING=0` to disable, default: 0 in embedded). Session emit tracking is also opt-in (`EMIT_SESSION_TRACKING`, default: 0).

### 4.2 Email Server PII

The email server inherently handles PII:
- Email addresses (From/To headers)
- Email body content
- User credentials (username + password hash)
- Failed login usernames are logged: `SX_WARN("[auth] failed login for user: %s", user)`
- Unknown user names are logged: `SX_WARN("[auth] unknown user: %s", user)`

### 4.3 Conversation Data

All user prompts and AI responses are stored in plaintext JSON files under `.scorpiox/sessions/` and `.scorpiox/conversations/`. No encryption at rest is applied. Users may inadvertently share passwords, tokens, or other secrets in conversations, which are then persisted to disk.

---

## 5. Credential Management

### 5.1 CRITICAL: Hardcoded Secrets in Embedded Config

**File:** `scorpiox/libsxutil/sx_config_embedded.c`  
**Severity:** 🔴 CRITICAL

The WASM embedded config contains hardcoded API keys and SSH credentials compiled into the binary:

| Key | Value (Redacted) | Risk |
|-----|----------|------|
| `ANTHROPIC_ANTIGRAVITY_KEY` | `sk-6088a10...` (full key) | **CRITICAL** — hardcoded API key |
| `ANTHROPIC_ZAI_KEY` | `9c6fba5d...ue19jY48d9GmddqX` (full key) | **CRITICAL** — hardcoded API key |
| `GEMINI_API_KEY` | `AIzaSyDs...IQHVA8` (full key) | **CRITICAL** — hardcoded API key |
| `CLAUDE_CODE_SSH_PASS` | `xboxone` | **CRITICAL** — hardcoded SSH password |
| `CLAUDE_CODE_SSH_HOST` | `192.168.1.6` | **HIGH** — internal infrastructure |
| `CLAUDE_CODE_SSH_PORT` | `22223` | **MEDIUM** |
| `CLAUDE_CODE_SSH_USER` | `root` | **HIGH** — root access |
| `TCP_HOST` | `20.53.240.54` | **MEDIUM** — infrastructure IP |
| `TMUX_REMOTE_HOST` | `root@192.168.1.3` | **HIGH** — internal infrastructure |
| `TMUX_SMB_SHARE` | `//192.168.1.3/GitHub` | **MEDIUM** — internal SMB share |

These secrets are extractable from the compiled WASM binary by any user.

### 5.2 Config File Credential Storage

**File:** `scorpiox/libsxutil/sx_config.c`  
**Severity:** 🟠 HIGH

The `scorpiox-env.txt` config cascade stores credentials in plaintext:

```
ANTHROPIC_API_KEY=sk-...
CLAUDE_CODE_SSH_PASS=...
CODEX_SSH_PASS=...
SMTP_PASS=...
GEMINI_API_KEY=AIza...
OPENAI_API_KEY=sk-...
```

**Issues:**
- Config files created with default `0755` directory permissions (via `sx_mkdir`) — too permissive for credential storage
- No file-level encryption of sensitive values
- Config snapshot written to session directory may expose keys

### 5.3 Non-Embedded Defaults

The non-embedded config defaults (`sx_config.c`) are mostly empty for sensitive keys:
- `ANTHROPIC_API_KEY` → `""` ✅
- `OPENAI_API_KEY` → `"xxx"` ⚠️ (placeholder but non-empty)
- All SSH passwords → `""` ✅

### 5.4 API Key Handling in Providers

| Provider | Key Source | In-Memory Storage | Header Redaction in Logs |
|----------|-----------|-------------------|------------------------|
| Anthropic (`sx_provider_anthropic.c`) | Config `API_KEY` / `ANTHROPIC_API_KEY` | Stack `char api_key[512]` | N/A (no traffic logging) |
| Claude Code (`sx_provider_claude_code.c`) | OAuth token via fetchtoken | Heap `char oauth_token[2048]` | ✅ `[REDACTED]` in traffic logs |
| Gemini (`scorpiox-gemini.c`) | Env `GEMINI_API_KEY` | Stack variable | ✅ `key=[REDACTED]` in traffic logs |
| OpenAI (`scorpiox-openai.c`) | Env `OPENAI_API_KEY` | Stack via `http_post()` param | ⚠️ URL logged without key redaction |

### 5.5 Token Fetch Mechanism

`scorpiox-claudecode-fetchtoken.c` fetches OAuth tokens via:
1. **Raw TCP** (no TLS) to `proxy.scorpiox.net:9800` — **HIGH RISK**: tokens transmitted in cleartext
2. SSH tunnel to remote host
3. HTTP endpoint

---

## 6. Encryption Usage

### 6.1 TLS Implementation (Email Server)

**Library:** mbedTLS (vendored)  
**File:** `scorpiox/sxmail_tls.c`

- Uses `mbedtls_ssl_config`, `mbedtls_x509_crt`, `mbedtls_pk_context`
- Entropy sourced from `mbedtls_entropy_func` → `mbedtls_ctr_drbg_seed`
- TLS configuration for both SMTP STARTTLS and implicit TLS (IMAP)
- Supports TLS accept (server) and upgrade (STARTTLS)
- ✅ Proper TLS implementation using mbedTLS

### 6.2 DKIM Signing

**File:** `scorpiox/sxmail_dkim.c`

- Algorithm: `rsa-sha256`
- Canonicalization: `relaxed/relaxed`
- Uses mbedTLS `mbedtls_pk_context`, `mbedtls_sha256`, `mbedtls_base64`
- CSPRNG via `mbedtls_ctr_drbg`
- ✅ Standard RFC 6376 implementation

### 6.3 Password Hashing

**File:** `scorpiox/sxmail_auth.c`  
**Severity:** 🟠 HIGH

```c
int sxmail_auth_hash_password(const char *pass, char *out, size_t out_sz) {
    unsigned char digest[32];
    mbedtls_sha256((const unsigned char *)pass, strlen(pass), digest, 0);
    // ... hex encode ...
}
```

**Issues:**
- ❌ **Unsalted SHA256** — vulnerable to rainbow tables and precomputation attacks
- ❌ **No key stretching** — SHA256 is too fast for password hashing; should use bcrypt, scrypt, or Argon2
- ❌ **No per-user salt** — identical passwords produce identical hashes

**Positive:** `sxmail_auth_free()` properly zeroes sensitive data with `memset()` before `free()`.

### 6.4 Data at Rest Encryption

- ❌ No encryption at rest for conversation data
- ❌ No encryption at rest for config files (including API keys)
- ❌ No encryption at rest for email storage (Maildir)
- ❌ No encryption at rest for session logs/traces

---

## 7. Temporary File Security

### 7.1 Editor Temp Files

**File:** `scorpiox/sx.c`, line 612

```c
snprintf(tmpfile, sizeof(tmpfile), "%s%csx-edit-%d.txt", ...);
FILE *f = fopen(tmpfile, "wb");
```

- ⚠️ Uses predictable filenames (`sx-edit-<pid>.txt`) — susceptible to symlink attacks
- ❌ Does not use `mkstemp()` for secure temp file creation
- File is cleaned up after use (read back and deleted)

### 7.2 Session Emit Temp Files

**File:** `scorpiox/sx.c`, line 1285

```c
snprintf(tmp_file, sizeof(tmp_file), "/tmp/sx_emit_%s_%04d.txt", ...);
```

- ⚠️ Predictable filename in world-accessible `/tmp`
- ❌ No `mkstemp()` usage

### 7.3 Maildir Temp Files

**File:** `scorpiox/sxmail_maildir.c`

- ✅ Uses Maildir standard `tmp/` → `new/` atomic rename pattern
- ✅ Temp files are cleaned up on error (`remove(tmp_path)`)
- ⚠️ Unique filenames based on timestamp+counter+PID — reasonably unique but not cryptographically random

### 7.4 Multiplexer Socket/PID Files

- ✅ Socket directory created with `0700` permissions
- ✅ Stale PID files and sockets are cleaned up
- ✅ Socket path in `/tmp/sxmux/` (restricted directory)

---

## 8. Logging Analysis

### 8.1 Logging Framework

**Files:** `scorpiox/libsxutil/sx_log.c`, `sx_log.h`

- Levels: ERROR, WARN, INFO, DEBUG, TRACE
- Output: configurable file (append mode) or stderr
- Timestamps with millisecond precision
- Session-specific log files (`.scorpiox/sessions/<id>/session.log`)

### 8.2 Sensitive Data in Logs

| What | Where | Logged? | Risk |
|------|-------|---------|------|
| API keys | Provider init | Masked (`***`) | ✅ Safe |
| OAuth tokens | Traffic logs | `[REDACTED]` | ✅ Safe |
| Gemini API key in URL | Traffic logs | `key=[REDACTED]` | ✅ Safe |
| Failed login usernames | Email auth | Full username logged | ⚠️ **MEDIUM** |
| SSH passwords | Config loading | Not explicitly logged | ✅ Safe |
| Config values | DEBUG level | May include sensitive values | ⚠️ **MEDIUM** if DEBUG enabled |
| Usage payloads | DEBUG level | `SX_DEBUG("usage: payload: %s", json)` — includes hostname, username | ⚠️ **MEDIUM** |
| Config snapshot | Session file | Full config dump to file | 🟠 **HIGH** — may include keys |

### 8.3 Config Snapshot Risk

`sx_session_write_config_snapshot()` writes the full configuration to `config-snapshot.txt` in the session directory. If API keys are configured, they will be written to this file in plaintext.

---

## 9. Environment Variable Usage

### 9.1 Sensitive Environment Variables

| Variable | Used In | Sensitivity |
|----------|---------|-------------|
| `ANTHROPIC_API_KEY` | `sx_provider_anthropic.c` | **CRITICAL** — API secret |
| `GEMINI_API_KEY` | `scorpiox-gemini.c` | **CRITICAL** — API secret |
| `OPENAI_API_KEY` | `scorpiox-openai.c` | **CRITICAL** — API secret |
| `AGENTS_PAT` | `scorpiox-agent.c` | **CRITICAL** — Git PAT token |
| `CLAUDE_CODE_SSH_PASS` | config system | **HIGH** — SSH password |
| `IMAGE_BASE_URL` | `scorpiox-wsl.c`, `scorpiox-vm.c` | **MEDIUM** — download source |
| `UPDATE_URL` | `scorpiox-wsl.c` | **MEDIUM** — update source |

### 9.2 All Environment Variables Read

The codebase reads **59 unique environment variables** via `getenv()`. Notable categories:

- **Authentication:** `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `OPENAI_API_KEY`, `AGENTS_PAT`
- **User identity:** `USER`, `USERNAME`, `LOGNAME`, `HOME`, `USERPROFILE`
- **System:** `SHELL`, `EDITOR`, `VISUAL`, `TERM`, `PATH`, `TZ`, `PROCESSOR_ARCHITECTURE`
- **Application:** `SCORPIOX_HOME`, `SCORPIOX_BRANCH`, `CONTAINER_PACKAGES`, `SCORPIOX_PERF`
- **Search config:** `SCORPIOX_SEARCH_WAIT`, `SCORPIOX_SEARCH_ENGINES`, `SCORPIOX_SEARCH_NUM`
- **Traffic:** `OPENAI_TRAFFIC_DIR`, `OPENAI_TRAFFIC_SEQ`, `GEMINI_TRAFFIC_DIR`, `GEMINI_TRAFFIC_SEQ`
- **Container:** `CONTAINER_PACKAGES`, `LOCALAPPDATA`, `TEMP`, `TMP`, `TMPDIR`
- **Agent:** `AGENTS_BASE_DIR`, `AGENTS_CWD`, `AGENTS_INSTANCE_ID`, `AGENTS_REPO_URL`
- **Misc:** `MCP`, `MCP_FILE`, `INIT_TOOLS`, `INVOKED_AGENT_NAME`, `PARENT_MESSAGES_DIR`

### 9.3 PAT Masking

**File:** `scorpiox-unshare.c`, line 2410–2424

The `--pat` argument value is partially masked in log output (first 3 chars shown, rest replaced). ✅ Good practice, though incomplete (should mask entirely).

---

## 10. Data Retention

### 10.1 Session Cleanup

- Configurable via `SESSION_RETENTION_DAYS` (default: 7 days)
- `sx_session_cleanup_old()` deletes sessions older than retention period
- Called during normal operation

### 10.2 Unmanaged Data Retention

The following data has **no automated cleanup**:

| Data | Location | Concern |
|------|----------|---------|
| Conversation files | `.scorpiox/conversations/*.json` | Accumulate indefinitely |
| WhatsApp auth/inbox | `.scorpiox/whatsapp/` | Credentials persist until manual logout |
| Traffic captures | `.scorpiox/traffics/` | Manual cleanup only (`--clear` flag) |
| DNS audit logs | `/var/log/scorpiox-dns/` | No rotation configured |
| Email server log | `~/.scorpiox/server-email.log` | Grows indefinitely (append mode) |
| Maildir email storage | Configurable path | No automatic purging |
| Temp files in `/tmp/` | `/tmp/sx_emit_*`, `/tmp/sx-edit-*` | Rely on OS cleanup |

---

## 11. Risk Assessment

### Critical Findings

| # | Finding | Severity | Location | Recommendation |
|---|---------|----------|----------|----------------|
| 1 | **Hardcoded API keys and SSH passwords in embedded config** | 🔴 CRITICAL | `sx_config_embedded.c` | Remove all secrets from source code; use runtime-only configuration |
| 2 | **Plaintext API keys in config files** with 0755 directory permissions | 🟠 HIGH | `sx_config.c` | Encrypt sensitive values or use OS keychain; restrict permissions to 0600 |
| 3 | **Unsalted SHA256 password hashing** for email auth | 🟠 HIGH | `sxmail_auth.c` | Replace with bcrypt/scrypt/Argon2 with per-user salt |
| 4 | **Raw TCP token fetch** without TLS | 🟠 HIGH | `scorpiox-claudecode-fetchtoken.c` | Require TLS for all token transmission |
| 5 | **Config snapshot may contain API keys** | 🟠 HIGH | `sx_session.c` | Redact sensitive config keys before writing snapshot |
| 6 | **Predictable temp file names** in `/tmp/` | 🟡 MEDIUM | `sx.c` | Use `mkstemp()` for all temporary files |
| 7 | **No encryption at rest** for conversations, sessions, email | 🟡 MEDIUM | Multiple | Consider encrypted storage for sensitive data |
| 8 | **OpenAI URL logged without key redaction** | 🟡 MEDIUM | `scorpiox-openai.c` | Add key redaction to URL logging |
| 9 | **Failed login usernames logged** | 🟡 MEDIUM | `sxmail_auth.c` | Consider rate-limiting log volume; don't log full usernames at WARN |
| 10 | **Usage tracking sends hostname/username** to remote server | 🟡 MEDIUM | `scorpiox-usage.c` | Hash or anonymize before transmission |

### Positive Findings

| # | Finding | Location |
|---|---------|----------|
| 1 | ✅ OAuth tokens properly redacted in Claude Code traffic logs | `sx_provider_claude_code.c` |
| 2 | ✅ Gemini API key redacted in traffic logs | `scorpiox-gemini.c` |
| 3 | ✅ API keys masked as `***` in provider init logging | `sx_provider_anthropic.c` |
| 4 | ✅ Auth entry memory zeroed before free | `sxmail_auth.c` |
| 5 | ✅ Multiplexer socket directory created with 0700 permissions | `sxmux_session.c` |
| 6 | ✅ Maildir uses atomic tmp→new rename pattern | `sxmail_maildir.c` |
| 7 | ✅ TLS properly implemented via mbedTLS | `sxmail_tls.c` |
| 8 | ✅ DKIM signing uses standard RSA-SHA256 | `sxmail_dkim.c` |
| 9 | ✅ Usage/session tracking is opt-in (disabled by default) | `sx_config.c` |
| 10 | ✅ Session retention with automated cleanup | `sx_session.c` |
| 11 | ✅ PAT argument partially masked in logs | `scorpiox-unshare.c` |

---

## 12. Recommendations Summary

### Immediate (P0)

1. **Remove all hardcoded secrets** from `sx_config_embedded.c` — rotate all exposed keys immediately
2. **Upgrade password hashing** from SHA256 to Argon2id with per-user random salt
3. **Add TLS** to the TCP token fetch path

### Short-term (P1)

4. **Restrict config file permissions** to `0600` (owner-only read/write)
5. **Redact sensitive keys** from config-snapshot.txt before writing
6. **Use `mkstemp()`** for all temporary file creation
7. **Add key redaction** to OpenAI traffic URL logging

### Medium-term (P2)

8. **Implement encrypted storage** for config secrets (OS keychain integration or file encryption)
9. **Add log rotation** for email server and DNS audit logs
10. **Add automated cleanup** for conversation files and traffic captures
11. **Anonymize telemetry data** (hash hostname/username before sending)

---

*End of Data Handling Audit Report*
