feat(runner): SEA-1443 bound the Runner runtime dir under the AF_UNIX socket-path budget - #25
Merged
Merged
Conversation
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Greptile SummaryThis PR validates the Runner runtime directory against the platform AF_UNIX socket-path limit at startup.
Confidence Score: 4/5The PR appears safe to merge, with only the previously reported regression-test coupling issue remaining. The runtime validation and prefix constraint are internally consistent, but the new minting-width regression test still duplicates the minting implementation and therefore will not detect a future width change at the actual minting site. Files Needing Attention: go/internal/runner/run_test.go
|
| Filename | Overview |
|---|---|
| go/cmd/compass-runner/main.go | Replaces the inline production container-name prefix with the shared Runner constant. |
| go/internal/runner/run.go | Adds platform-derived AF_UNIX path budgeting and validates RuntimeDir before network enrollment. |
| go/internal/runner/run_test.go | Adds validator boundary tests, a real kernel socket-bind check, and verification that Run rejects invalid configuration before dialing. |
| go/internal/runner/spec.go | Rejects name prefixes wider than the prefix included in the startup socket-path model. |
| go/internal/runner/spec_test.go | Adds coverage for rejecting a name prefix that exceeds the socket budget allocation. |
Reviews (4): Last reviewed commit: "feat(runner): SEA-1443 bound the runtime..." | Re-trigger Greptile
seal-agent
force-pushed
the
compass-runner-1443-runtime-dir-budget
branch
2 times, most recently
from
July 29, 2026 17:50
1872eb0 to
8dfef67
Compare
…dget Ports sealed#992. Rejects at startup a --runtime-dir that cannot fit the longest agent socket path the Runner will build under it, so a misconfigured deployment fails to boot with a legible message naming the overshoot instead of failing at the first provision with a bare EINVAL. Stacked on the sun_path cap branch, which it collides with in spec.go and spec_test.go: both add a NamePrefix guard at the same startup edge. They are independent properties of one operand and both are kept -- the cap branch rejects a prefix containing a path separator (shape), this one rejects a prefix wider than the budget reserves (length). A shape check cannot catch an over-long prefix and a length check cannot catch a traversing one. Adds the test the budget model was missing. run_test.go's existing tests derive their expectations from the same constants as the code under test, which its own comment notes leaves them green if the model shrinks. The kernel test binds sunPathMax that way; nothing bound agentAccountIDWidth. TestAgentAccountIDWidthMatchesTheMintingSite pins it against the actual construction -- hex.EncodeToString of a 16-byte array -- rather than against the literal 32, so it tests the constant instead of restating it. Verified red-capable: widening the constant to 40 fails with the message naming both widths. The id width itself is still unchecked at provision time, and that is recorded as an open question rather than silently fixed: asserting it would change the Runner's contract with every caller (four test files provision ids like "acct-1"), which is a design call. Refs SEA-1443 Co-Authored-By: seal <noreply@sealedsecurity.com>
seal-agent
force-pushed
the
compass-runner-1443-runtime-dir-budget
branch
from
July 29, 2026 17:54
8dfef67 to
3bd6161
Compare
The id becomes a path component (container name + agent socket path), so constrain it to its minted shape — exactly agentAccountIDWidth lowercase hex — at the provision edge, subsuming the prior shape-only check. Refs SEA-1505. Co-Authored-By: seal <noreply@sealedsecurity.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Ports
sealedsecurity/sealed#992. Rejects at startup a--runtime-dirthat cannot fit thelongest agent socket path the Runner will build under it, so a misconfigured deployment
fails to boot with a message naming the overshoot instead of failing at the first
provision with a bare
EINVAL.Stacked on
compass-runner-sea-1440-sunpath-cap(#12) — it collides with it, and thecollision is the interesting part.
The collision: two guards on one operand, both kept
Both branches add a
NamePrefixcheck at the same startup edge inNewConfigSpecBuilder,which is why the patch does not apply to #12 (
patch failed: go/internal/runner/spec.go:51).They are independent properties of the same value:
A shape check cannot catch an over-long prefix and a length check cannot catch a
traversing one, so keeping either alone would half-enforce the model. Same for the two
test-table rows.
The test the budget model was missing
run_test.go's own comment already named this gap:TestSunPathMaxMatchesTheKernelcloses that forsunPathMaxby binding a real socket.Nothing closed it for
agentAccountIDWidth— the budget clears every path usingstrings.Repeat("0", agentAccountIDWidth), and if the minting site ever changes width, themodel silently clears a path the kernel refuses.
TestAgentAccountIDWidthMatchesTheMintingSitepins it against the actual construction(
hex.EncodeToStringof a 16-byte array, which is whatstore.newIDdoes) rather thanagainst the literal
32. Asserting32 == 32would restate the constant instead of testingit.
Verified red-capable rather than merely observed green:
Restored and re-verified.
Open Question — the third operand is still unchecked
The socket path has three operands. This PR and #12 together bound two of them; the third
is asserted by a comment.
validateRuntimeDirclears a runtime dir by modelling the id as exactly 32 chars. Nothingverifies an incoming id is that wide —
validAccountIDconstrains the shape only. Apath-safe id of 200 chars passes every guard and builds a path 168 bytes past what the
budget cleared: boot passes, bind fails
EINVAL— the exact failure the budget exists toprevent.
I implemented the guard, measured its blast radius, and reverted it.
len(id) != 32reddens three tests in
spec_test.goand would break four test files that provision idslike
"acct-1"and"a". That makes it a change to the Runner's contract with everycaller, not a fixture fix — a design call rather than something to decide by rewriting
tests until they agree with me.
The comment at
spec.go:118-132now states the gap and why it is open, rather than theearlier version which implied the width was covered. A false stated reason is worse than a
stated gap.
Tracked as SEA-1443.
Gate: run locally, because this repo has no CI
sealedsecurity/compasshas no workflows — aCLEANPR here means nothing ran. Localtestimony at
5446670, local == remote == PR head confirmed byrev-parse:-count=1is deliberate:moon run compass-go:test --forcebypasses moon's cache but notgo test's per-package cache, and reports every package(cached)— a green that executednothing.
moon run :cicannot currently complete in an agent shell:compass-go:fmtfails on cleanorigin/mainbecause~/.proto/shims/gofmtprints a 165-byte NDJSON banner on stdout thatout=$(gofmt -l .)captures. Pre-existing, reported to compass-repo, not fixed here.Base verification
All 5 files compared between sealed's merge-base (
fe4e8424) and compassorigin/main:5/5 byte-identical. Against #12's branch, 3/5 identical and 2 divergent — which is the
collision above, found by measurement rather than discovered at apply time.
Refs SEA-1443