Hacker DirectoryHacker Directory

WEB / WEB-17.S03

Deserialization and object reconstruction boundaries

Separate parsing, schemas, permission and trusted constructors.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

DTO allowed

  1. Fixed JSON ready

    The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer. Parser and constructor work locally in one process; external data selects no behavior.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Local parser waiting; no object constructed
  2. Plain values parsed

    JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Parsed plain object; Book instance=false
  3. Schema decision

    id, title and pageCount are exactly the three approved keys. id=note-A, title length=11 and integer pageCount=12 pass; schema acceptance is not yet a readAllowed decision.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Schema valid; context pending
  4. Context decision

    contextPresent=true and readAllowed=true are application inputs independent of the JSON. After they pass, the three-field DTO may enter the fixed Book constructor; input selects no class or method.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Schema and context accepted; projection pending
  5. Explicit projection

    After schema and read context pass, the application explicitly copies only id/title/pageCount into its fixed Book constructor. A Book instance now exists; its caption has not yet been produced.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Fixed Book constructed; plain caption pending
  6. Local result ready

    The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Caption ready: Tea & Bread (12 pages); mutation=false

Unknown field

  1. Fixed JSON ready

    The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer; subtitle=Reading notes. Parser and constructor work locally in one process; external data selects no behavior.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    Local parser waiting; no object constructed
  2. Plain values parsed

    JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    Parsed plain object; Book instance=false
  3. Schema decision

    subtitle=Reading notes is valid JSON data outside the approved id/title/pageCount keys. unknownFieldMode=reject denies the DTO; context evaluation and construction do not run.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    Schema denied; constructor not run
  4. Schema denial retained

    Schema rejection stops the context gate from running. This branch makes no new actor-permission decision and performs no reconstruction.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    Schema denied; context not evaluated
  5. Explicit projection

    This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    Constructor count=0; protected body absent
  6. Local result ready

    The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer; subtitle=Reading notes
    DTO / constructor
    No caption/body/delivery; mutation=false

Type mismatch

  1. Fixed JSON ready

    The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount="12" string. Parser and constructor work locally in one process; external data selects no behavior.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    Local parser waiting; no object constructed
  2. Plain values parsed

    JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    Parsed plain object; Book instance=false
  3. Schema decision

    pageCount="12" is a JSON string. This contract requires an integer from 1–1000 with no coercion; the type gate denies it. Successful parsing does not run context evaluation or construction.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    Schema denied; constructor not run
  4. Schema denial retained

    Schema rejection stops the context gate from running. This branch makes no new actor-permission decision and performs no reconstruction.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    Schema denied; context not evaluated
  5. Explicit projection

    This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    Constructor count=0; protected body absent
  6. Local result ready

    The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.

    Fixed JSON data
    note-A / Tea & Bread / "12" string
    DTO / constructor
    No caption/body/delivery; mutation=false

Context missing

  1. Fixed JSON ready

    The application has prepared book-note/v1 text: id=note-A, title=Tea & Bread, pageCount=12 integer. Parser and constructor work locally in one process; external data selects no behavior.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Local parser waiting; no object constructed
  2. Plain values parsed

    JSON.parse locally produces plain values; text selects no method or runtime class and no reviver is used.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Parsed plain object; Book instance=false
  3. Schema decision

    id, title and pageCount are exactly the three approved keys. id=note-A, title length=11 and integer pageCount=12 pass; schema acceptance is not yet a readAllowed decision.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Schema valid; context pending
  4. Context decision

    The normal JSON shape passes, but contextPresent=false and readAllowed=null. Permission remains unknown; safe denial withholds construction/projection rather than establishing false permission.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    No context; permission UNKNOWN; no constructor
  5. Explicit projection

    This denied branch performs no explicit DTO projection or Book-constructor call. Constructor count=0 means no domain object or caption; an object from the normal branch cannot be reused here.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    Constructor count=0; protected body absent
  6. Local result ready

    The caption is only a plain string; DOM/store/network delivery and object mutation are not part of this scene.

    Fixed JSON data
    note-A / Tea & Bread / 12 integer
    DTO / constructor
    No caption/body/delivery; mutation=false

ACTORS · STATE · DATA FLOW

JSON produces data, not a choice of behavior

