Skip to content

microVM JIT credential mint + jail staging - #11905

Closed
gunbai-bot[bot] wants to merge 2 commits into
mainfrom
three-findings
Closed

gunbai-bot[bot] wants to merge 2 commits into
mainfrom
three-findings

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session keen-bear-791.
Pushing to three-findings advances this PR.

Worker attestation

Before flipping this PR to ready for review, confirm each item:

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why (replace the TODO below).
  • Tests run: name the command (e.g. npm test, cargo test) and the result.
  • If this closes a work item, the body contains a Closes #N directive.
  • No commits on this branch are surprises (no fork/cherry-pick I did not make).
  • No secrets / credentials / large binaries staged.

Summary

TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.

Test plan

  • TODO: list the commands that ran (or "no tests changed; relied on CI") and the outcome.

gunbc-ci-auto-heal and others added 2 commits September 20, 2026 20:12
…t merged

#11679's park verdict arrived after it landed, so all three findings are on
main. Repaired here in one change.

(a) THE ORDER WAS COMMENT-VERSUS-CODE, AND WORSE, IT WAS ENCODED IN TWO
WITNESS NAMES. converge_controller_app_key called ensure_key_dir, which
runs `install -d` and THEN observes, before observe_upper_ancestors -- so a
host mutation preceded the observation entitled to refuse the whole
converge. No key was ever written (controller_app_key_action decides after
every observation), so the residue was an empty root-owned directory rather
than a custody hole. But an_unsafe_directory_refuses_before_any_write and
a_writable_ancestor_refuses_before_any_write call only the pure decision
with supplied observations, so they stayed green while advertising a
property the production route did not have.

Both repairs, not one: the create is now gated on the ancestor reading (on
the refusing arm the directory is only OBSERVED, which is a read), and the
two witnesses are renamed to what a claim over a pure function can
establish -- refuses before any KEY-CONTENT write. controller_app_key_action
is untouched, so the decision keeps its single authority.

(b) CUSTODY WAS COUPLED TO RUNNER WIDTH. The entry resolved its host through
runner_host_file_subject, which requires an admitted RunnerHostDeploy -- a
spec plus an admitted WIDTH. srv2's width is unresolved, so srv2 has no
deploy row and the mode terminated on srv2 while describing itself as
covering srv1 and srv2. The App key's location, administrator target and
custody do not depend on how many slots a host admits, so the module now
resolves its own subject from runner_host_spec_for, which names srv2's
address and principals independently of width.

The privilege law is NOT dropped with the deploy row: the writer may not be
the account CI jobs run as, and that comparison keeps its one authority --
gunbc.runner_host_grants gains bootstrap_principal_is_not_the_job_user, and
the existing deploy-shaped predicate now calls it rather than being
duplicated. The new subject deliberately carries no unit populations: this
module verifies no teardown, so a value with empty unit lists would lie
about what was established.

(c) THE STAGING ABSENCE PROBE COULD FALSELY CONFIRM. `test -e` exit 1 became
StagingAbsent, and GNU test -e is stat(path) == 0, so EACCES, ELOOP, ENOTDIR
and EIO all answer 1 with an empty stderr -- and StagingAbsent is an input
to ControllerAppKeyHeld, so a metadata failure would have been reported as
custody held with no residue. Absence is now established by a successful
listing of the PARENT, which is gunbc.live_deploy.member_observe's rule
rather than a second vocabulary.

The departure from that authority is stated rather than silent (DESIGN §3b):
entry_presence reaches the far side as the bootstrap principal, and this
parent is the key directory at root:root 0700, so an unelevated listing can
only ever refuse -- it would answer Indeterminate on every host whether or
not residue exists. The same membership question therefore runs over this
module's elevated leg. classify_staging_residue is now pure over a listing
that SUCCEEDED, so StagingUnobservable has no constructor inside it; that
arm belongs to the leg.

EXECUTED EVIDENCE: all 21 witnesses in
microvm_controller_app_key_converge_witness_test pass, including three new
discriminating ones -- srv2 resolves a custody subject although the deploy
route still refuses it (which is the pair that would go red if custody were
re-coupled to width), and the parent listing establishing absence, residue
and the empty-listing case.

Retained untouched, as the reviewer asked: the key path consumed from the
signer's own JwsSigningKeyRef, the placement refusing the fabric-cell tree,
RemoteFileModeOwnerRead closing the octal vocabulary at 0400, the
byte-for-byte comparison against the resolved SM version, the full re-read
after mutation, no key bytes in any receipt, and the old runner-owned key
left alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eview 69368)

Both findings are the same class, both are right, and the sharper point is
that this diff applied the correct standard one line earlier -- the privilege
predicate was deliberately extracted to keep one authority -- and then broke
it twice in the same file.

1. The staging listing argv and the membership read were re-spellings of
   gunbc.live_deploy.member_observe entry_presence_in_parent. The stated
   §3b departure argues only that the TRANSPORT must be this module's
   elevated leg; it does not reach the argv or the predicate, which are the
   same facts whichever principal runs them. And the copies had ALREADY
   drifted in the commit that created them: mine trimmed each line, the
   original does not -- two sources that can answer one question
   differently, which is the fork §3 forbids and the drift §2 predicts.

   member_observe now exports the two pure halves, parent_listing_argv and
   listing_contains_entry, and BOTH entry_presence_in_parent and this module
   consume them. The elevated transport stays here, because that is the only
   part that actually differs.

2. The administrator SSH target was re-spelled from
   runner_host_file_subject_over_obligation. gunbc.runner_host_file_converge
   now exports administrator_ssh_target -- the endpoint from the fleet reach
   authority, the principal from the declared administrator, neither
   depending on the deploy row -- and both subjects consume it.

Executed: 21/21 microvm_controller_app_key_converge witnesses still pass,
and member_observe's own consumers (member_identity_witness_test) stay green
after the extraction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Stray duplicate: auto-push published my local branch three-findings, which carries the identical head (954ff01f9c5) as #11902 (session/keen-bear-791-three-findings). #11902 is the real PR. Closing and deleting the branch.

@gunbai-bot gunbai-bot Bot closed this Sep 20, 2026
@gunbai-bot
gunbai-bot Bot deleted the three-findings branch September 20, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants