paperclipai/paperclip · error · Error

path must start with / and be relative to /api, and must not

Error message

path must start with / and be relative to /api, and must not contain '..'

What it means

The paperclipApiRequest escape-hatch tool sanitizes the caller-supplied path: it must start with '/' and must not contain '..'. The check is a deliberately conservative guard against path traversal, since path is forwarded verbatim (minus the leading slash) into client.requestJson against the /api base.

Source

Thrown at packages/mcp-server/src/tools.ts:626

        return client.requestJson("POST", path, { body });
      },
    ),
    makeTool(
      "paperclipAddApprovalComment",
      "Add a comment to an approval",
      z.object({ approvalId: approvalIdSchema, body: z.string().min(1) }),
      async ({ approvalId, body }) =>
        client.requestJson("POST", `/approvals/${encodeURIComponent(approvalId)}/comments`, {
          body: { body },
        }),
    ),
    makeTool(
      "paperclipApiRequest",
      "Make a JSON request to an existing Paperclip /api endpoint for unsupported operations",
      apiRequestSchema,
      async ({ method, path, jsonBody }) => {
        if (!path.startsWith("/") || path.includes("..")) {
          throw new Error("path must start with / and be relative to /api, and must not contain '..'");
        }
        return client.requestJson(method, path, {
          body: parseOptionalJson(jsonBody),
        });
      },
    ),
  ];
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Ensure path begins with '/' and is relative to /api (e.g. '/issues/123').
  2. Remove any '..' segments — only forward slash paths within /api are allowed.
  3. If you genuinely need an endpoint outside /api, use a different transport; this tool is scoped to /api on purpose.

Example fix

// before
apiRequest({ method: 'GET', path: 'issues/123' })      // no leading '/'
apiRequest({ method: 'GET', path: '/api/../users' })     // contains '..'
// after
apiRequest({ method: 'GET', path: '/issues/123' })
Defensive patterns

Strategy: validation

Validate before calling

function isSafeApiPath(p: string): boolean {
  return p.startsWith('/') && !p.includes('..');
}
if (!isSafeApiPath(input.path)) throw new Error('path must start with / and stay within /api');

Prevention

When it happens

Trigger: An LLM or caller passes a path that does not start with '/' (e.g. 'issues/123') or contains '..' (e.g. '/../admin/users'). Both shapes throw before the HTTP call.

Common situations: Agent omits the leading slash by mistake; agent tries to escape /api to reach a sibling route; caller copy-pastes a URL path including the /api prefix already.

Related errors


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