Deserialization turns an external representation into values that a program can read. For JSON these are objects, arrays, strings, numbers, booleans and null. A book object returned by JSON.parse is not an instance of the application’s Book class; its text does not automatically choose a caption method or approved constructor. Reconstruction is a separate design decision: the application chooses which validated fields enter a trusted domain type. Atlas Notes uses book-note/v1 with id, title and pageCount. Tea & Bread is only a plain title string. Successful parsing proves neither that pageCount is an appropriate integer, that the ID refers to the requested object, nor that an actor may use that data. This lesson creates only a fixed read-only caption; it derives no DOM, file or database action from the object.

From a closed DTO to a trusted constructor

The selected profile accepts exactly three keys: pageCount is an integer from 1 to 1000, title is a string from 1 to 80 characters, and id must equal note-A. An unknown subtitle field is rejected in this profile; this is not a claim that every API must reject all unknown fields. A versioned contract can choose another compatibility policy, but silent field loss should be visible. An accepted DTO is built by explicit projection, and the constructor receives only those three values. Its name is not read from the input; external data selects no runtime module or method. ContextPresent and readAllowed are separate server-side inputs; no JSON field can open that gate. With missing context, even a correctly shaped object is not reconstructed for client delivery. Validation and authorization each retain their own decision.

Revivers and format boundaries

The optional JSON.parse reviver is a function supplied by the application, not an executable instruction inside the text. A transformation hook introduces behavior that needs its own review; this profile uses no reviver. JSON is also not a universal, lossless snapshot of every runtime value. Class identity, methods and special runtime behavior are outside this three-field DTO. Numeric precision, nesting and text-size limits belong in the parser and contract profile. Unique object member names matter for interoperability; choose an explicit ingress parser policy rather than depending on duplicate-key behavior. This fixture produces no duplicate keys and runs no duplicate-preserving parser. A pure data format narrows the surface, but does not independently guarantee safe downstream business methods, output interpretation or permission.

2. Red · Trust & Impact

Read every scenario without motion

Unknown field

  1. The data-only profile was selected

    book-note/v1 accepts only id, title and pageCount. The unknown-field row adds subtitle=Reading notes, which conflicts with this closed contract.

    External JSON data
    Closed keys: 3
    Closed DTO gate
    Shape review pending
    Constructor/caption boundary
    Constructor not called
  2. JSON parsing and domain type were separated

    The JSON parser can read subtitle as ordinary data. Parsing does not allow the field into the approved DTO or behavior selection.

    External JSON data
    Parsed values only
    Closed DTO gate
    Unknown field present
    Constructor/caption boundary
    Domain object absent
  3. The closed-DTO gate rejected the data

    unknownFieldMode=reject withholds an accepted projection. Silently deleting the field would change this profile’s denial into acceptance.

    External JSON data
    Shape mismatch known
    Closed DTO gate
    Projection withheld
    Constructor/caption boundary
    Constructed=false
  4. The constructor boundary remained closed

    expectedConstructed=false. An input format name or title cannot select the fixed application Book constructor; only approved application code invokes it.

    External JSON data
    No approved DTO
    Closed DTO gate
    No constructor call
    Constructor/caption boundary
    No caption produced
  5. No plain caption was delivered

    expectedDelivery=false, expectedBody=null and expectedMutation=false remain. Parsed data alone is insufficient to advance to the caption consumer.

    External JSON data
    Delivery=false
    Closed DTO gate
    Body=null
    Constructor/caption boundary
    Mutation=false
  6. The failure class remained precise

    This row is contract rejection of an ordinary unknown field, not evidence of object injection or a dangerous loader. The data-only boundary deliberately avoids loading behavior.

    External JSON data
    Known contract rejection
    Closed DTO gate
    Permission separate
    Constructor/caption boundary
    No behavior loading

