paperclipai/paperclip · error · Error
codex auth cache: ${label} is a relative path segment
Error message
codex auth cache: ${label} is a relative path segment What it means
Thrown by toSafePathSegment when a value used as a path segment is exactly "." or ".." after trimming. This is the relative-segment guard in the same path-traversal defense chain (Security condition 3) that protects the companies/<companyId>/.../<accountId>/auth.json cache layout from escaping its directory.
Source
Thrown at packages/adapters/codex-local/src/server/codex-auth-cache.ts:75
const raw = env[CODEX_AUTH_CACHE_OFF_SWITCH_ENV];
if (typeof raw !== "string") return true;
return !FALSY_ENV_RE.test(raw.trim());
}
/**
* Sanitizes one raw value to a single safe path segment. Rejects an empty value,
* a relative segment (`.` or `..`), a path separator (`/` or `\`), and a NUL
* byte, so the value can never become a path traversal. Returns the trimmed,
* safe segment. The `label` names the value in the error message. (Security
* condition 3.)
*/
function toSafePathSegment(value: string, label: string): string {
const trimmed = typeof value === "string" ? value.trim() : "";
if (trimmed.length === 0) {
throw new Error(`codex auth cache: ${label} is empty`);
}
if (trimmed === "." || trimmed === "..") {
throw new Error(`codex auth cache: ${label} is a relative path segment`);
}
if (trimmed.includes("/") || trimmed.includes("\\") || trimmed.includes("\0")) {
throw new Error(`codex auth cache: ${label} contains a path separator`);
}
// Defense in depth: a safe segment is exactly its own basename. Anything else
// carries a separator or a relative segment the checks above must have caught.
if (path.basename(trimmed) !== trimmed) {
throw new Error(`codex auth cache: ${label} is not a single path segment`);
}
return trimmed;
}
/**
* Sanitizes an `account_id` to one safe path segment. Rejects an empty value, a
* relative segment (`.` or `..`), a path separator, and a NUL byte, so a raw
* `account_id` can never become a path traversal. Returns the trimmed, safe
* segment. (Security condition 3.)
*/View on GitHub (pinned to 67001ec6eb)
Solutions
- Re-generate the Codex auth.json so account_id is a real opaque id (re-run codex login).
- Validate/sanitize the account_id upstream before it reaches the cache; reject "." and ".." explicitly.
- If the value is genuinely unusable, disable the cache (PAPERCLIP_CODEX_AUTH_CACHE=0) until the credential is replaced.
Defensive patterns
Strategy: validation
Validate before calling
function isSafePathSegment(value: unknown): value is string {
if (typeof value !== "string") return false;
const t = value.trim();
if (t.length === 0 || t === "." || t === "..") return false;
if (t.includes("/") || t.includes("\\") || t.includes("\0")) return false;
return path.basename(t) === t;
} Type guard
function isRelativeSegment(value: unknown): boolean {
return typeof value === "string" && (value.trim() === "." || value.trim() === "..");
} Try / catch
try {
const key = toCacheKey(accountId);
} catch (e) {
if (e instanceof Error && /is a relative path segment/.test(e.message)) {
// treat as corrupt credential; refuse to cache, log a fixed line
} else throw e;
} Prevention
- Sanitize upstream data sources that populate account_id; reject dot-segments early.
- Add a schema check on auth.json so account_id is an opaque id before caching.
- Keep PAPERCLIP_CODEX_AUTH_CACHE=0 as an escape hatch for untrusted credential sources.
When it happens
Trigger: toCacheKey(".") or toCacheKey("..") is called (an account_id of "." or ".."), or resolveCodexAuthCacheDir is called with companyId equal to "." or "..".
Common situations: Corrupted or hand-edited auth.json where account_id was set to a dot segment; a test fixture using "." as a placeholder id; malformed upstream data feeding the cache key.
Related errors
- codex auth cache: ${label} is empty
- Refusing to write export file outside output directory: ${re
- Invalid object key for company ${companyId}.
- sync operation ${label} path is not a confined absolute path
- sync operation ${label} path escapes its confinement root: $
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/3d06f5e3e9f8db7d.
Report an issue: GitHub.