| Version | Supported |
|---|---|
| Latest release | Yes |
| Older releases | No |
Only the latest published release receives security fixes. Please upgrade before reporting.
Do not open a public issue. Instead, use one of these channels:
- Email: security@littlebearapps.com
- GitHub Security Advisories: Report a vulnerability
Include:
- Description of the vulnerability
- Steps to reproduce
- Untether version and Python version
- Any relevant logs (redact credentials)
| Step | Target |
|---|---|
| Acknowledgement | Within 48 hours |
| Initial assessment | Within 5 business days |
| Fix for critical issues | Within 7 days |
| Public disclosure | After fix is released |
In scope:
- Untether application code
- Configuration parsing and validation
- Telegram transport security
- Subprocess management and session handling
Out of scope:
- Upstream agent CLIs (Claude Code, Codex, OpenCode, Pi) — report to their respective maintainers
- Telegram Bot API — report to Telegram
- Bot token management — token security is the operator's responsibility
- Issues requiring physical access to the host machine
v0.35.3 ships a follow-on hardening bundle on top of v0.35.2. Upgrade notes:
- BREAKING — empty
allowed_user_idsrejected at startup (#377). Previously the empty default meant any Telegram user who knew the bot username could send commands. Untether now refuses to start withConfigError: [transports.telegram] allowed_user_ids is empty …. Operators who genuinely need an open bot (demos, hackathons, dev) must opt in explicitly withallow_any_user = true, which is logged INFO every boot (security.allow_any_user). See Security how-to. - AMP
dangerously_allow_alldefault flipped tofalse(#206). AMP runs no longer skip its built-in permission system unless the operator opts in. - Pi session directory locked to
0o700(#207). Other users on shared hosts can no longer read Pi session JSONL. voice_transcription_api_keyis nowSecretStr(#378) — parity withbot_token. Masked in repr/str/tracebacks and structlog serialisation.- Prompt content removed from INFO logs (#205, #478) —
runner.startno longer carriesprompt[:100]. A debug-onlyrunner.start_promptevent is available when explicitly enabled. /file getTOCTOU window closed (#211) — single-open + bounded read in a worker thread.- stderr sanitisation regex extended (#208) — covers macOS (
/Users/…,/private/var/…), container roots (/app/,/workspace/), and other absolute paths beyond/home/<user>/. - OpenAI project-key redaction (#213) — structlog redaction now covers
sk-proj-…keys (the genericsk-…regex didn't match the project-key char set). - Daily cost tracker race fixed (#379) — the unguarded read-modify-write that could lose a run's cost (and bypass the per-day budget cap) is now wrapped in a lock.
- Pygments bumped 2.19.2 → 2.20.0 (#402) — clears CVE-2026-4539 (ReDoS in
AdlLexer). - Auto-approve scope re-audit (#380) —
ControlRewindFilesRequestandControlMcpMessageRequestre-verified safe under the upstream Claude Code 2.1.x trust model. Regression-lock tests fail loudly if the auto-approve path starts inspecting payloads. Audit memo atdocs/audits/2026-04-27-380-auto-approve-scope-review.md. - User-extensible env allowlist (#409) —
[security] env_extra_allowandenv_extra_prefix_allowlet operators thread credential-manager tokens (1Password, Doppler, Vault, Infisical) into engine subprocesses without forking.BWS_ACCESS_TOKENis now in the built-in defaults.
See CHANGELOG v0.35.3 for the full entry list.
v0.35.2 ships a security hardening bundle. Upgrade notes:
- Env allowlist for Claude/Pi subprocesses — only approved variables pass through; unrelated process env no longer leaks to agent CLIs. (#198)
- Runtime env hardening (always on) — Claude exec is wrapped with
env -i KEY=VAL …so the resolved environment is exactly the allowlist fromutils/env_policy.filtered_env(), even if an upstream rc-file source or wrapper script would otherwise re-introduce host vars aftersubprocess.spawn(env=…)is honoured. This hardening is not controlled by any config setting. - Runtime env audit — gated by
[security] env_audit = true(default). Samples/proc/<claude_pid>/environonce per session and emits aclaude.env_audit.leaked_varWARNING for every non-allowlisted variable observed. Disabling the audit only silences the warning sampler — it does not disable theenv -ihardening above. (#361) bot_tokenstored asSecretStr— masked in repr/str/tracebacks; unwrapped only at the transport boundary. (#196)- User-safe error messages — voice transcription and command-dispatch failures route through
user_safe_error()(strips URLs/paths, caps length, fallback on empty). (#200, #201) - Codex auth output HTML-escaped — prevents entity injection before
<pre>wrapping. (#199) - Download URL path validation — blocks
://,.., and leading/before URL construction. (#204) - Duplicate-request dedup via LRU — bounded
OrderedDict(max 200) closes a small race that the previous wholesale-clear approach left open. (#197) - Registry ephemeral sweep —
_EPHEMERAL_MSGS/_OUTLINE_REGISTRYentries older than 1 hour are pruned on a 60 s tick. (#203) - CI matrix interpolation moved to
env:— eliminates a shell-injection vector in the release pipeline. (#195) - Subprocess sites annotated inline — global
B603/B607bandit skips removed; each call site carries its own# nosecjustification. (#202)
See CHANGELOG v0.35.2 for the full entry list.
We follow coordinated disclosure. We ask that you:
- Allow us reasonable time to investigate and fix the issue
- Do not exploit the vulnerability beyond what is needed for the report
- Do not disclose publicly until a fix is available
We credit reporters in the release notes (unless you prefer to remain anonymous).