Type mismatch

  1. The data-only profile was selected

    book-note/v1 requires pageCount as an integer in 1..1000. The wrong-type row contains pageCount="12"; a numeric-looking string remains a string.

    External JSON data
    Closed keys: 3
    Closed DTO gate
    Shape review pending
    Constructor/caption boundary
    Constructor not called
  2. JSON parsing and domain type were separated

    The parser correctly produces pageCount as a string. This is not a syntax error; mismatch with the application’s integer contract occurs at a separate stage.

    External JSON data
    Parsed values only
    Closed DTO gate
    pageCount type: string
    Constructor/caption boundary
    Domain object absent
  3. The closed-DTO gate rejected the data

    Failure of the integer-type gate withholds explicit projection. Automatically converting the string into a number is not this contract’s declared behavior.

    External JSON data
    Shape mismatch known
    Closed DTO gate
    Projection withheld
    Constructor/caption boundary
    Constructed=false
  4. The constructor boundary remained closed

    expectedConstructed=false. An input format name or title cannot select the fixed application Book constructor; only approved application code invokes it.

    External JSON data
    No approved DTO
    Closed DTO gate
    No constructor call
    Constructor/caption boundary
    No caption produced
  5. No plain caption was delivered

    expectedDelivery=false, expectedBody=null and expectedMutation=false remain. Parsed data alone is insufficient to advance to the caption consumer.

    External JSON data
    Delivery=false
    Closed DTO gate
    Body=null
    Constructor/caption boundary
    Mutation=false
  6. The failure class remained precise

    This row is an ordinary type mismatch, not unreadable numeric syntax or false actor permission. Format and permission causes remain separate.

    External JSON data
    Known contract rejection
    Closed DTO gate
    Permission separate
    Constructor/caption boundary
    No behavior loading

ASSUMPTION · BOUNDARY · CONTROL

The assumption between data and runtime type

The failure class under review gives an external representation too much influence over runtime type or behavior selection. A parseable object is not sufficient evidence of a trusted domain object. The risk requires the application to connect external values to behavior-bearing objects, side effects or permission decisions without an approved DTO boundary. This example contains no class-selecting payload or dangerous loader; the finite Book constructor is fixed application code. The unknown subtitle branch demonstrates a contract mismatch, not an exploit result. Keep the states “parsed”, “shape valid”, “actor permitted” and “domain object constructed” separate. Asking where external data stops being a field projection and starts selecting behavior is a concrete review boundary. In this profile that transition occurs only through an approved constructor.

Signatures, schemas and context provide different evidence

If integrity verification exists, it contributes evidence that particular bytes came with appropriate provenance; it does not independently authorize the business meaning of their fields or the recipient’s action. No actual signature exists in this lesson, and provenance is an external dependency rather than an assumed result. In the wrong-type branch pageCount arrives as a string. The parser correctly creates a string, while the contract expects an integer and denies it. The missing-context branch uses the same normal DTO but lacks context evidence; it does not prove that the actor is unauthorized. The safe result still withholds reconstruction delivery and its body. Distinguishing format mismatch, missing permission evidence and unsafe runtime reconstruction reduces both misplaced confidence and unnecessary alarms. The fixed example is applied to no organizational format or actual endpoint.

3. Blue · Secure development & defense

Read every scenario without motion

Field projection

  1. Normal JSON data was read

    The normal text contains id=note-A, title=Tea & Bread and pageCount=12. JSON.parse produces a data object; the text supplies neither a Book prototype nor method implementation.

    JSON/context observation
    Parsed: 3 data fields
    Projection review
    Book instance=false
    Construction conclusion
    Reconstruction pending
  2. Typed-DTO conditions were checked

    Approved keys and types are compared with the profile. Title length 1..80 and pageCount 1..1000 must pass before creating an object with behavior.

    JSON/context observation
    Closed shape accepted
    Projection review
    Title/count within bounds
    Construction conclusion
    Constructor pending
  3. Authorization context was read separately

    The normal row declares contextPresent=true and readAllowed=true. DTO validity cannot replace these permission values; they are supplied separately.

    JSON/context observation
    Shape accepted
    Projection review
    Read allowed=true
    Construction conclusion
    Projection eligible
  4. Three fields were explicitly copied

    The pipeline copies only id, title and pageCount into an application projection. approvedConstructor=fixed application Book does not select classes or methods from input.

    JSON/context observation
    Explicit 3-field projection
    Projection review
    Constructor fixed by app
    Construction conclusion
    Constructed=true
  5. The caption remained a plain string

    expectedBody contains caption=Tea & Bread (12 pages). This string does not establish HTML parsing or DOM rendering; expectedMutation=false.

    JSON/context observation
    Caption: Tea & Bread (12 pages)
    Projection review
    Plain string
    Construction conclusion
    Mutation=false
  6. Freeze and authority were separated

    runtimeLedger declares freezeIsAuthorization=false. Constraining local object mutation proves neither identity, resource permission nor immutability of an entire nested graph.

    JSON/context observation
    Reconstruction known
    Projection review
    Freeze ≠ permission
    Construction conclusion
    DOM/persistence unobserved

