Path traversal: unsanitized provider id flows into credential storage path #9

Open
opened 2026-07-23 18:38:34 +00:00 by claude-bot · 0 comments
Collaborator

Severity: Medium

packages/core/src/auth/store.ts:13packages/core/src/storage/index.ts:19

keyFor(provider) = `auth/${provider}`          // provider comes from argv
pathFor(key)     = `${this.root}/${key}.json`  // no normalization

credentialIdFor (packages/core/src/provider/catalog.ts:155) returns the raw provider string when it is not in the catalog. So thorny auth login ../../../etc/foo resolves to a path outside the store root — enabling arbitrary .json read (get), write (set), and delete (remove). The same untrusted-key-into-path pattern applies to any storage key built from external input.

Impact

Local and partly self-inflicted, but a real input-validation gap: think a copy-pasted command from a malicious README, or a wrapper script that forwards an attacker-controlled provider name.

Fix

  • Validate provider ids against ^[a-z0-9._-]+$ (reject / and ..) before they reach the store, or
  • Resolve the final path and confine it under root before any fs operation.

Found via security audit.

**Severity: Medium** `packages/core/src/auth/store.ts:13` → `packages/core/src/storage/index.ts:19` ``` keyFor(provider) = `auth/${provider}` // provider comes from argv pathFor(key) = `${this.root}/${key}.json` // no normalization ``` `credentialIdFor` (`packages/core/src/provider/catalog.ts:155`) returns the raw provider string when it is not in the catalog. So `thorny auth login ../../../etc/foo` resolves to a path outside the store root — enabling arbitrary `.json` read (`get`), write (`set`), and delete (`remove`). The same untrusted-key-into-path pattern applies to any storage key built from external input. ### Impact Local and partly self-inflicted, but a real input-validation gap: think a copy-pasted command from a malicious README, or a wrapper script that forwards an attacker-controlled provider name. ### Fix - Validate provider ids against `^[a-z0-9._-]+$` (reject `/` and `..`) before they reach the store, **or** - Resolve the final path and confine it under `root` before any fs operation. Found via security audit.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
brodycritchlow/thorny#9
No description provided.