WEB / WEB-16.S03
Paths, upload, and download authorization
Follow distinct owners of display names, stored keys, owner policy, and response bodies.
1. Core · Mechanism
Read every scenario without motion
Accepted upload
- Attachment intent ready
The attachment intent is supplied: Alice; catalog.txt; text/plain; Tea. The principal is supplied context, not real login evidence. No operation I/O or consumer result has occurred yet.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- No policy decision
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Operation-policy decision
Supplied Alice context permits upload. catalog.txt is an approved display name; text/plain, three Tea bytes and strict UTF-8 pass. No write has run yet.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- Policy accepted
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Storage-key and root selection
The application selects new key asset-02.dat inside its root; display catalog.txt is not used as a path. Exclusive creation is for a separate file without overwriting asset-01.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- Mapped own storage root
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Owned storage operation
Tea bytes were written to new asset-02.dat: reads=0, writes=1. asset-01 bytes remain unchanged. This local write is not proof of a distributed disk/metadata transaction.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- Mapped own storage root
- Owned storage
- Reads=0; writes=1
- Consumer
- No result
- Operation result ready
Completed upload metadata is ready with storedId=asset-02. Display catalog.txt remains separate; upload produces no download body or headers. Consumer update is the next local step.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- Mapped own storage root
- Owned storage
- Stored asset-02 metadata
- Consumer
- No result
- Consumer outcome completed
The local consumer received new storedId=asset-02 metadata. Existing asset-01 remains unchanged; this upload outcome is not a download body, browser receipt or permission for another resource.
- Attachment intent
- Alice; catalog.txt; text/plain; Tea
- Policy gate
- Mapped own storage root
- Owned storage
- Stored asset-02 metadata
- Consumer
- Uploaded asset-02
Owner download
- Attachment intent ready
The attachment intent is supplied: Alice; asset-01 download. The principal is supplied context, not real login evidence. No operation I/O or consumer result has occurred yet.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- No policy decision
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Operation-policy decision
Alice matches asset-01 metadata owner Alice. This finite resource policy admits the read; ID knowledge or filename alone grants no permission. The file has not been read yet.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- Policy accepted
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Storage-key and root selection
Metadata selects key asset-01.dat and its resolved parent matches the example root. Root checking differs from resource permission; the model adds no general race-free guarantee between resolve and open.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- Mapped own storage root
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Owned storage operation
Tea bytes were read from selected asset-01.dat: reads=1, writes=0. A body can be prepared now; the consumer has not used the result and browser delivery is not established.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- Mapped own storage root
- Owned storage
- Reads=1; writes=0
- Consumer
- No result
- Operation result ready
The response record is ready with body=Tea, Content-Type text/plain; charset=utf-8 and attachment; filename="memo.txt". The header is presentation advice; the consumer has not received it and browser saving is unproven.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- Mapped own storage root
- Owned storage
- Approved Tea response record
- Consumer
- No result
- Consumer outcome completed
The local consumer received Tea and approved download metadata. reads=1, writes=0 remain; no actual file-save outcome is inferred because this model runs no HTTP server/browser.
- Attachment intent
- Alice; asset-01 download
- Policy gate
- Mapped own storage root
- Owned storage
- Approved Tea response record
- Consumer
- Delivered Tea; reads=1
Denied download
- Attachment intent ready
The attachment intent is supplied: Bob; asset-01 download. The principal is supplied context, not real login evidence. No operation I/O or consumer result has occurred yet.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- No policy decision
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Operation-policy decision
Bob does not match record owner Alice; resource-policy is rejected. This decision precedes storage operations; no file read or new write starts.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- Rejected: resource-policy
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Storage-key and root selection
The preceding policy rejection prevents storage mapping/root evaluation. No operation file is opened or created; initial metadata and bytes remain unchanged.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- Storage not evaluated
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Owned storage operation
The rejected operation retains reads=0 and writes=0. A separate inspection read does not count as I/O by the rejected download or upload.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- Storage not evaluated
- Owned storage
- Reads=0; writes=0
- Consumer
- No result
- Operation result ready
No new storedId, body or headers are prepared. Rejection does not reuse an earlier Tea result as empty success; the consumer has not updated yet.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- Storage not evaluated
- Owned storage
- No body; no metadata change
- Consumer
- No result
- Consumer outcome completed
The consumer shows resource-policy rejection: body=null, headers=null and no new metadata. No storage I/O ran; this local outcome is not an HTTP status or browser-download observation.
- Attachment intent
- Bob; asset-01 download
- Policy gate
- Storage not evaluated
- Owned storage
- No body; no metadata change
- Consumer
- No result; resource-policy
Media mismatch
- Attachment intent ready
The attachment intent is supplied: Alice; catalog.txt; image/png; Tea. The principal is supplied context, not real login evidence. No operation I/O or consumer result has occurred yet.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- No policy decision
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Operation-policy decision
Declared image/png does not satisfy required text/plain; text-profile is rejected. This decision precedes storage operations; no file read or new write starts.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- Rejected: text-profile
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Storage-key and root selection
The preceding policy rejection prevents storage mapping/root evaluation. No operation file is opened or created; initial metadata and bytes remain unchanged.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- Storage not evaluated
- Owned storage
- Seed unchanged; no operation I/O
- Consumer
- No result
- Owned storage operation
The rejected operation retains reads=0 and writes=0. A separate inspection read does not count as I/O by the rejected download or upload.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- Storage not evaluated
- Owned storage
- Reads=0; writes=0
- Consumer
- No result
- Operation result ready
No new storedId, body or headers are prepared. Rejection does not reuse an earlier Tea result as empty success; the consumer has not updated yet.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- Storage not evaluated
- Owned storage
- No body; no metadata change
- Consumer
- No result
- Consumer outcome completed
The consumer shows text-profile rejection: body=null, headers=null and no new metadata. No storage I/O ran; this local outcome is not an HTTP status or browser-download observation.
- Attachment intent
- Alice; catalog.txt; image/png; Tea
- Policy gate
- Storage not evaluated
- Owned storage
- No body; no metadata change
- Consumer
- No result; text-profile
ACTORS · STATE · DATA FLOW
Resource IDs, display filenames, and storage paths differ
Atlas keeps three names for a text attachment. asset-01 is the resource ID, memo.txt is a presented display filename, and asset-01.dat is the application’s own storage key. A client filename does not directly become a filesystem path. The download handler receives a resource ID, locates its metadata record, and chooses a path from that record. Opaque naming does not replace authorization; the relevant policy is still evaluated on each read.
The example’s local storage holds Tea bytes. Existing asset-01 stays unchanged; an accepted upload creates separate asset-02.dat. The display name catalog.txt is another metadata field. This mapping exposes why storage naming and HTTP presentation naming differ. Local file behavior does not establish the behavior of an object store, web-server alias, or shared volume.
A canonical path is not a permission decision
Python Path.resolve resolves symlinks in the own filesystem and produces an absolute path. Here public-link.dat points to asset-01.dat inside the same root: the lexical basename differs while the resolved target is the same file. Allowed-root decisions do not use a raw string prefix. The selected profile requires the resolved parent to equal the own root exactly; it does not support nested directories.
That check is separate from resource-owner policy. Even when Alice is permitted to read her asset, metadata accidentally pointing to catalog.txt in an own sibling directory causes storage-root rejection before the operation reads the file. The native fixture creates this ordinary incorrect mapping itself, without traversal input or an external file. It gives no general race-free guarantee between resolve and later open. Production file handles, directory ownership, and filesystem concurrency need additional design.
Upload admission includes more than a filename
This teaching profile accepts only memo.txt/catalog.txt display choices, declared text/plain, 1–16 bytes, and strict UTF-8 text. Supplied Alice context permits upload, while Bob causes no write. A declared image/png with ordinary Tea bytes stops at the text-profile gate. Content-Type is a client declaration; putting a value in a header does not prove that the bytes have the required format.
An accepted upload uses exclusive creation at a generated storage key rather than overwriting an existing resource with the same display filename. Metadata is prepared after writing bytes. Actual write/readback checks observe Tea and the asset-02 key, without claiming a distributed transaction across disk and metadata. Real upload services also need multipart parsing, authentication, CSRF policy, quarantine/scanning, storage quotas, and cleanup. No image/PDF/parser payload or malware sample is processed here.
Download permission precedes reading bytes
The download branch evaluates a finite policy between the supplied principal and metadata owner before reading a body. Alice is admitted for asset-01, the resolved storage root is checked, and Tea bytes are then read. Bob receives resource-policy rejection for the same known resource: reads=0, null body, and null headers. Successful resource lookup and delivery to a caller are separate facts.
A missing principal is NOT-COMPUTED; absent identity evidence does not become permission. An unknown asset ID also performs no read. A real endpoint’s disclosure policy across not-found/denied responses is a separate design choice; no HTTP status or timing is observed here. Identity aliases are fixed supplied context, not real login/session verification. Keeping that boundary explicit prevents the policy model from being presented as a working authorization infrastructure.
Content-Type and Content-Disposition have different roles
For an admitted download, the application selects text/plain; charset=utf-8 and attachment; filename="memo.txt" in a response record. Content-Type indicates the representation’s media type. Content-Disposition attachment suggests default save handling to a recipient; the filename is advisory rather than the recipient’s storage path or the server’s resource ID. Preparing a header does not establish that a browser actually saved the file.
The native check starts no HTTP server; headers are local typed records. ASCII display labels come from an approved fixed set. Arbitrary filename-header serialization, Unicode filename* interoperability, and MIME-sniffing behavior are not tested. Choosing a media type does not bypass download authorization; denied branches have neither header. Showing this artifact in the static site does not expose an actual download endpoint for these bytes.
Keep four stages of operation evidence separate
The artifact distinguishes intent, policy, storage I/O, and consumer outcome. Upload success produces writes=1 and a storedId, without a download body. Download success produces reads=1 and body Tea, without mutating the file. Media mismatch and denied read retain I/O count=0. The consumer changes only after a completed approved operation, so an earlier success cannot hide a new rejection.
Separate operation counts from reads used to verify the result. Reading an existing file for inspection does not mean the rejected-download function read it. Specify the expected Tea bytes, metadata keys, and new-file state separately for each branch. This keeps the operation’s result distinct from subsequent observation. Local file examples provide no general guarantee for arbitrary paths or OS isolation.
2. Red · Trust & Impact
Read every scenario without motion
Owner mismatch
- The requested file operation was selected
Bob requests download of asset-01, owned by Alice. Knowing the asset ID does not grant read permission.
- Upload/download context
- case=denied
- Resource/format policy
- Gate not examined
- Storage/response boundary
- No I/O
- The authoritative consumer rule was separated
The fixture uses supplied Alice-equals-owner policy, without actual authentication. Bob is a known mismatch, not a missing principal.
- Upload/download context
- case=denied
- Resource/format policy
- Known owner mismatch
- Storage/response boundary
- No I/O
- The first failing gate stopped before I/O
Expected decision is REJECT with reason resource-policy. Metadata relationship checking occurs before reading file bytes.
- Upload/download context
- case=denied
- Resource/format policy
- Reason: resource-policy
- Storage/response boundary
- No I/O
- The negative I/O outcome was preserved
reads=0, writes=0 and storedId=null remain. Denial is not shown as hiding a completed read/write; the operation does not proceed in this case.
- Upload/download context
- case=denied
- Resource/format policy
- No storage operation
- Storage/response boundary
- Reads=0; writes=0
- Body and header projection stayed closed
body=null and headers=null form the negative consumer boundary. An attachment filename or response media type cannot create passage through the failed resource/profile gate.
- Upload/download context
- case=denied
- Resource/format policy
- REJECT
- Storage/response boundary
- No body or headers
- The denial scope was not generalized incorrectly
The fixture shows owner mismatch; opaque IDs or UI links do not replace authorization. General root/race-hardening guarantees are not inferred from this record.
- Upload/download context
- case=denied
- Resource/format policy
- Known: failed consumer gate
- Storage/response boundary
- Known: I/O/body/header withheld
Media mismatch
- The requested file operation was selected
Alice requests a text-profile upload with display name catalog.txt but declares media image/png. Client filename and media are neither storage keys nor accepted format.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- Gate not examined
- Storage/response boundary
- No I/O
- The authoritative consumer rule was separated
The profile requires declaredMedia=text/plain and strict UTF-8 text. Even passing the media declaration cannot replace byte validation; this media gate already mismatches.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- Known text-profile mismatch
- Storage/response boundary
- No I/O
- The first failing gate stopped before I/O
Expected decision is REJECT with reason text-profile. The upload stops at this profile boundary before storage writing starts.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- Reason: text-profile
- Storage/response boundary
- No I/O
- The negative I/O outcome was preserved
reads=0, writes=0 and storedId=null remain. Denial is not shown as hiding a completed read/write; the operation does not proceed in this case.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- No storage operation
- Storage/response boundary
- Reads=0; writes=0
- Body and header projection stayed closed
body=null and headers=null form the negative consumer boundary. An attachment filename or response media type cannot create passage through the failed resource/profile gate.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- REJECT
- Storage/response boundary
- No body or headers
- The denial scope was not generalized incorrectly
The fixture shows declared-media mismatch; a text profile is not safety for every PDF/archive/media decoder. Other formats need their own validation and isolation contracts.
- Upload/download context
- case=media-mismatch
- Resource/format policy
- Known: failed consumer gate
- Storage/response boundary
- Known: I/O/body/header withheld
ASSUMPTION · BOUNDARY · CONTROL
Review metadata mapping alongside access decisions
In a file review, separate names influenced by the client from names selected by the backend. Display filename, resource ID, and actual storage key differ in the artifact. A UI link labeled memo.txt does not establish a disk path. Likewise, hard-to-guess asset IDs do not replace owner/resource policy; consider the read decision in every request context.
Rejection is measured beyond a text error. The actual function returns reads=0, no body/headers, and unchanged own existing bytes. An incorrect storage mapping stops at the root gate even when the owner is permitted. These failures differ: resource policy versus a storage boundary. A review should not combine them into a single not-found conclusion without stating its evidence.
Ordinary failures do not certify format safety
A declared-media mismatch shows upload admission taking effect. A text/plain declaration alone does not establish content safety; selected bytes are separately decoded as strict UTF-8. This profile is not an HTML, PDF, archive, or media-processing pipeline. Passing strings to another interpreter involves separate boundaries in the preceding interpretation and following isolation lessons.
The Path.resolve observation is narrow too. Resolving a symlink within the same root does not establish safe handling of concurrent filesystem changes or every possible path. The review is supported by the explicit relationship among owner aliases, key mappings, root policy, observed I/O, and consumer outcome. Concurrency and filesystem permissions outside that relationship require separate assessment.
3. Blue · Secure development & defense
Read every scenario without motion
Name mapping
- The download metadata was selected
Seed resource id asset-01, storageKey asset-01.dat and displayName memo.txt are separate fields. These names establish different roles for the same file.
- File metadata observation
- Asset metadata
- Mapping/context review
- Mapping not examined
- Evidence conclusion
- No header/body outcome
- The resource-owner decision was read
The download for principal Alice expects ACCEPT. This alias does not replace identity verification; it is a limited input under the profile’s owner-equality rule.
- File metadata observation
- Resource asset-01; owner Alice
- Mapping/context review
- Declared owner match
- Evidence conclusion
- No header/body outcome
- Storage and display names were compared
The application-selected storage key is asset-01.dat. Download filename memo.txt is approved presentation metadata; recipients should not treat it as a server disk path.
- File metadata observation
- Storage: asset-01.dat
- Mapping/context review
- Display: memo.txt
- Evidence conclusion
- Distinct naming roles
- The response projection was read
Expected body is Tea with Content-Type text/plain; charset=utf-8. Content-Disposition attachment; filename="memo.txt" is metadata, not read permission.
- File metadata observation
- Reads=1; writes=0
- Mapping/context review
- Selected text response
- Evidence conclusion
- Attachment presentation only
- The upload’s exclusive identity stayed separate
The accepted upload produces storedId=asset-02, not an overwrite of seed asset-01. Display name catalog.txt is not a path converted into this new opaque storage key.
- File metadata observation
- Seed retained: asset-01
- Mapping/context review
- Upload separate: asset-02
- Evidence conclusion
- Display/storage mapping explicit
- The metadata conclusion stayed in scope
The ledger shows I/O counts and header/body projection. Browser saving, actual object-store consistency and general filename-serializer safety need separate evidence.
- File metadata observation
- Known: distinct naming roles
- Mapping/context review
- Known: selected response projection
- Evidence conclusion
- Broader storage/browser behavior unknown
Missing principal
- The missing-principal scope was selected
The scope starts with missing.principal=null. The known subject from the Bob-mismatch row is not inserted into this gap; trusted identity evidence is missing.
- File metadata observation
- Principal=null
- Mapping/context review
- Policy not computed
- Evidence conclusion
- No I/O/body
- The NOT-COMPUTED decision was read
The decision is NOT-COMPUTED. Missing input establishes neither known owner denial nor existence/absence of an unknown resource.
- File metadata observation
- Principal=null
- Mapping/context review
- Decision NOT-COMPUTED
- Evidence conclusion
- No owner-attribution result
- Reads and writes were checked separately
reads=0 and writes=0 remain. Failure to resolve a trusted principal does not justify storage processing or guessed Alice context.
- File metadata observation
- Missing identity evidence
- Mapping/context review
- No storage operation
- Evidence conclusion
- Reads=0; writes=0
- No response body was produced
body=null remains. A public display name in metadata does not automatically expose file bytes to a consumer with missing principal evidence.
- File metadata observation
- Missing identity evidence
- Mapping/context review
- No accepted download
- Evidence conclusion
- Body=null
- A trusted-context source was requested
A resource action needs server identity binding and owner-policy evidence. Client-supplied names or attachment headers cannot verify this missing context.
- File metadata observation
- Missing principal known
- Mapping/context review
- Trusted binding evidence required
- Evidence conclusion
- No guessed permission
- Unknown and hostile remained distinct
The known outcome is no I/O and no body; the caller’s actual identity or permission outcome is unknown. A missing principal is not automatically evidence of malicious intent.
- File metadata observation
- Known: input missing
- Mapping/context review
- Known: not computed
- Evidence conclusion
- UNKNOWN: identity/permission
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Generate storage keys and authorize before reads
Use an approved application key mapping rather than reusing client filenames as storage identifiers. The fixed generated asset-02 key differs from existing asset-01; exclusive creation prevents overwriting existing bytes. Download metadata-owner policy runs before reading a body. Root checking remains a separate storage responsibility, so successful authorization does not legitimize a wrong mapping.
Production identity evidence must come from trusted server context; static Alice does not test it. Upload admission, storage commit, metadata publication, and serving policies also need failure/cleanup plans. This artifact covers ordinary text and finite context decisions only. Reduced motion preserves no-body rejection and completed read/write counts for the consumer.
Include headers and format policy in regression evidence
Do not treat an upload declaration as the sole proof of byte format. Record admitted-format validation, byte budgets, and storage naming together. Download metadata should select the right media type and an approved safe display name; recipients should not trust advisory filenames as storage-path instructions. Attachment handling does not replace authorization. The header check here is neither a browser-save nor a general serializer test.
Specify expected I/O and outcomes separately for accepted upload, admitted read, denied read, and media-mismatched upload. Keep unknown resources distinct from missing principals. Operation counters exclude reads made to verify the result. Streaming limits, MIME sniffing, malware scanning, object-store consistency, and filesystem races lie outside this local text profile. A successful control does not establish those additional responsibilities.
NOW APPLY IT TO THE CASE
At which gate must upload/download withhold I/O?
The application generates storage keys while display metadata remains separate. Negative resource-policy and text-profile branches produce no reads, writes, body or headers.
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 text attachment responsibility ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"profile": {
"displayNames": [
"memo.txt",
"catalog.txt"
],
"declaredMedia": "text/plain",
"byteRange": [
1,
16
],
"contentValidation": "strict UTF-8 text",
"storageKeys": "application-generated opaque IDs",
"rootRule": "resolved parent equals own root; no nested dirs",
"ownerPolicy": "supplied Alice equals record owner; no real authentication"
},
"seed": {
"id": "asset-01",
"owner": "Alice",
"storageKey": "asset-01.dat",
"displayName": "memo.txt",
"bytesHex": "546561"
},
"inputs": {
"upload": {
"principal": "Alice",
"display": "catalog.txt",
"media": "text/plain",
"bytesHex": "546561"
},
"download": {
"principal": "Alice",
"resourceId": "asset-01"
},
"denied": {
"principal": "Bob",
"resourceId": "asset-01"
},
"media-mismatch": {
"principal": "Alice",
"display": "catalog.txt",
"media": "image/png",
"bytesHex": "546561"
}
},
"expected": {
"upload": {
"decision": "ACCEPT",
"reason": "stored-text",
"reads": 0,
"writes": 1,
"storedId": "asset-02",
"body": null,
"headers": null
},
"download": {
"decision": "ACCEPT",
"reason": "delivered-text",
"reads": 1,
"writes": 0,
"storedId": "asset-01",
"body": "Tea",
"headers": {
"Content-Type": "text/plain; charset=utf-8",
"Content-Disposition": "attachment; filename=\"memo.txt\""
}
},
"denied": {
"decision": "REJECT",
"reason": "resource-policy",
"reads": 0,
"writes": 0,
"storedId": null,
"body": null,
"headers": null
},
"media-mismatch": {
"decision": "REJECT",
"reason": "text-profile",
"reads": 0,
"writes": 0,
"storedId": null,
"body": null,
"headers": null
}
},
"missing": {
"principal": null,
"decision": "NOT-COMPUTED",
"reads": 0,
"writes": 0,
"body": null
}
}- seed / inputs
- Own ordinary text and supplied identity aliases; opaque IDs, paths, and displays differ.
- reads / writes
- Operation I/O counts, separate from proof inspection.
- storedId / body
- Upload metadata differs from completed download delivery.
- headers
- Approved local response record, not actual HTTP/browser execution.
Own auto-cleaned local text files and finite supplied-context policy; actual Path.resolve/internal symlink. No HTTP/browser, real identity/tenant, arbitrary paths/traversal, OS-race isolation, scanning, or cloud verification.
Two reality checks
An opaque asset ID or canonical path establishes permission.
ID/path resolution and caller-resource policy make distinct decisions.
Content-Type and attachment establish complete file safety.
Byte validation, storage policy, authorization, and recipient handling are different boundaries.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
Bob requests asset-01, but Alice owns the record. Is the file read or a body prepared?
- No. reads=0, writes=0 and body=null.
- Yes. Any existing resource ID is a public download for every principal.
Read the explained answer
No. reads=0, writes=0 and body=null. — The resource-policy rejection applies before storage reads. Knowing the resource ID does not grant download permission.
Why are the memo.txt display name and asset-01.dat storage key separate?
Selected lesson artifact fields; teaching example
- seed.id
- asset-01
- seed.storageKey
- asset-01.dat
- seed.displayName
- memo.txt
- expected.download.headers
- {"Content-Type":"text/plain; charset=utf-8","Content-Disposition":"attachment; filename=\"memo.txt\""}
- The filename in Content-Disposition determines the entire filesystem path.
- The display name is presentation; the application chooses the storage key.
Read the explained answer
The display name is presentation; the application chooses the storage key. — The attachment header presents memo.txt while the backing key remains asset-01.dat. A client display name grants no filesystem-path authority.
Tea bytes labelled image/png are rejected by text-profile. Why are content validation and owner policy separate, and what happens with a missing principal?
Read the explained answer
This narrow upload contract requires text/plain, a byte range and strict UTF-8. Acceptable content does not grant the principal resource permission. The application generates the storage key and separately restricts root mapping. Missing principal yields NOT-COMPUTED with no reads, writes or body. This text-only example is no guarantee for every file type or real authentication.
□ I separated content validation from owner permission.
□ I did not turn missing principal into automatic allow or hostile attribution.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- OWASP — File Upload Cheat SheetContent-Type Validation · Filename Safety · File Storage Location · User Permissions · Upload and Download Limits
- OWASP — Authorization Cheat SheetValidate the Permissions on Every Request · Enforce Authorization Checks on Static Resources · Ensure Lookup IDs are Not Accessible Even When Guessed or Cannot Be Tampered With
- Python — pathlibPath.resolve; symlink resolution and strict mode · PurePath.parent; lexical operation
- RFC 9110 — HTTP Semantics8.3 Content-Type
- RFC 6266 — Content-Disposition4.2 Disposition Type · 4.3 Disposition Parameter: Filename; advisory filenames