Applications often store or transmit values as bytes or text, a process called serialization. Deserialization reads that representation and rebuilds values. Some formats can rebuild powerful program objects or invoke code while loading, so reading untrusted serialized data can cross a code-execution boundary.
The benign JSON file contains only a name value. The data-only path parses its text, then checks the required structure. The other loader is described rather than supplied: it can run code during loading. A familiar file extension says nothing about who created the contents or what the loader may do.
Before you begin
- Recommended first
- Notes: scope, command, result, time, HTTP methods, headers, status codes, cookies, How a web app is put together, Same-origin policy, OWASP Top 10:2025
- Estimated time
- 18 min reading, 12 min activity. Setup and optional practice may take longer.
- Where you work
- Read the original fictional source, object tables, token claims and policy models in any current desktop or mobile browser. No loader, template engine, provider registration, service or network request is required.
- Without a lab
- Follow the printed data through each stated rule on paper. Record the decision, its supporting fact and a limit, then compare with the guided rubric. Model reasoning does not establish a live tool result. Reading works without JavaScript. Checking requires JavaScript and a secure context; saving also requires usable storage.
After this lesson you can:
- Define serialization as saving data and deserialization as rebuilding it.
- Accept the data-only path for the printed JSON.
- Refuse a code-capable load of an untrusted file on the basis of its name.
01Example
This fresh fictional JSON value demonstrates parsing and schema checks. The guided activity uses Ada in the separate supplied file.
Input text: {"name":"Mira"}
Parse as JSON: an object with property name.
Schema: name must be a string; no extra fields.
Decision: meets this simple schema.
Prediction only; no parser ran.02The loader is the boundary
The safe comparison is about loader capability, not just whether the file looks ordinary. Parse a constrained data format, validate that the result has the expected types and fields, and enforce resource limits. JSON parsing does not itself validate the application's schema, authorize the data or make later uses safe.
The fictional code-capable loader illustrates why a file must not receive execution authority merely because it has a recognized suffix. The fitting defense is to avoid unsafe loading of untrusted objects. No unsafe file or payload is provided, and the predicted dictionary is a teaching model rather than parser output.
Compare a constrained data parser with a loader that can execute code, and keep an untrusted filename from deciding trust.Model. A teaching model drawn by hand. It shows the idea, not real tool output.
Read the full explanation below.
Input text: {"name":"Mira"}
met · Object with property name.Schema: name must be a string; no extra fields.
met · Mira is a string and no extra fields are shown.This is the supplied schema prediction; no parser ran.
Constrained parsing plus schema checks is a narrower authority than executable object loading; this is no live parser result.
This is the supplied schema prediction; no parser ran.
Follow the explanation
- This is the supplied schema prediction; no parser ran.
- The model establishes no execution or real deserializer behavior.
Read every state and value
1. This is the supplied schema prediction; no parser ran.
- Case
- schema
- Conditions inspected
- Declared JSON object · Name string
- Decision shown
- Yes
2. The model establishes no execution or real deserializer behavior.
- Case
- limit
- Conditions inspected
- Declared JSON object · Name string
- Decision shown
- Yes
03Choose the path
Read the evidence before comparing with the activity rubric. Do not run a parser.
Two loaders, described. The unsafe one is not in this folder.
Data-only
Input: benign-data.json
Operation: parse the text as JSON and accept only an object with a string name
Result on the card: a dictionary {"name": "Ada"}
The card is not a live parser result.
Code-capable
Input: an untrusted file whose name ends in a familiar extension
Operation: rebuild program objects and run code during the load
This folder does not contain that file or that call.
A familiar extension does not change the operation.
Activity choice: the data-only path.
{"name": "Ada"}
- Write the data-only operation and the card's result.
- Write what the code-capable description does, and whether that file is in the folder.
- Check: the activity choice is the data-only path. The code-capable file is absent. The result dictionary was not produced by a run.
- Stop. Do not add a code-capable load to the folder.
04Optional challenge
Name one check that remains after the JSON parse. The rubric is: the value is an object and name is a string, and the text is within a size you set. About ten minutes.
05Fresh cases for the checks
Use these fictional cases for the checks below. They have different inputs from the worked examples. Read them here or make notes; no installation or external service is needed.
Loading case A: distinct operationsOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
P: turn an in-memory data object into saved text.
Q: parse saved JSON text back into a data object.
R: after parsing, check the object has exactly a string field name and no other fields.
Parsing and checking are described only; no parser ran.
Loading case B: fresh schema inputsOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
Expected result: an object with exactly one field, name, whose value is a string.
M: {"name":"Oren"}
N: {"name":8}
O: {"name":"Lina","admin":true}
All inputs are within the size limit; each is valid JSON syntax.
Loading case C: independent loader choicesOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
The input is untrusted.
Loader D parses constrained data and validates types, allowed fields and size.
Loader X rebuilds program objects and can execute code during loading.
The input filename ends .familiar, but its name establishes no trust.
06Explain your evidence
Optional written self-check: explain one decision using the supplied case. No tool run is required.
Check your explanation: distinguish saving, rebuilding and validating data; apply exact types and allowed keys; judge loader capability independently of filenames; keep resource and later-use limits visible.
07Common mistakes
If you accept the code-capable path because the extension is familiar, you used the filename as the control.
If you look for a binary payload, the folder does not have one.
If you treat the dictionary as observed output, read it as the card's prediction. It is not a live parser result.
References
- RFC 8259: JSON
Describes JSON types and syntax. Parsing a value does not establish its application schema or trust.
- PortSwigger: Insecure deserialization
Further explanation of this mechanism and its defenses. The original printed model supplies the required evidence.