Context absent

  1. The same DTO was selected with missing context

    The context-missing row carries the normal three-field JSON text. contextPresent=false and readAllowed=null are evidence conditions distinct from format mismatch.

    JSON/context observation
    Normal DTO data
    Projection review
    Context present=false
    Construction conclusion
    Read allowed=null
  2. Format validity did not become permission

    Even with correct id, title and pageCount, approved actor context is missing. Guessing identity from field values cannot repair that missing evidence.

    JSON/context observation
    Shape valid
    Projection review
    Permission UNKNOWN
    Construction conclusion
    No guessed context
  3. Withheld reconstruction was matched

    expectedConstructed=false remains. Because constructor admission needs context as well as shape, a parsed plain object is insufficient.

    JSON/context observation
    Parsed data known
    Projection review
    Constructor not called
    Construction conclusion
    No domain caption
  4. The negative consumer outcome was checked

    expectedDelivery=false, expectedBody=null and expectedMutation=false are retained together. Review does not infer absent construction from an error label alone.

    JSON/context observation
    Delivery=false
    Projection review
    Body=null
    Construction conclusion
    Mutation=false
  5. Unknown permission was separated from denial cause

    The safe outcome is withheld delivery without claiming verified false actor permission. The normal row’s true value is not copied here without finding the context source.

    JSON/context observation
    Safe delivery withheld
    Projection review
    Permission remains UNKNOWN
    Construction conclusion
    Context evidence required
  6. Data-reconstruction scope was preserved

    This finite pipeline relates plain JSON to a fixed constructor. Endpoint authentication, rich deserializers and persistence safety require separate implementation evidence.

    JSON/context observation
    Data-only boundary known
    Projection review
    Identity unobserved
    Construction conclusion
    No broad deserializer claim

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

Explicit projection and bounded reconstruction

The defensive pipeline is external text → JSON values → closed schema → authorization context → explicit DTO → fixed constructor → plain caption. Construction does not run before schema acceptance, and no caption is delivered without context. The success branch copies only id, title and pageCount. Freezing the object is a local choice that reduces mutation risk; it neither authenticates identity nor makes every nested graph automatically immutable. The method implementation is fixed application code, so input need not load behavior. Adding a field later requires a joint review of contract version, compatibility and constructor projection. Other formats requiring richer runtime serialization need separate parser, type-allowlist and behavior review. Pure JSON gives this small example a clear boundary; it does not certify every format or deserializer as secure.

Prove that reconstruction did not occur

The fixture checks more than whether a successful caption is correct. For unknown field, wrong type and missing context it requires constructed=false, delivered=false, body=null and mutation=false together. The native check uses fixed JSON.parse data to observe that a plain object is not a Book instance, that an approved constructor runs after validated projection, and that the caption is only a plain string. These are actual JSON and class observations; they establish neither a web endpoint’s authorization nor the safety of an unsafe serialization format. Parsing a denied row must not increment the constructor counter. Missing context remains unknownPermission, with a diagnostic selected by the application profile. The checks retain value as contracts change because they compare field, type and context boundaries alongside the normal input. Browser DOM, persistence and remote deserialization services remain outside the evidence.

NOW APPLY IT TO THE CASE

When can parsed JSON become an approved domain object?

book-note/v1 requires a closed DTO and current context. Input does not select behavior; three fields pass through application projection to a fixed Book constructor.

Separate decisions for verified actor, tenant relation and requested action in the case. Do not substitute authentication or proof success for object permission.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Atlas Notes — decision ledger

Select a field and examine what it supports and where the evidence ends.

