A nonempty output descriptor lets stale bytes pass as this request's output
- Dominant language
- Ruby
- Stars
- 23
- Forks
- 0
- Avg merge
- 11h 43m
- Merged PRs (30d)
- 27
Description
Bytes a request never produced can be reported as that request's successful output. `descriptors.rb` validates that an output is a regular file, one-way, and not `O_APPEND`, but never checks its initial size or offset. A direct output then reports the file's total final size rather than what this request wrote, and a staged copy writes without truncating the caller's file first (`Output#post`). Both the worker and the client reject only a measured final size of zero.
Reproduced through the server harness and through the documented `HotCell::Client#perform_in_hotcell` API, against a caller file already containing `SECRET-TAIL`:
```
silent operation -> success, "SECRET-TAIL"
one-byte write -> success, "XECRET-TAIL"
```
The cell cannot read those bytes, so one-way access still holds. The defect is attribution: an old sensitive tail can be published or attached as fresh output, and content can be smuggled or corrupted under a success verdict.
The shipped Active Storage integration is unaffected — it opens fresh, truncated tempfiles. This reaches custom clients, and our custom-client documentation does not state the invariant.
## Fix direction
Reject, on both client and server, any output whose initial size or current offset is nonzero. Reject rather than truncate: silently destroying caller data is the worse failure. Measure bytes produced by the request rather than the file's total size.
Acceptance: reject nonempty and nonzero-offset outputs before the operation runs; test every member of a multi-output call; a one-byte write leaves exactly one byte; a silent operation stays a transient failure.
`HC-PT-006` of the purple-team assessment of 2026-08-22, rated Medium for custom clients.
Contributor guide
Research direction
Start with descriptors.rb and Output#post, then trace the corresponding client and server output handling through the server harness and documented HotCell::Client#perform_in_hotcell API. Verify behavior for every output in a multi-output call: nonempty or nonzero-offset files are rejected before execution, a one-byte write leaves exactly one byte, and a silent operation is a transient failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100