Skip to content

SEC-007: Harden backend process recovery - #295

Draft
budzeg wants to merge 1 commit into
mainfrom
budzeg/sec-007-process-records
Draft

SEC-007: Harden backend process recovery#295
budzeg wants to merge 1 commit into
mainfrom
budzeg/sec-007-process-records

Conversation

@budzeg

@budzeg budzeg commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Berd’s backend process recovery and shutdown handling relied on mutable pathnames and process identifiers that could become stale. This could allow pathname substitution, unsafe record permissions, PID reuse, or cleanup races to cause Berd to signal an unrelated process or modify the wrong filesystem object.

  • Add a bounded, owner-private recovery-record store with retained-directory operations, no-replace publication, verified reads, and exact-object deletion.
  • Bind process signaling to captured identity, revalidate identity before escalation, and retain recovery evidence whenever exit or exact cleanup cannot be confirmed.
  • Make backend startup, readiness-failure handling, singleton shutdown, and app-exit teardown bounded, asynchronous, and successor-safe.
  • Fail closed on macOS by using deletion-only recovery records when stable process-bound executable identity is unavailable.
  • Harden Windows storage with retained-root handle operations, owner-only protected DACL validation, reparse rejection, bounded directory parsing, handle-relative rename, and exact-handle deletion.
  • Add lifecycle and adversarial regressions covering PID reuse, identity changes, publication and retention failures, cleanup timeouts, path substitution, hostile ACLs, root swaps, reparse children, and pathname successors.

This is a high-sensitivity change to Berd’s backend lifecycle and local recovery-record storage, with platform-specific behavior. No current architectural law directly governs backend process-record storage or teardown (LAWS/README.md, LAWS/AGENTS.md, LAWS/CHAT.md).

Full native Windows adversarial verification remains a merge blocker. GitHub’s native Windows/MSVC CI compiled the implementation and passed its 71 managed-service tests on exact head da966afa688779903e9b8a04b8913bf53890a7cd. That CI evidence does not exercise the complete Windows adversarial suite. Before final QA or merge, an authorized native Windows/MSVC host must still validate the adversarial ACL, retained-root enumeration, handle-relative no-replace rename, exact-handle deletion, root-swap, reparse-child, pathname-substitution, and pathname-successor scenarios.

Related issue

N/A — no public issue was opened because the underlying report is security-sensitive. No duplicate public issue or PR is cited.

Testing

Locally available macOS gates passed on the implementation snapshot:

  • Rust formatting and check
  • just tauri-check
  • just clippy
  • Focused recovery-store tests
  • Backend lifecycle tests

Two broader backend tests still fail because of known unrelated default-provider fixtures.

GitHub’s native Windows/MSVC CI compiled the implementation and passed 71 managed-service tests on exact head da966afa688779903e9b8a04b8913bf53890a7cd; all GitHub checks on that head passed. Full native Windows adversarial execution remains outstanding and merge-blocking as described above.

Generated with Goose

@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch 3 times, most recently from 9a4b378 to d5e7b6e Compare September 4, 2026 14:18
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 14:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are verified security/correctness issues in the Unix record publication/cleanup path (name substitution + unbound deletion) and a concrete portability build break on non-Linux/macOS Unix targets.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens Berd’s backend (Goose serve) lifecycle recovery by replacing path/PID-based recovery handling with a verified, bounded process-record store and process-identity-based signaling decisions across platforms (including special “fail closed” handling on macOS and hardened handle-relative operations on Windows).

Changes:

  • Introduces a new ProcessRecordStore that publishes and cleans up recovery records using owner-private, no-replace, successor-safe filesystem operations (Unix + Windows-specific implementations).
  • Switches Goose serve startup/shutdown and stale-process cleanup to use verified record reads, exact-object deletion, and identity probes before signaling/escalation.
  • Extends process identity plumbing on Unix (Linux + macOS) and updates shutdown flow to be asynchronous and bounded.
File summaries
File Description
src-tauri/src/services/process.rs Expands process identity support beyond Windows and adds Unix identity capture/probe helpers.
src-tauri/src/services/acp/process_record_store.rs Adds the verified, bounded, platform-specific recovery record store and its adversarial tests.
src-tauri/src/services/acp/mod.rs Wires the new process_record_store module into ACP services.
src-tauri/src/services/acp/goose_serve.rs Migrates Goose serve lifecycle + stale recovery to the new store and identity-based signaling/retention behavior.
src-tauri/src/lib.rs Updates app-exit teardown to await async singleton shutdown.
src-tauri/Cargo.toml Adds required windows-sys feature flags for the new Windows ACL / NT API usage.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src-tauri/src/services/acp/process_record_store.rs Outdated
Comment thread src-tauri/src/services/process.rs
Comment thread src-tauri/src/services/acp/goose_serve.rs
Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from d5e7b6e to b6d12ca Compare September 4, 2026 14:46
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 14:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It’s a high-sensitivity, platform-specific lifecycle/security change with outstanding native Windows adversarial verification, and it includes at least one correctness/robustness issue to address (stored PR comment).

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from b6d12ca to 11cf7ca Compare September 4, 2026 14:54
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 14:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Unix stale-process cleanup retains recovery records even when a follow-up identity probe could confirm the process is gone/mismatched after a SIGTERM/SIGKILL failure, which can leave behind stale records indefinitely.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

