Uh oh!
There was an error while loading. Please reload this page.
ci: add PR quality gates (fmt/clippy/test/build) [#230] - #2
Merged
Conversation
Uh oh!
There was an error while loading. Please reload this page.
MichaelTaylor3d added a commit
that referenced
this pull request
Jul 10, 2026
MichaelTaylor3d added a commit
that referenced
this pull request
Jul 10, 2026
MichaelTaylor3d added a commit
that referenced
this pull request
Jul 13, 2026
…residual) Close the LOW-but-real control-token custody residual an adversarial verify found: `load_or_create_token_at` trusted a non-empty pre-existing token file WITHOUT checking who owns it. An unprivileged local user who plants a KNOWN token in the machine-wide state dir (a %PROGRAMDATA% squat, or the narrow window during a service harden) would have the LocalSystem daemon read + trust it, learning the control token → full local `control.*` node control (local privilege escalation). Fix: before trusting an existing token, verify its file OWNER; a foreign-owned token is deleted + regenerated, never returned. Trust rule (pure, unit-tested): - Windows: owner SID SYSTEM (S-1-5-18) / Administrators (S-1-5-32-544) always; a NON-service run also accepts the current process user's SID (dev tokens in the legacy per-user dir); a SERVICE run requires SYSTEM/Administrators. - Unix: owner uid 0 (root) always, else owner == current euid AND mode 0600. Owner read via the existing Get-Acl helper (`dir_owner_sid` renamed to `path_owner_sid`, now used for files too) on Windows and `stat` on Unix; euid via a dependency-free probe file. Layered beneath the §7.3a state-dir hardening (which already purges a squatter-owned dir on a service run — item #2 landed in ee33f1b) as defense-in-depth: it also guards the non-hardened dev path and any harden gap. Coherent with the installer daemon_dir.rs trust model (dir owner SYSTEM/root + interactive-user read). TDD: pure trust-decision helpers + FS-decision + regeneration tests (red→green, Windows path verified locally on win32; unix-gated tests run in CI). SPEC.md §7.3 documents the owner-verification requirement. Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3d added a commit
that referenced
this pull request
Jul 13, 2026
…(#501, #389) (#32) * feat: machine-wide control-token state dir + dig-node open handler (#501, #389) Deliverable A (#501): decouple the control token + paired-token store from the per-user config dir into a machine-wide, identity-INDEPENDENT state dir so the daemon (which may run as a service under a different OS account, e.g. Windows LocalSystem) and the operator CLI resolve the SAME token file. - Add `state::state_dir()`: Windows `%PROGRAMDATA%\DigNode`, Linux `/var/lib/dig-node` (fallback `/etc/dig-node`), macOS `/Library/Application Support/DigNode`; env override `DIG_NODE_STATE_DIR`; legacy per-user fallback for a non-service dev run (back-compat). - Move ONLY control-token + paired-tokens.json there; the bulk per-user `.dig` cache + config.json stay exactly as-is (#96). - Security: created dir/token get a restrictive ACL (Unix 0700 dir / 0600 file; Windows SYSTEM+Admins full + the installing user read, inheritance removed) — never world-readable. The ACL is applied only on FRESH create so a SYSTEM/root service re-run cannot clobber the installer's install-user grant. `dig-node install` pre-creates the dir as the interactive user; the service self-identifies via DIG_NODE_RUN_CONTEXT. - `dig-node pair` reads the token read-only (never mints a phantom the node won't trust) and surfaces a precise service-vs-user remedy; the control.* 401 names the exact path + remedy. Deliverable B (#389): implement `dig-node open <chia://… | urn:dig:chia:…>` (+ --json), the OS scheme-handler target. Strictly validates (only chia/urn-dig schemes; rejects file:/javascript:/data:, shell metacharacters, path traversal, non-64-hex store refs), then opens the default browser at the node's local serve URL via a no-shell launcher behind an injectable trait. Version: 0.26.0 -> 0.27.0 (minor; additive + back-compat). Refs #501 #389 Co-Authored-By: Claude <noreply@anthropic.com> * fix(state): grant creator full ACL, derive Outcome Debug, doc state-dir in SPEC - Windows ACL: grant the CREATING user full (not read-only) on the fresh state dir — the same process that creates the dir must be able to WRITE the token it mints (dev/self-create path failed with Access Denied otherwise). Security property held: every OTHER local user is still denied. Simplify windows_restrict_dir (dirs only). - derive Debug on cli::Outcome (needed for the open.rs error-path test). - Map io::ErrorKind::InvalidInput -> USAGE exit (a rejected `dig-node open` link). - SPEC.md: new §7.3a (state-dir location/resolution/ACL/threat-model), §8.5 (`open` scheme-handler contract), and control-token/paired-token/conformance/ security updates to the state-dir model. Refs #501 #389 Co-Authored-By: Claude <noreply@anthropic.com> * fix(state): clippy cloned-ref-to-slice in state_dir test (CI --all-targets) Co-Authored-By: Claude <noreply@anthropic.com> * fix(state): gate MACHINE_FOLDER to win/macos (dead_code on Linux -D warnings) Co-Authored-By: Claude <noreply@anthropic.com> * fix(state): harden+verify machine state dir on service run (close ProgramData squat P0) The control token grants FULL local control of the node, so its machine-wide state dir (%PROGRAMDATA%\DigNode) must never be readable by Users/Everyone. On Windows %PROGRAMDATA% lets BUILTIN\Users create subfolders, so a low-priv user could pre-create C:\ProgramData\DigNode, become CREATOR OWNER (implicit WRITE_DAC), and control the dir the node writes the control token into — a local privilege escalation. Previously choose_state_dir returned a pre-existing machine dir via the `exists` branch WITHOUT hardening it, and ensure_dir_restricted early-returned on any existing dir, so a squatted dir was trusted as-is. Fix (coherent with dig-installer's daemon_dir.rs contract): on a SERVICE run, before the token is written/read, harden+readback-verify the resolved MACHINE state dir — setowner *S-1-5-18 (SYSTEM) -> /reset (purge foreign ACEs) -> /inheritance:r + grant {SYSTEM:F, Administrators:F, and only-if-discoverable the interactive install-user:R} -> parse `icacls`/Get-Acl readback and assert no Users/Everyone/Authenticated-Users/Anonymous ACE, owner=SYSTEM, inheritance off, no unexpected principal. A squatter-owned pre-existing dir is purged. FAIL CLOSED: if the dir cannot be secured, the node refuses to serve control from it (ephemeral dir + in-memory unauthorizable token), never writing the token into an unsecured dir. Grant principal comes from the CURRENT PROCESS TOKEN (whoami /user), never the spoofable %USERNAME% env, and well-known group SIDs are rejected. A SYSTEM service preserves an installer-set interactive read grant only on a TRUSTED (SYSTEM/Administrators-owned) dir. The CLI (non-service) never hardens — it only reads an existing machine dir, else the legacy per-user dir (unchanged). Dev self-create keeps the creating user FULL so it can write the token it mints. Pure argv builders, the SID reject, and the readback-assertion parser are unit-tested (real ACL is not exercised in CI). SPEC.md §7.3a documents the contract. Co-Authored-By: Claude <noreply@anthropic.com> * fix(state): verify control-token file owner before trusting it (#501 residual) Close the LOW-but-real control-token custody residual an adversarial verify found: `load_or_create_token_at` trusted a non-empty pre-existing token file WITHOUT checking who owns it. An unprivileged local user who plants a KNOWN token in the machine-wide state dir (a %PROGRAMDATA% squat, or the narrow window during a service harden) would have the LocalSystem daemon read + trust it, learning the control token → full local `control.*` node control (local privilege escalation). Fix: before trusting an existing token, verify its file OWNER; a foreign-owned token is deleted + regenerated, never returned. Trust rule (pure, unit-tested): - Windows: owner SID SYSTEM (S-1-5-18) / Administrators (S-1-5-32-544) always; a NON-service run also accepts the current process user's SID (dev tokens in the legacy per-user dir); a SERVICE run requires SYSTEM/Administrators. - Unix: owner uid 0 (root) always, else owner == current euid AND mode 0600. Owner read via the existing Get-Acl helper (`dir_owner_sid` renamed to `path_owner_sid`, now used for files too) on Windows and `stat` on Unix; euid via a dependency-free probe file. Layered beneath the §7.3a state-dir hardening (which already purges a squatter-owned dir on a service run — item #2 landed in ee33f1b) as defense-in-depth: it also guards the non-hardened dev path and any harden gap. Coherent with the installer daemon_dir.rs trust model (dir owner SYSTEM/root + interactive-user read). TDD: pure trust-decision helpers + FS-decision + regeneration tests (red→green, Windows path verified locally on win32; unix-gated tests run in CI). SPEC.md §7.3 documents the owner-verification requirement. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Jul 25, 2026
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 freeto 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.
What
Adds
.github/workflows/ci.yml— the professional PR-gated CI for this Rust workspace, triggeredon: pull_request(tomain) andpushtomain.Jobs (stable
name:= required-check contexts):cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo llvm-cov --workspace --summary-only(runs the whole workspace test suite AND measures line coverage in one instrumented build)Notes
vendor/digstore_guest.wasm) and wired via.cargo/config.tomlDIGSTORE_GUEST_WASM, so the checkout already carries the artifact (CLAUDE.md §3.5).--fail-under-lines 80).-D warnings, 71 tests pass.Version
Patch bump
dig-node-service0.4.0 → 0.4.1 (chore/ci, no behaviour change) to satisfy the version-increment gate.