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.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
| 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 |
| File | Operation | Purpose | Sensitivity |
|---|---|---|---|
.scorpiox/sessions/ | Read/Write | Full conversation history | HIGH — may contain user secrets shared in chat |
.scorpiox/sessions/ | Append | Debug/info/error logging | MEDIUM — may contain API error details |
.scorpiox/sessions/ | Append | Structured event log | MEDIUM |
.scorpiox/sessions/ | Append | Data flow trace | MEDIUM — tool inputs/outputs |
.scorpiox/sessions/ | Write | Config dump at session start | HIGH — may contain API keys |
.scorpiox/sessions/ | Write | Session metadata | LOW |
.scorpiox/sessions/ | Write | Raw HTTP request/response | HIGH — API payloads |
.scorpiox/conversations/ | Read/Write | Persistent conversation storage | HIGH |
| 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 |
| File | Operation | Purpose | Sensitivity |
|---|---|---|---|
/tmp/sxmux/sxmux- | Create/Delete | Unix domain socket for session | LOW |
/tmp/sxmux/sxmux- | Read/Write/Delete | PID file for session | LOW |
| File | Operation | Purpose | Sensitivity |
|---|---|---|---|
.scorpiox/whatsapp/auth/creds.json | Read/Write | WhatsApp auth credentials | CRITICAL |
.scorpiox/whatsapp/inbox/ | Write | Incoming messages | HIGH — message contents |
| File | Operation | Purpose | Sensitivity |
|---|---|---|---|
.scorpiox/sessions/ | 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/ | Write | Traffic capture output | HIGH |
.gitignore | Read/Append | Git ignore management | LOW |
/var/log/scorpiox-dns/ | Append | DNS audit logs | MEDIUM — query data |
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 |
USAGE_TRACKING=0 to disable, default: 0 in embedded). Session emit tracking is also opt-in (EMIT_SESSION_TRACKING, default: 0).
The email server inherently handles PII:
SX_WARN("[auth] failed login for user: %s", user)SX_WARN("[auth] unknown user: %s", user)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.
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.
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:
0755 directory permissions (via sx_mkdir) — too permissive for credential storageThe non-embedded config defaults (sx_config.c) are mostly empty for sensitive keys:
ANTHROPIC_API_KEY → "" ✅OPENAI_API_KEY → "xxx" ⚠️ (placeholder but non-empty)"" ✅| 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 |
scorpiox-claudecode-fetchtoken.c fetches OAuth tokens via:
proxy.scorpiox.net:9800 — HIGH RISK: tokens transmitted in cleartextscorpiox/sxmail_tls.c
mbedtls_ssl_config, mbedtls_x509_crt, mbedtls_pk_contextmbedtls_entropy_func → mbedtls_ctr_drbg_seedscorpiox/sxmail_dkim.c
rsa-sha256relaxed/relaxedmbedtls_pk_context, mbedtls_sha256, mbedtls_base64mbedtls_ctr_drbgscorpiox/sxmail_auth.c
Severity: 🟠 HIGH
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:
sxmail_auth_free() properly zeroes sensitive data with memset() before free().
scorpiox/sx.c, line 612
snprintf(tmpfile, sizeof(tmpfile), "%s%csx-edit-%d.txt", ...);
FILE *f = fopen(tmpfile, "wb");
sx-edit-.txt ) — susceptible to symlink attacksmkstemp() for secure temp file creationscorpiox/sx.c, line 1285
snprintf(tmp_file, sizeof(tmp_file), "/tmp/sx_emit_%s_%04d.txt", ...);
/tmpmkstemp() usagescorpiox/sxmail_maildir.c
tmp/ → new/ atomic rename patternremove(tmp_path))0700 permissions/tmp/sxmux/ (restricted directory)scorpiox/libsxutil/sx_log.c, sx_log.h
.scorpiox/sessions//session.log )| 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 |
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.
| 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 |
The codebase reads 59 unique environment variables via getenv(). Notable categories:
ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY, AGENTS_PATUSER, USERNAME, LOGNAME, HOME, USERPROFILESHELL, EDITOR, VISUAL, TERM, PATH, TZ, PROCESSOR_ARCHITECTURESCORPIOX_HOME, SCORPIOX_BRANCH, CONTAINER_PACKAGES, SCORPIOX_PERFSCORPIOX_SEARCH_WAIT, SCORPIOX_SEARCH_ENGINES, SCORPIOX_SEARCH_NUMOPENAI_TRAFFIC_DIR, OPENAI_TRAFFIC_SEQ, GEMINI_TRAFFIC_DIR, GEMINI_TRAFFIC_SEQCONTAINER_PACKAGES, LOCALAPPDATA, TEMP, TMP, TMPDIRAGENTS_BASE_DIR, AGENTS_CWD, AGENTS_INSTANCE_ID, AGENTS_REPO_URLMCP, MCP_FILE, INIT_TOOLS, INVOKED_AGENT_NAME, PARENT_MESSAGES_DIRscorpiox-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).
SESSION_RETENTION_DAYS (default: 7 days)sx_session_cleanup_old() deletes sessions older than retention periodThe 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 |
| # | 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 |
| # | 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 |
sx_config_embedded.c — rotate all exposed keys immediately0600 (owner-only read/write)mkstemp() for all temporary file creation