Request helper: private exchange body, filtered refusals, a checked upload directory #288
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the architect review of #287 (
torb owner --step-up), out of its scope:tokenForincompiler/src/package/upload.trbwritesexchange.json, which holds the CI job's identity token, withwriteText(default mode) and empties it afterwards. It should go throughwritePrivatelike the header files.refusalOfprints the registry's body as it came where it is not the service's JSON, so a hostile or broken registry can put terminal escape sequences on standard error, for every registry command. Strip control characters there.requestaccepts a<cache>/uploadthat is a symbolic link or belongs to another user (a sharedTORB_CACHEunder/tmp). Refuse it unless it is a real directory owned by the user.#287 already makes the directory
0700, makes the private files anew and empties all three files even where one fails.torb owner --step-up: approve owner changes with a passkey #280[loop:torbscript] intake: in scope (author orion, follow-up of the architect review on PR #287 for #280), not a duplicate, no collision with a design record; security hardening of the registry request helper in compiler/src/package. next: refine
[loop:torbscript] refine: ready, one PR (read against main after #287 landed; all three points are in
compiler/src/package/upload.trb, tests incompiler/tests/packages.test.trb).Goal. The request helper stops leaving a token in a world-readable file, stops printing a registry's raw bytes to the terminal, and refuses an upload directory that is not the user's own.
Acceptance criteria (each with a test)
tokenForwrites<work>/upload/exchange.jsonthroughwritePrivate(made anew, mode0600while still empty), and empties it afterwards as today, also where the exchange fails. Test: the file's mode after a failed and after a successful exchange.refusalOfstrips control characters (C0 except none kept, DEL, C1, so ESC, CSI and OSC cannot start a sequence) from the body it prints where the body is not the service's JSON; the same for the identity-token answer text intokenForand theerrorfield of a JSON answer, since a hostile registry controls those too. Newlines inside the text become a single space. Test: a body with\u001b[2Jand\u001b]0;x\u0007comes out as plain text.requestrefuses<work>/uploadwhen it is a symbolic link, is not a directory, or is owned by another user, with a message naming the path and the reason, before any file is written into it and beforechmod. A real directory of the user (existing or just created) works as today. Tests: a symlink to a directory, a regular file in its place, and the normal case; the other-owner case is covered where the test can arrange it, else by the owner check being a separate function with a unit test.torb login,torb owner,torb yankandpublishkeep working unchanged (existing loopback tests stay green).Seed. No syntax change. If
std/fsalready offers a symlink and owner query, no seed impact. If the owner or link query is missing, add it as a method ofFile(methods over free functions, naming per the std conventions) under the two-commit rule: the compiler/std change first, the use inupload.trbsecond; the seed refresh stays Torben's. Decision by the loop: the check belongs inrequestitself, since all registry commands go through it; no new env var and no opt-out.Size. One PR, one or two Conventional Commits (
fix(package): ...), no docs change beyond the doc comment ofrequest(it states the directory contract); ifdocs/mentions the upload directory, update it and regenerateskills/.Collision. #279 (in flight) uses
requestbut does not edit this file; rebase before pushing.[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T06:10Z (ready, refined in the comment above)
[loop:torbscript] implement: PR #294, CI success (tier A and tools/registry green, run 717), worker usage ~160k tokens, next: waiting (review by the merge gate argus). Decided by the loop: the "owned by another user" half of criterion 3 needs a new std/fs owner native whose use must wait for a seed refresh (two-commit rule), so it moved to #293 with the registry.trb body writes; until then the chmod to 0700 after the new link/directory checks fails for non-root users on a foreign directory.