Security Finding
Severity: low
Type: unsafe-pattern (path traversal — unvalidated session name in log path)
pluk attach validates session names against ^[A-Za-z0-9._-]+$ (validateSessionName, src/attach.ts), but pluk subscribe / pluk-subscribe does not. Subscriber.logFile (src/subscriber.ts) builds the tail path as:
join(this.runDir, 'logs', `${this.session}.jsonl`)
so a session argument containing / or .. escapes the private run directory entirely: pluk subscribe ../../../../home/user/anything tails <...>/anything.jsonl anywhere on disk, and subscribe() is also exported as library API with the same hole.
Impact
Pluk runs with the invoking user's privileges, so this is not a privilege escalation by itself — but session names are frequently plumbed from config files, hive kick messages, and other automation (the README wires pluk subscribe <session> into agent supervisors). Any caller that forwards an attacker-influenced session string turns into an arbitrary-path .jsonl tail primitive outside the 0700 run dir that run-dir.ts works hard to guarantee, silently waiting up to 60s for the target file to appear. It also breaks the ownership/symlink invariants (ensurePrivateDirectory/ensurePrivateLogFile) that attach enforces for everything under logs/.
Recommendation
Enforce the existing SAFE_SESSION_PATTERN at the Subscriber constructor (covers both the CLI and the exported subscribe() API), sharing the validator that attach already uses. Fix PR to follow (hold-gated).
Filed by sec-check agent (ACMM L4/L5 — hold-gated mode)
🐝 Hive Agent: security | Instance: hosted-available-oke-11-placeholder-r05x | SHA: unknown
— hive: agent=sec-check backend=copilot model=claude-fable-5 copilot=1.0.88
Security Finding
Severity: low
Type: unsafe-pattern (path traversal — unvalidated session name in log path)
pluk attachvalidates session names against^[A-Za-z0-9._-]+$(validateSessionName, src/attach.ts), butpluk subscribe/pluk-subscribedoes not.Subscriber.logFile(src/subscriber.ts) builds the tail path as:so a session argument containing
/or..escapes the private run directory entirely:pluk subscribe ../../../../home/user/anythingtails<...>/anything.jsonlanywhere on disk, andsubscribe()is also exported as library API with the same hole.Impact
Pluk runs with the invoking user's privileges, so this is not a privilege escalation by itself — but session names are frequently plumbed from config files, hive kick messages, and other automation (the README wires
pluk subscribe <session>into agent supervisors). Any caller that forwards an attacker-influenced session string turns into an arbitrary-path.jsonltail primitive outside the 0700 run dir that run-dir.ts works hard to guarantee, silently waiting up to 60s for the target file to appear. It also breaks the ownership/symlink invariants (ensurePrivateDirectory/ensurePrivateLogFile) that attach enforces for everything underlogs/.Recommendation
Enforce the existing
SAFE_SESSION_PATTERNat theSubscriberconstructor (covers both the CLI and the exportedsubscribe()API), sharing the validator that attach already uses. Fix PR to follow (hold-gated).Filed by sec-check agent (ACMM L4/L5 — hold-gated mode)
🐝 Hive Agent:
security| Instance:hosted-available-oke-11-placeholder-r05x| SHA:unknown— hive: agent=sec-check backend=copilot model=claude-fable-5 copilot=1.0.88