cybersecurity · beginner · ~15 min · safe pentest lab

Mass Assignment: Field Allowlist Guard

Understand mass-assignment (auto-binding) attacks and implement a deny-by-default input allowlist that rejects protected fields, unknown fields, and malformed input (NULL/empty) using exact matching.

Challenge

Mass Assignment (a.k.a. Auto-Binding / Object Injection)

Many web frameworks let a client submit a JSON body and then blindly copy every key/value pair onto a server-side object: user.name = body.name, user.role = body.role, and so on. The insecure assumption is that clients only send the fields the form shows. An attacker who adds an unexpected key like is_admin, role, or balance to the request can silently escalate privileges or edit protected state. This is mass assignment, and the standard defense is an input allowlist: only fields you explicitly permit may ever be written.

Asset & threat

The asset is a user profile record. The threat is an attacker adding extra JSON keys to overwrite protected columns. Your guard is the last line that decides which incoming field names are writable.

Your task

Implement is_allowed_field(const char *field). Return 1 only when field exactly matches one of the four permitted input fields: name, email, bio, avatar_url. For anything else — protected fields, unknown fields, or malformed input — return 0. This is a fixed, in-memory allowlist; you never touch a network or filesystem.

Edge cases you must handle

  • NULL pointer => 0 (never dereference it).
  • Empty string "" => 0.
  • Case variants ("Name"), prefixes ("nam"), superstrings ("name_admin"), and trailing whitespace ("email ") are NOT matches => 0.

Deny by default: if you are not certain a field is on the allowlist, reject it.

Example

Given the allowlist {name, email, bio, avatar_url}:

is_allowed_field("email")    -> 1
is_allowed_field("is_admin") -> 0
is_allowed_field(NULL)       -> 0

Input format

A single C string field (may be NULL) representing an incoming JSON field name the client wants to write.

Output format

Return int 1 if field is exactly one of the four allowed input fields, otherwise 0.

Constraints

C11. No dynamic allocation required. Must not dereference a NULL pointer. The allowlist is fixed: name, email, bio, avatar_url. Matching is exact and case-sensitive. The harness provides all standard includes (stdio.h, string.h, stdlib.h, stdint.h).

Starter code

int is_allowed_field(const char *field){
    /* TODO: return 1 only if field is EXACTLY one of the allowed input
       fields (name, email, bio, avatar_url); otherwise return 0.
       Remember: handle NULL and empty string, and use EXACT matching so
       attacker keys like is_admin / role / balance are rejected.
       This insecure stub allows everything -- replace it. */
    (void)field;
    return 1;
}

Common mistakes

Using strncmp with a short length so 'name_admin' or 'name123' passes; forgetting the NULL check and crashing; doing a case-insensitive compare so 'Name' or 'ROLE' behaves unexpectedly; using a denylist (blocking only is_admin/role) instead of an allowlist, which fails open on any protected field you forgot to list; treating empty string as allowed.

Edge cases to handle

NULL pointer returns 0 without dereferencing; empty string returns 0; case-different variants like 'Name' return 0; prefixes like 'nam' return 0; superstrings like 'name_admin' return 0; trailing/leading whitespace like 'email ' returns 0; protected fields is_admin/role/balance return 0.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.