A remote Telegram user can write files to arbitrary paths inside an agent's persistent workspace volume (praktor-wk-<workspace>, mounted at /workspace/agent), escaping the documented uploads/ directory.
The attacker controls the Telegram document filename, which was concatenated into the destination path without sanitization (internal/telegram/bot.go, at both upload sites) and resolved with path.Join, which collapses ../ sequences. A filename like ../../../CLAUDE.md resolved to the root of the agent workspace volume, outside uploads/.
Because the agent workspace is the persistent working directory the Claude agent reads from and operates on across runs, writing outside uploads/ lets an attacker plant or overwrite files the agent later consumes — e.g. CLAUDE.md, agent instruction/skill/hook files, or other config under /workspace/agent. This turns a file upload into a stored injection into the agent's instruction/execution surface (CWE-22 path traversal escalating to stored instruction injection).
By default the bot has no user allowlist (allow_from: [] means "allow all"), so the only precondition is that a user can message the bot. No authentication or prior privilege is required.
Through v0.9.0 (and HEAD 3902d29).
v0.9.1, containing PR #228.
Restrict telegram.allow_from to trusted user IDs to limit who can send uploads to the bot. Upgrading to v0.9.1 is the recommended fix.
internal/telegram/bot.go: apply path.Base() to the attacker-controlled filename at both upload sites, stripping directory components and ...internal/container/manager.go: WriteVolumeBytes now rejects any path that escapes /vol after path.Join, protecting future callers.Reported privately by tonghuaroot, who provided a detailed root-cause analysis, a deployed end-to-end proof of concept against the real container.Manager, and fix verification.
{
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-11-03T17:27:25Z",
"nvd_published_at": "2026-10-30T19:18:33Z",
"severity": "HIGH"
}