# Triage Report: laude-institute/headlong
REAL THREATS
Authentication & Authorization Bypass (Web Server)
[8] Remote Code Execution via Unauthenticated Self-Update
The
/api/update endpoint executes
git pull --ff-only and restarts the server without any authentication. While gated by an environment flag (
HEADLONG_WEB_SELF_UPDATE=1), once enabled it accepts requests from any localhost process. If the git remote has been compromised or an attacker gains any local access, they can trigger arbitrary code deployment and execution.
[9] Unauthenticated Identity Data Exfiltration
/api/identities/{identity_id}/export serves complete identity archives (memories, trajectories, .env files with potential secrets) with zero authentication. Any process on localhost can enumerate and download all identity data.
[13] Denial of Service via Killall
/api/killall terminates every Headlong process system-wide without authentication. On localhost-only deployments, any local user or compromised service can halt the entire platform.
[14] Environment Variable Injection
PUT /api/identities/{identity_id}/env writes arbitrary key-value pairs to identity
.env files without authentication. An attacker can inject
ANTHROPIC_API_KEY or override
MODEL settings to redirect LLM calls, exfiltrate data, or cause billing fraud.
State & Concurrency Issues
[3] State File Corruption on Crash
state.py:21 writes the offset directly without atomic rename. A crash mid-write leaves a truncated or corrupted file. On restart,
int(path.read_text()) can fail or load garbage, breaking message deduplication in the Telegram bot and potentially causing infinite loops or message loss.
[11] Race Condition in Identity Import
Concurrent import requests share a temp file created with
tempfile.mkstemp(). The function doesn't prevent two requests from writing to the same file descriptor simultaneously, leading to archive corruption and potential identity data loss or mixing.
[12] Race Condition in Identity Creation
Concurrent
POST /api/identities calls can mkdir and write to the same directory without locking, resulting in half-written configs, corrupted
info.txt, or unusable identities.
Operational & Configuration Issues
[1] Memory Exhaustion in Telegram Dedup Cache
The
_seen_msg_ids dict grows unbounded during message floods. While pruned on each new message (retaining 300s window), an attacker sending thousands of messages per second can force multi-GB memory growth before the next prune cycle, potentially OOM-killing the bot.
[4] Silent Authentication Failure
Defaulting missing
ANTHROPIC_API_KEY to empty string causes silent auth failures that may be obscured by shell pipelines. While not directly exploitable, it creates operational blind spots that mask real attacks or misconfigurations.
ATTACK CHAINS
Chain 1: Localhost Takeover → Full System Compromise
1. Attacker gains any localhost access (e.g., via browser exploit, SSRF from another service, or shared development machine)
2. [14] Inject malicious API key into identity .env → redirect LLM calls to attacker-controlled endpoint → exfiltrate all conversation data
3. [9] Export all identities → extract secrets, conversation history, and PII
4. [8] If HEADLONG_WEB_SELF_UPDATE=1, pull malicious code and restart → persistent RCE
5. [13] Or simply /api/killall to deny service
Chain 2: Multi-Request Race → Identity Corruption
1. [12] Send concurrent identity creation requests with same name
2. [11] Follow immediately with concurrent import requests
3. Result: corrupted identity directory, mixed archive data, potential secret leakage across identities
DROPPED FINDINGS (False Positives / Low Impact)
[2] HTML injection in Telegram - The rationale is truncated but describes proper escaping via
to_html(). Telegram's HTML mode is restricted to their safe subset; this is not XSS in a browser context.
FALSE POSITIVE.
[5] Path traversal in identity import - The function signature shows
archive: Path (typed), and without evidence of user-controlled input reaching this from an API endpoint, this is speculative.
INSUFFICIENT EVIDENCE.
[6][7] SSRF and path traversal in openrouter.py - No code snippet provided, only generic scanner output. Line 53/58 likely reference OpenRouter API calls (fixed endpoint) or model cache paths. Without seeing actual user input flow,
INSUFFICIENT EVIDENCE.
[10] Job download IDOR - UUIDs are cryptographically random (128-bit). While lack of auth is bad practice, guessing a UUID job_id has 2^-128 probability per attempt.
LOW EXPLOITABILITY (demoted from HIGH).
[15-25] Shell quoting issues - Standard shellcheck warnings. While these can cause issues with filenames containing spaces, they're code quality issues, not security vulnerabilities in this context.
ACCEPTED AS LOW.
[0] Insecure HTTP - INFO severity, single mention in Swift macOS app. Without context (could be localhost-only), and marked INFO by scanner.
ACCEPTED AS INFO.
VERDICT
This system is NOT safe to deploy in any multi-tenant or network-accessible environment.The web server effectively has
no authentication layer while exposing:
• Complete data exfiltration (identities, conversation histories, secrets)
• Environment manipulation (API key injection, model override)
• Code execution (if self-update is enabled)
• Denial of service
The implicit security model assumes "localhost-only = trusted," which fails catastrophically on:
• Shared development machines
• Systems running other web services (SSRF pivot points)
• Any scenario where an attacker achieves initial foothold
Must fix before ANY deployment:
1. [8][9][13][14] - Implement authentication middleware for ALL /api/* endpoints. At minimum, require a bearer token; ideally integrate with existing identity system.
2. [3] - Use atomic write pattern (write to temp, rename) for state file.
3. [11][12] - Add file locking or identity-level mutexes for import/create operations.
Should fix for production:
4. [1] - Add hard limit to dedup cache size (e.g., max 10K entries, LRU eviction).
5. [4] - Fail fast with clear error when API key is missing.
Risk assessment: Currently
CRITICAL for any deployment. With authentication and atomic writes:
MEDIUM (standard operational risks remain).