The strict trust boundary for FormData.
safe-formdata is a security-focused parser that establishes a predictable boundary between untrusted input and application logic. It enforces strict rules on keys and forbids structural inference by design.
FormData is untyped and unstructured by nature. Many parsers attempt to infer structure or semantics from key naming conventions.
safe-formdata intentionally does not.
It performs only minimal, security-focused parsing and reports all structural issues explicitly, without inferring structure, intent, or meaning.
- 🧱 Keys are opaque
Key names are never interpreted as structure. - 🚫 No silent fixes
Invalid or conflicting input is reported, not corrected. - ⚖️ Parsing is not validation
Schema and business logic belong outside the boundary. - 🔒️ Security over convenience
Unsafe input is surfaced early and explicitly.
safe-formdata defines a strict trust boundary between untrusted FormData input and application logic.
Within this boundary, safe-formdata focuses exclusively on:
- Preventing prototype pollution
- Detecting forbidden, invalid, and duplicate keys
- Ensuring explicit issue reporting with no silent correction
- Providing predictable, non-inferential parsing behavior
Anything beyond this boundary — including value validation, schema enforcement, framework conventions, authentication, or denial-of-service protection — is out of scope and must be handled by the application.
📘 Authoritative security guarantees, assumptions, and reporting policy:
See SECURITY.md
Security decisions and issue triage are based on the definitions in SECURITY.md.
import { parse } from "safe-formdata";
const { data, issues } = parse(formData);dataisnullif any boundary violations are detectedissuescontains all detected structural issues- Partial success is not allowed
export interface ParseResult {
data: Record<string, string | File> | null;
issues: ParseIssue[];
}datais non-null only when no boundary violations are detecteddatais always a flat object; no structural inference is performedissuesmust always be checked by the caller
export interface ParseIssue {
code: "invalid_key" | "forbidden_key" | "duplicate_key";
path: string[];
key?: unknown;
}pathis always empty and exists only for compatibility- Issues are informational and are never thrown
safe-formdata intentionally omits several common features.
Keys such as a[b][c], user.name, or items[]
are treated as opaque strings, not paths.
{
"a[b][c]": "value"
}Inferring structure introduces ambiguity and security risks. safe-formdata validates keys, but never constructs objects from them.
safe-formdata does not produce typed structural output.
Allowing generic types would imply runtime guarantees that the library intentionally does not provide.
The output type is intentionally flat:
Record<string, string | File>;FormData is external input. Throwing encourages accidental 500 errors and obscures boundary handling.
safe-formdata exposes a single, explicit error-handling model: inspect issues and decide what to do.
- Not a schema validator
- Not a typed form parser
- Not a replacement for Zod, Yup, or similar libraries
safe-formdata defines a safe boundary. Validation and typing belong beyond it.
v0.x focuses exclusively on establishing and clarifying the FormData boundary. No inference or convenience features will be added within v0.x.
MIT