paperclipai/paperclip · error · HttpError

Workspace file path is denied by policy

Error message

Workspace file path is denied by policy

What it means

throwIfDenied policy guard: the workspace path matches a deny rule — a denied path segment, a secrets file (.env*, *.pem/*.key/*.p12/*.pfx, id_rsa, .npmrc, .netrc, kubeconfig...), or traversal through .aws/.ssh. The 422 prevents agents from reading credential material from workspaces regardless of filesystem permissions; choose a non-secret path.

Source

Thrown at server/src/services/workspace-file-resources.ts:332

  if (lowerSegments.some((segment) => DENIED_SEGMENTS.has(segment))) return "denied_path_segment";

  const fileName = lowerSegments.at(-1) ?? "";
  if (fileName === ".env" || fileName.startsWith(".env.")) return "denied_secret";
  if (fileName.endsWith(".pem") || fileName.endsWith(".key") || fileName.endsWith(".p12") || fileName.endsWith(".pfx")) {
    return "denied_secret";
  }
  if (["id_rsa", "id_ed25519", ".npmrc", ".pypirc", ".netrc", "kubeconfig"].includes(fileName)) return "denied_secret";
  if (lowerSegments.includes(".aws") || lowerSegments.includes(".ssh")) return "denied_secret";
  if (lowerSegments.length >= 2 && lowerSegments.at(-2) === ".docker" && fileName === "config.json") return "denied_secret";
  if (lowerSegments.length >= 2 && lowerSegments.at(-2) === ".kube" && fileName === "config") return "denied_secret";

  return null;
}

function throwIfDenied(segments: string[]) {
  const denialReason = denyReasonForPathSegments(segments);
  if (denialReason) {
    throw new HttpError(403, "Workspace file path is denied by policy", { code: denialReason });
  }
}

function shouldPruneSegments(segments: string[]) {
  return denyReasonForPathSegments(segments) != null;
}

function contentTypeForPath(filePath: string): string | null {
  const ext = path.extname(filePath).toLowerCase();
  if (IMAGE_CONTENT_TYPES.has(ext)) return IMAGE_CONTENT_TYPES.get(ext) ?? null;
  if (VIDEO_CONTENT_TYPES.has(ext)) return VIDEO_CONTENT_TYPES.get(ext) ?? null;
  if (ext === ".pdf") return "application/pdf";
  if (ext === ".svg") return "image/svg+xml";
  if (ext === ".html" || ext === ".htm") return "text/html";
  if (TEXT_EXTENSIONS.has(ext)) return "text/plain; charset=utf-8";
  return null;
}

View on GitHub (pinned to 120ae5428f)

Solutions

  1. The path matches a deny rule (e.g. .env, key files). Choose an allowed path or adjust the workspace file policy.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/services/workspace-file-resources.ts:332 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18). Data as JSON: /api/errors/af55c917c24efa8b. Report an issue: GitHub.