# Risk map — trpc/trpc

> Canonical page: https://codevetter.com/unpack/trpc/risk-map

# Risk map — trpc/trpc

Scanned commit 8b649ad874a8fe97c73962d4617912231b975736 (2026-09-17). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The framework does not authenticate requests; authorization is a user middleware. The risky defaults are unlimited Node request bodies, batching on with no max batch, stack traces in any non-production NODE_ENV, and transformer.deserialize running on attacker-controlled JSON. Several high-churn areas (Next app dir, the upgrade CLI, the SSE chat example) are outside the coverage gate or marked continue-on-error. WebSocket and HTTP stacks duplicate procedure invocation, so adapter bugs do not all flow through resolveResponse.
- getErrorShape copies error.stack into the client-visible error when config.isDev is true. isDev defaults to process.env.NODE_ENV !== production, so any deployment that forgets NODE_ENV=production leaks stacks. The Prisma and SSE examples' errorFormatters return the shape unchanged. — [packages/server/src/unstable-core-do-not-import/error/getErrorShape.ts#L29-L35](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/error/getErrorShape.ts#L29-L35) [packages/server/src/unstable-core-do-not-import/initTRPC.ts#L156-L159](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/initTRPC.ts#L156-L159) [examples/next-sse-chat/src/server/trpc.ts#L22-L25](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/examples/next-sse-chat/src/server/trpc.ts#L22-L25)
- nodeHTTPRequestHandler passes maxBodySize: opts.maxBodySize ?? null. incomingMessageToRequest only rejects PAYLOAD_TOO_LARGE when maxBodySize is truthy and size exceeds it, so the default null means no body cap. The check also treats 0 as unlimited because it uses !opts.maxBodySize. — [packages/server/src/adapters/node-http/nodeHTTPRequestHandler.ts#L87](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/node-http/nodeHTTPRequestHandler.ts#L87) [packages/server/src/adapters/node-http/incomingMessageToRequest.ts#L6-L49](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/node-http/incomingMessageToRequest.ts#L6-L49)
- Batching is on unless the adapter sets allowBatching or batching.enabled to false. maxBatchSize is optional; jsonContentTypeHandler checks it only when it is a number. httpBatchLink defaults maxURLLength and maxItems to Infinity, so a client can build arbitrarily large batched URLs or bodies unless the app opts in. — [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L229-L313](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L229-L313) [packages/server/src/unstable-core-do-not-import/http/contentType.ts#L84-L97](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/contentType.ts#L84-L97) [packages/client/src/links/httpBatchLink.ts#L25-L26](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/client/src/links/httpBatchLink.ts#L25-L26)
- GET query inputs are a raw JSON string in the input search param, then JSON.parse, then transformer.input.deserialize. Mutations cannot use GET: TYPE_ACCEPTED_METHOD_MAP and the method-override map both list mutation as POST only, with an explicit comment that GET must never perform a mutation. — [packages/server/src/unstable-core-do-not-import/http/contentType.ts#L100-L118](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/contentType.ts#L100-L118) [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L49-L61](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L49-L61)
- resolveResponse returns 204 for every HEAD with no router or auth check, documented as a Lambda warmup. Subscriptions cannot be batched. A single-call JSON response that is an async iterable or contains promises/async iterables throws UNSUPPORTED_MEDIA_TYPE and tells the client to use httpBatchStreamLink. — [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L222-L227](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L222-L227) [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L350-L357](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L350-L357) [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L417-L423](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L417-L423)
- There is no auth inside @trpc/server. The SSE example's authedProcedure only checks that session.user.name is non-empty. post.onAdd and post.infinite are publicProcedure, so channel messages are readable without that check. When GitHub credentials are absent outside production, auth.tsx installs a Credentials provider that authorizes any name. — [examples/next-sse-chat/src/server/trpc.ts#L79-L96](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/examples/next-sse-chat/src/server/trpc.ts#L79-L96) [examples/next-sse-chat/src/server/routers/post.ts#L43-L88](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/examples/next-sse-chat/src/server/routers/post.ts#L43-L88) [examples/next-sse-chat/src/server/auth.tsx#L12-L48](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/examples/next-sse-chat/src/server/auth.tsx#L12-L48)
- CI e2e sets NEXTAUTH_SECRET to the literal supersecret and starts Postgres with trust auth. That is test-only, but the workflow file is the template people copy. SECURITY.md supports versions greater than 9.x and says to report vulnerabilities by Twitter DM to alexdotjs or email alex@kattcorp.com. — [.github/workflows/main.yml#L106-L117](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/.github/workflows/main.yml#L106-L117) [SECURITY.md#L1-L12](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/SECURITY.md#L1-L12)
- eval() appears only in tests that round-trip a devalue/uneval transformer (packages/tests/server/transformer.test.ts, httpSubscriptionLink.test.ts, and packages/next/test/issue-4130-ssr-different-transformers.test.tsx). It is not on the request path. The production risk is user-supplied transformers: deserialize runs on request JSON, and next-sse-chat uses superjson. — [packages/tests/server/transformer.test.ts#L100-L101](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/tests/server/transformer.test.ts#L100-L101) [packages/server/src/unstable-core-do-not-import/http/contentType.ts#L115-L133](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/contentType.ts#L115-L133) [examples/next-sse-chat/src/server/trpc.ts#L12-L19](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/examples/next-sse-chat/src/server/trpc.ts#L12-L19)
- @trpc/upgrade shells out: src/lib/execa.ts imports node:child_process exec, the CLI calls assertCleanGitTree unless --force, and it can installPackage/uninstallPackage. OpenAPI tests call execFileSync. Standalone HTTP/2 tests import child_process. These are maintainer and test tools, not the RPC runtime. — [packages/upgrade/src/lib/execa.ts#L1](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/upgrade/src/lib/execa.ts#L1) [packages/upgrade/src/bin/index.ts#L7-L49](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/upgrade/src/bin/index.ts#L7-L49) [packages/openapi/test/cli.test.ts#L1](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/openapi/test/cli.test.ts#L1) [packages/tests/server/adapters/standalone.http2.test.ts#L1](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/tests/server/adapters/standalone.http2.test.ts#L1)
- The e2e job is continue-on-error: true, and next-sse-chat (the Drizzle plus auth plus SSE example) is commented out of the matrix. App-dir sources are excluded from coverage and from codecov ignore paths. A green unit job does not prove the example apps or the experimental Next app-dir caller. — [.github/workflows/main.yml#L121-L140](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/.github/workflows/main.yml#L121-L140) [vitest.shared.ts#L55-L58](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/vitest.shared.ts#L55-L58) [codecov.yml#L4-L8](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/codecov.yml#L4-L8)
- Client and server both depend on the unstable-core-do-not-import export for proxies, callProcedure, and transformResult. A breaking change there breaks @trpc/client even if the public index stays stable. Several v12 removals are already marked: inferRouterClient, header objects that are not Headers, experimental_lazy, and the sse() alias. — [packages/client/src/createTRPCClient.ts#L13-L16](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/client/src/createTRPCClient.ts#L13-L16) [packages/client/src/createTRPCClient.ts#L24-L33](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/client/src/createTRPCClient.ts#L24-L33) [packages/server/src/@trpc/server/index.ts#L62-L75](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/%40trpc/server/index.ts#L62-L75) [packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L123-L126](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/unstable-core-do-not-import/http/resolveResponse.ts#L123-L126)
- Adapter duplication is a blast-radius hotspot. Express and Next pages share nodeHTTPRequestHandler, but WebSockets call callTRPCProcedure directly and Fastify has its own fastifyRequestHandler. A procedure-lookup bug fixed only in resolveResponse will not automatically apply to applyWSSHandler. — [packages/server/src/adapters/express.ts#L25-L38](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/express.ts#L25-L38) [packages/server/src/adapters/next.ts#L54-L59](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/next.ts#L54-L59) [packages/server/src/adapters/ws.ts#L9-L17](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/ws.ts#L9-L17) [packages/server/src/adapters/fastify/fastifyTRPCPlugin.ts#L22-L23](https://github.com/trpc/trpc/blob/8b649ad874a8fe97c73962d4617912231b975736/packages/server/src/adapters/fastify/fastifyTRPCPlugin.ts#L22-L23)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
