Mesrai
Back to blog
// essayTechnical Deep Dive

The any Cast Mesrai Caught in a Trust Boundary

Real PR catch: `req.body as User` — type assertion is not validation. Zod schema fix.

Mesrai TeamAugust 10, 20268 min read

An API handler casting `req.body` to a User type with `as`. Type-checks fine. Runtime: any shape gets through. Mesrai flagged the trust-boundary type assertion.

The vulnerable diff

tsapi/users.ts
// api/users.ts
interface User { name: string; email: string; age: number; }

usersRouter.post("/users", async (req, res) => {
  // BUG: as is a type assertion, not validation.
  // req.body could be {}, null, { age: "not a number" }, etc.
  const data = req.body as User;
  await db.users.create({ data });
});

What is wrong

`as` in TypeScript is a *trust-me* operator — it tells the type system to treat a value as a type without checking. At a trust boundary (HTTP request body, file content, third-party API response, environment variables), the data hasn't been validated and the cast is a hope, not a guarantee. The fix is to validate at the boundary with a runtime schema library (Zod, io-ts, Yup, ArkType). The validator parses the value and either returns a typed value or throws — the type is now backed by a runtime check.

The attack

Failure modes without validation:

textexploit
- Missing fields: db.users.create({ name: undefined }) → constraint violation.
- Wrong types: { age: "twenty" } → DB insert silently coerces or fails.
- Extra fields: { isAdmin: true } → mass-assignment vulnerability.
- Wrong shape entirely: req.body = null → TypeError reading .name.

Mass-assignment is the worst — a casual cast lets attackers set fields the API never intended to expose.

Mesrai's review comment

textreview-comment.txt
mesraipilot · Bot · reviewed 1 min ago

[mesrai] [code-review] [Language] [Type-Hole] [medium]

`as User` is a type assertion, not validation. Anything at runtime
gets through — including data that doesn't have the User shape, or
data with extra fields you didn't anticipate (mass-assignment).

Validate with Zod (or io-ts / ArkType / Yup):

  import { z } from "zod";

  const CreateUserSchema = z.object({
    name:  z.string().min(1).max(120),
    email: z.string().email(),
    age:   z.number().int().min(0).max(150),
  }).strict();   // .strict() rejects unknown keys

  const data = CreateUserSchema.parse(req.body);   // throws on bad shape
  await db.users.create({ data });

Pair with a global error handler that converts ZodError → 400 with
a clean message.

The fix

tsapi/users.ts (fixed)
// api/users.ts — fixed
import { z } from "zod";

const CreateUserSchema = z.object({
  name:  z.string().min(1).max(120),
  email: z.string().email(),
  age:   z.number().int().min(0).max(150),
}).strict();

usersRouter.post("/users", async (req, res) => {
  const result = CreateUserSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({ error: result.error.flatten() });
  }
  await db.users.create({ data: result.data });
  res.status(201).end();
});

Zod schema defines the shape, validates types, enforces constraints, and rejects unknown keys with `.strict()`. The result is a typed value backed by a runtime check; downstream code can trust it.

Why human review missed it

The `as` cast is the TypeScript escape hatch and tutorials use it freely. The trust-boundary distinction (where untrusted input enters the program) is the discipline. Mesrai flags every `as` cast applied to a known trust-boundary source: `req.body`, `req.query`, `req.params`, `process.env`, JSON.parse, response.json().

Related rules + further reading

Mesrai rule pack: language/no-as-at-trust-boundary — flags `as` casts on untrusted-input sources without preceding validation.

Colin McDonnell's Zod docs: 'Parsing instead of casting'.

Common in TypeScript codebases that adopted types but not runtime validation.

Takeaway

Cast does not validate. Parse with a schema at every trust boundary. Mesrai catches every cast on untrusted input.

// try

See it on your next PR.

Free for individuals. Install in two minutes. Mesrai reviews every commit.