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

  1. Re-generate the Codex auth.json so account_id is a real opaque id (re-run codex login).
  2. Validate/sanitize the account_id upstream before it reaches the cache; reject "." and ".." explicitly.
  3. 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

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


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/3d06f5e3e9f8db7d. Report an issue: GitHub.