Read the raw artifact and field explanations
{
  "profile": {
    "format": "book-note/v1",
    "keys": [
      "id",
      "title",
      "pageCount"
    ],
    "id": "note-A",
    "titleLength": [
      1,
      80
    ],
    "pageCountRange": [
      1,
      1000
    ],
    "unknownFieldMode": "reject",
    "approvedConstructor": "fixed application Book",
    "reviverUsed": false,
    "actualEndpoint": false
  },
  "rows": [
    {
      "case": "normal",
      "text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12}",
      "contextPresent": true,
      "readAllowed": true,
      "expectedConstructed": true,
      "expectedDelivery": true,
      "expectedBody": {
        "caption": "Tea & Bread (12 pages)"
      },
      "expectedMutation": false
    },
    {
      "case": "unknown-field",
      "text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12,\"subtitle\":\"Reading notes\"}",
      "contextPresent": true,
      "readAllowed": true,
      "expectedConstructed": false,
      "expectedDelivery": false,
      "expectedBody": null,
      "expectedMutation": false
    },
    {
      "case": "wrong-type",
      "text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":\"12\"}",
      "contextPresent": true,
      "readAllowed": true,
      "expectedConstructed": false,
      "expectedDelivery": false,
      "expectedBody": null,
      "expectedMutation": false
    },
    {
      "case": "context-missing",
      "text": "{\"id\":\"note-A\",\"title\":\"Tea & Bread\",\"pageCount\":12}",
      "contextPresent": false,
      "readAllowed": null,
      "expectedConstructed": false,
      "expectedDelivery": false,
      "expectedBody": null,
      "expectedMutation": false
    }
  ],
  "pipeline": [
    "JSON values",
    "closed typed DTO",
    "current authorization context",
    "explicit three-field projection",
    "trusted fixed Book constructor",
    "plain caption"
  ],
  "runtimeLedger": {
    "parsedJSONHasBookPrototype": false,
    "textSelectsConstructor": false,
    "methodLoadedFromText": false,
    "freezeIsAuthorization": false,
    "duplicateKeyParserExecuted": false
  },
  "boundaries": {
    "actualUnsafeDeserializer": false,
    "actualDOM": false,
    "actualPersistence": false,
    "actualIdentity": false
  }
}
profile
Local closed contract and trusted constructor selection; input selects no constructor.
rows
Only fixed normal and harmless field/type/context comparisons.
runtimeLedger
Differences between data, class behavior and authorization.

Fixed JSON and an approved Book class; no unsafe loader, gadget, runtime type selector, endpoint or side effect runs.

Two reality checks

JSON.parse returns a trusted domain object.

Parsing produces plain values; schema, context and constructor projection are separate decisions.

A pure data format solves permission problems.

Pure data narrows behavior exposure; business permission is still required.

YOUR TURN

Work through this story.

Predict the outcome, find the evidence boundary, and explain it in your own words.

JSON contains pageCount="12" as a string. Does this Book-reconstruction profile coerce it and construct the object?

  1. Yes. Every numeric-looking string automatically becomes a trusted Book.
  2. No. expectedConstructed=false and body=null.
Read the explained answer

No. expectedConstructed=false and body=null. — This profile requires a numeric pageCount. JSON parsing does not make the string the expected type.

Does JSON parsing load the Book prototype and caption method from the input?

Selected lesson artifact fields; teaching example

runtimeLedger
{"parsedJSONHasBookPrototype":false,"textSelectsConstructor":false,"methodLoadedFromText":false,"freezeIsAuthorization":false,"duplicateKeyParserExecuted":false}
pipeline
["JSON values","closed typed DTO","current authorization context","explicit three-field projection","trusted fixed Book constructor","plain caption"]
  1. No. The approved Book constructor is a fixed application choice.
  2. Yes. JSON object fields select runtime classes and methods.
Read the explained answer

No. The approved Book constructor is a fixed application choice. — parsedJSONHasBookPrototype=false, textSelectsConstructor=false and methodLoadedFromText=false. A fixed constructor follows explicit three-field projection.

The normal shape is valid, but context-missing stops construction. Why is rejecting unknown subtitle not a universal JSON rule?

Read the explained answer

This profile chooses unknownFieldMode=reject; other contracts may explicitly choose preserve or ignore. JSON itself does not prescribe business fields. A valid DTO still needs current read context; without it, construction and delivery stop. Freezing an object grants no permission. This is fixed trusted Book reconstruction, not an unsafe deserializer, DOM or persistence execution.

□ I tied unknown-field behavior to this contract.

□ I separated object shape/freeze from current authorization.

Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples

Sources and scope

  • RFC8259 JSON§3 Values; §4 Objects / member uniqueness · §9 Parsers / limits; §12 Security Considerations
  • MDN JSON.parseSyntax/return value; Description: reviver parameter
  • OWASP Deserialization Cheat SheetIntroduction / What is Deserialization · Language-Agnostic Methods: Using Alternative Data Formats / pure data DTO