/** * @module @arcis/node/sanitizers/mass-assignment * v1.7 W4. Denylist detection of privilege-escalation fields in a body. * * The classic mass-assignment attack smuggles a sensitive field into a * request body that the handler blindly spreads onto a model: * * user.update({ ...req.body }) // attacker set isAdmin: true * * The allowlist approach (`applyMassAssignFilter` / `MassAssignMiddleware`) * is the robust fix but needs a per-route field list, so it cannot be * default-on. This detector is the default-on complement: it scans the * body for a curated set of privilege/auth field NAMES that a normal * client request almost never sets, and blocks when one appears. * * Scope: detection only. It does not strip or rewrite. Recurses into * nested objects and arrays so `{ profile: { permissions: [...] } }` is * caught. Value-agnostic: the presence of the key is the signal. * * False-positive note: `role` and `permissions` DO appear in legitimate * admin APIs. Apps with such routes opt out via `arcis({ massAssign: false })` * or scope the check off for those paths, then use the allowlist filter * (`applyMassAssignFilter`) on the routes that legitimately accept them. */ export interface MassAssignDetectOptions { /** * Sensitive field names to detect (overrides the default set entirely). * Compared case-insensitively after stripping `_` and `-`, so * `is_admin`, `isAdmin`, and `is-admin` all match a `isadmin` entry. */ sensitiveFields?: string[]; /** Max recursion depth into nested objects/arrays. Default: 8. */ maxDepth?: number; } export interface MassAssignDetectResult { /** True if a sensitive field name was found anywhere in the body. */ detected: boolean; /** The offending field name (original casing) or null. */ field: string | null; } /** * Default privilege-escalation field names. Stored in normalized form * (lowercased, separators stripped). These are fields a profile/signup * update should never carry from the client. `role` / `permissions` are * the canonical mass-assignment fields and the FP-risk ones, kept in by * default; opt out per-route if your admin API legitimately accepts them. */ export declare const SENSITIVE_FIELD_NAMES: ReadonlySet; /** * Recursively scan a parsed JSON body for sensitive field names. * Returns the first hit (original-cased key) or `{ detected: false }`. */ export declare function detectMassAssignment(body: unknown, options?: MassAssignDetectOptions): MassAssignDetectResult; //# sourceMappingURL=mass-assignment.d.ts.map