src-tauri/src/services/acp/goose_serve.rs:889

  • If SIGKILL fails, we unconditionally retain the record. When the failure is due to the process already being gone (or the PID having already moved to a mismatched identity), a follow-up identity probe would allow us to remove the exact verified record and avoid leaving stale recovery evidence indefinitely.
    if !kill(pid) {
        log::warn!(
            "SIGKILL failed for exact goose serve {}; keeping {}",
            identity.pid,
            path.display()
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/goose_serve.rs Outdated
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 11cf7ca to 3e40c33 Compare September 4, 2026 15:00
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

This is a high-sensitivity, cross-platform lifecycle/security change with at least one confirmed correctness issue in identity stability that can undermine orphan cleanup behavior.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src-tauri/src/services/process.rs
Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 3e40c33 to de5008e Compare September 4, 2026 15:07
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Windows implementation has a compile-time issue (STATUS_OBJECT_NAME_NOT_FOUND is referenced but not imported/defined), which must be fixed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from de5008e to 88bb792 Compare September 4, 2026 15:14
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It’s a high-sensitivity, platform-specific security hardening change with an explicit merge-blocking requirement for native Windows adversarial verification still outstanding.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs Outdated
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 88bb792 to da966af Compare September 4, 2026 15:22
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unix record publication can leave a hardlinked record in an undeletable/invalid state if temp-name unlink fails after a successful publish, breaking cleanup guarantees.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs Outdated
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from da966af to 2f36572 Compare September 4, 2026 15:32
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new process-record store currently has at least one confirmed correctness issue (MAX_RECORD_BYTES boundary) and one handle-safety issue (missing CLOEXEC on dup’d directory fd) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs Outdated
Comment thread src-tauri/src/services/acp/process_record_store.rs Outdated
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 2f36572 to 7d16be3 Compare September 4, 2026 15:42
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It is a high-sensitivity cross-platform security change and the PR description explicitly notes outstanding native Windows adversarial verification as merge-blocking.

Review details

Suppressed comments (7)

src-tauri/src/services/acp/goose_serve.rs:761

  • remove_verified() errors are ignored here; if exact deletion fails, the record will persist without any log signal. Logging the error will help diagnose recovery-record retention and potential directory pollution.
            let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:820

  • remove_verified() failures are silently ignored here; if exact deletion fails, stale or invalid records can accumulate without any diagnostic breadcrumb. Prefer logging the error (but still continuing) to keep startup recovery transparent.
        let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:825

  • This exact-record deletion is best-effort, but errors are dropped. If identity-bound deletion fails, logging helps explain why a record continues to reappear on subsequent startups.
            let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:857

  • When SIGTERM fails but a follow-up probe confirms Gone/Mismatch, the record cleanup still ignores remove_verified() errors. Please log failures so you can distinguish 'record intentionally retained' from 'cleanup failed'.
                let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:870

  • Exact cleanup is attempted here, but any remove_verified() error is discarded; that can silently leave behind a record even after a Gone/Mismatch probe. Logging failures would make this path diagnosable.
            let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:893

  • If SIGKILL fails but the follow-up probe confirms Gone/Mismatch, cleanup ignores any remove_verified() error. Please log deletion failures to avoid silently retaining records due to substitution/permission races.
                let _ = store.remove_verified(path, verified);

src-tauri/src/services/acp/goose_serve.rs:906

  • This final best-effort cleanup drops remove_verified() errors; if the record can't be deleted exactly, it will remain with no log. Logging the error keeps recovery-record retention explainable in the field.
            let _ = store.remove_verified(path, verified);
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/goose_serve.rs Outdated
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 7d16be3 to d063873 Compare September 4, 2026 15:52
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 15:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Security-sensitive, cross-platform process/FS hardening changes still need manual validation (including the stated native Windows adversarial verification) and there are correctness issues to address.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src-tauri/src/services/process.rs
Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from d063873 to 1f8c547 Compare September 4, 2026 17:00
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 17:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

High-sensitivity, cross-platform process/FS hardening with a confirmed Unix enumeration error-handling gap plus outstanding native Windows adversarial verification called out as merge-blocking in the PR description.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/process_record_store.rs
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 1f8c547 to 51a977a Compare September 4, 2026 18:54
@budzeg
budzeg requested a lite review from Copilot September 4, 2026 18:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces high-sensitivity, cross-platform process/FS security changes and still depends on outstanding native Windows adversarial verification before merge.

Review details
  • Files reviewed: 6/7 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src-tauri/src/services/acp/goose_serve.rs
Prevent stale identifiers and mutable record paths from authorizing process signals or cleanup of the wrong filesystem object.

Co-authored-by: Fuzzy <644e8093c651dbf16ecec80095552ed2e9180ec9e3de2f5f4f0d86ecfbe9d5f5@buzz.block.builderlab.xyz>

Signed-off-by: Olabode Olaoke <olabode@squareup.com>
@budzeg
budzeg force-pushed the budzeg/sec-007-process-records branch from 51a977a to 58e6413 Compare September 4, 2026 19:13
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.

2 participants