machine-bridge-mcp 2.0.0 → 3.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/CONTRIBUTING.md +20 -25
  3. package/README.md +21 -14
  4. package/SECURITY.md +147 -123
  5. package/browser-extension/manifest.json +3 -2
  6. package/browser-extension/service-worker.js +31 -12
  7. package/docs/ARCHITECTURE.md +27 -13
  8. package/docs/AUDIT.md +85 -2
  9. package/docs/CLIENTS.md +2 -2
  10. package/docs/ENGINEERING.md +9 -3
  11. package/docs/GETTING_STARTED.md +10 -9
  12. package/docs/LOCAL_AUTHORIZATION.md +115 -72
  13. package/docs/LOGGING.md +12 -3
  14. package/docs/MANAGED_JOBS.md +24 -29
  15. package/docs/MULTI_ACCOUNT.md +98 -37
  16. package/docs/OPERATIONS.md +33 -22
  17. package/docs/OVERVIEW.md +7 -7
  18. package/docs/PROJECT_STANDARDS.md +9 -5
  19. package/docs/RELEASING.md +171 -64
  20. package/docs/TESTING.md +19 -7
  21. package/docs/THREAT_MODEL.md +138 -67
  22. package/docs/TOOL_REFERENCE.md +2 -2
  23. package/docs/UPGRADING.md +102 -18
  24. package/native/macos/MachineBridgeTrustBroker.swift +233 -0
  25. package/package.json +36 -5
  26. package/scripts/candidate-runtime-store.mjs +38 -0
  27. package/scripts/check-plan.mjs +19 -0
  28. package/scripts/check-runner.mjs +4 -1
  29. package/scripts/commit-message-check.mjs +5 -2
  30. package/scripts/coverage-check.mjs +30 -2
  31. package/scripts/github-push.mjs +11 -0
  32. package/scripts/github-release.mjs +38 -7
  33. package/scripts/install-published-prerelease.mjs +167 -0
  34. package/scripts/local-release-acceptance.mjs +23 -12
  35. package/scripts/npm-publication-policy.mjs +16 -0
  36. package/scripts/prerelease-activation.mjs +79 -0
  37. package/scripts/privacy-check.mjs +7 -5
  38. package/scripts/promotion-digest.mjs +121 -0
  39. package/scripts/publish-npm.mjs +51 -0
  40. package/scripts/published-release.mjs +80 -0
  41. package/scripts/release-acceptance.mjs +30 -1
  42. package/scripts/release-candidate-manifest.mjs +40 -0
  43. package/scripts/release-channel.mjs +106 -0
  44. package/scripts/release-impact-check.mjs +12 -22
  45. package/scripts/release-soak.mjs +237 -0
  46. package/scripts/start-release-candidate.mjs +113 -7
  47. package/src/local/account-access.mjs +6 -0
  48. package/src/local/account-admin.mjs +34 -16
  49. package/src/local/agent-context.mjs +45 -42
  50. package/src/local/app-automation.mjs +9 -4
  51. package/src/local/authority-context.mjs +106 -0
  52. package/src/local/browser-bridge-http.mjs +4 -1
  53. package/src/local/browser-bridge.mjs +14 -9
  54. package/src/local/browser-broker-routes.mjs +4 -0
  55. package/src/local/browser-broker-server.mjs +5 -4
  56. package/src/local/browser-extension-identity.mjs +50 -0
  57. package/src/local/browser-extension-protocol.mjs +9 -4
  58. package/src/local/browser-operation-service.mjs +7 -0
  59. package/src/local/browser-pairing-http.mjs +36 -0
  60. package/src/local/browser-pairing-store.mjs +56 -47
  61. package/src/local/cli-account-admin.mjs +41 -7
  62. package/src/local/cli-activate.mjs +90 -0
  63. package/src/local/cli-approval.mjs +14 -58
  64. package/src/local/cli-local-admin.mjs +5 -15
  65. package/src/local/cli-options.mjs +11 -7
  66. package/src/local/cli-service.mjs +35 -5
  67. package/src/local/cli.mjs +112 -58
  68. package/src/local/daemon-process.mjs +6 -0
  69. package/src/local/delegated-process-sandbox.mjs +147 -0
  70. package/src/local/device-identity.mjs +157 -48
  71. package/src/local/device-root-provider.mjs +87 -0
  72. package/src/local/errors.mjs +25 -3
  73. package/src/local/git-service.mjs +16 -15
  74. package/src/local/job-runner.mjs +35 -27
  75. package/src/local/log.mjs +14 -1
  76. package/src/local/macos-trust-broker.mjs +320 -0
  77. package/src/local/managed-job-lock.mjs +18 -0
  78. package/src/local/managed-job-projection.mjs +9 -1
  79. package/src/local/managed-job-runner.mjs +13 -1
  80. package/src/local/managed-job-storage.mjs +2 -1
  81. package/src/local/managed-job-terminal.mjs +138 -0
  82. package/src/local/managed-jobs.mjs +88 -32
  83. package/src/local/operation-authorization.mjs +75 -239
  84. package/src/local/operation-risk.mjs +28 -0
  85. package/src/local/operation-state-lock.mjs +7 -86
  86. package/src/local/owner-state-lock.mjs +104 -0
  87. package/src/local/policy.mjs +19 -0
  88. package/src/local/process-execution.mjs +21 -9
  89. package/src/local/process-sessions.mjs +27 -17
  90. package/src/local/process-tracker.mjs +30 -6
  91. package/src/local/process-tree-ownership.mjs +59 -0
  92. package/src/local/process-tree.mjs +22 -18
  93. package/src/local/relay-connection.mjs +47 -35
  94. package/src/local/relay-diagnostics.mjs +65 -0
  95. package/src/local/remote-configuration.mjs +48 -0
  96. package/src/local/runtime-activation.mjs +141 -0
  97. package/src/local/runtime-diagnostics.mjs +21 -0
  98. package/src/local/runtime-relay.mjs +9 -8
  99. package/src/local/runtime-reporting.mjs +8 -3
  100. package/src/local/runtime-tool-handlers.mjs +8 -8
  101. package/src/local/runtime.mjs +73 -39
  102. package/src/local/secure-file.mjs +5 -1
  103. package/src/local/security-audit-log.mjs +204 -0
  104. package/src/local/service-convergence.mjs +17 -1
  105. package/src/local/service-ownership.mjs +17 -0
  106. package/src/local/service-restart-handoff.mjs +50 -0
  107. package/src/local/service-restart-scheduler.mjs +49 -0
  108. package/src/local/service-status.mjs +47 -0
  109. package/src/local/service.mjs +142 -43
  110. package/src/local/state-inventory.mjs +21 -3
  111. package/src/local/state.mjs +155 -17
  112. package/src/local/stdio.mjs +5 -0
  113. package/src/local/tool-executor.mjs +39 -6
  114. package/src/local/tool-result-boundary.mjs +51 -0
  115. package/src/local/tools.mjs +1 -0
  116. package/src/local/trusted-executable.mjs +53 -0
  117. package/src/local/trusted-git-executable.mjs +34 -0
  118. package/src/local/trusted-github-cli.mjs +24 -0
  119. package/src/local/windows-service.mjs +20 -0
  120. package/src/local/worker-deployment.mjs +3 -4
  121. package/src/local/worker-secret-file.mjs +2 -2
  122. package/src/local/workspace-file-service.mjs +34 -31
  123. package/src/shared/admin-auth.d.mts +2 -1
  124. package/src/shared/admin-auth.mjs +3 -3
  125. package/src/shared/device-session-auth.d.mts +20 -0
  126. package/src/shared/device-session-auth.mjs +51 -0
  127. package/src/shared/server-metadata.json +1 -1
  128. package/src/shared/tool-catalog.json +2 -2
  129. package/src/worker/account-admin.ts +23 -22
  130. package/src/worker/authority.ts +9 -2
  131. package/src/worker/daemon-auth.ts +45 -67
  132. package/src/worker/daemon-sockets.ts +12 -2
  133. package/src/worker/device-session-verifier.ts +129 -0
  134. package/src/worker/dpop.ts +151 -0
  135. package/src/worker/http.ts +47 -16
  136. package/src/worker/index.ts +53 -16
  137. package/src/worker/nonce-store.ts +1 -5
  138. package/src/worker/oauth-client-admin.ts +45 -0
  139. package/src/worker/oauth-controller.ts +55 -6
  140. package/src/worker/oauth-refresh-families.ts +21 -7
  141. package/src/worker/oauth-state.ts +6 -0
  142. package/src/worker/oauth-tokens.ts +28 -8
  143. package/src/worker/websocket-protocol.ts +8 -2
package/SECURITY.md CHANGED
@@ -6,230 +6,254 @@ Security fixes are applied to the latest released version. Upgrade before report
6
6
 
7
7
  ## Reporting a vulnerability
8
8
 
9
- Do not open a public issue for an undisclosed vulnerability. Use [GitHub private vulnerability reporting](https://github.com/YuLeiFuYun/machine-bridge-mcp/security/advisories/new) for this repository. Include:
9
+ Do not open a public issue for an undisclosed vulnerability. Use [GitHub private vulnerability reporting](https://github.com/YuLeiFuYun/machine-bridge-mcp/security/advisories/new). Include:
10
10
 
11
11
  - affected version and operating system;
12
12
  - remote or stdio transport;
13
- - selected profile and relevant flags;
13
+ - selected daemon policy and authenticated account role;
14
14
  - minimal reproduction;
15
15
  - expected and observed impact;
16
- - whether credentials, filesystem data, process authority, or network access were exposed.
16
+ - whether credentials, files, process authority, browser/application state, or network access were exposed.
17
17
 
18
- Do not include live account passwords, account-administration secrets, daemon secrets, OAuth tokens, Cloudflare credentials, private keys, or unrelated local files. Rotate credentials used in a reproduction.
18
+ Do not include live account passwords, OAuth tokens, Cloudflare credentials, private keys, browser material, or unrelated local files. Rotate any credential used in a reproduction.
19
19
 
20
20
  ## Repository and documentation privacy
21
21
 
22
- Tests, examples, documentation, release notes, and package metadata are publication surfaces. Use only synthetic hostnames, resource aliases, usernames, paths, and project names. Run `npm run privacy:check` before committing, review `npm run privacy:history` before publishing, and maintain private local identifiers in the ignored `.privacy-denylist`; neither scanner mode prints matched values. See [Repository privacy hygiene](docs/PRIVACY.md).
22
+ Tests, examples, documentation, release notes, and package metadata are publication surfaces. Use synthetic hostnames, aliases, usernames, paths, and project names.
23
23
 
24
- Removing a value from the current branch does not remove it from Git history, caches, forks, or an already published npm package. Rotate any exposed credential immediately and coordinate destructive history rewriting separately when its risk is justified.
24
+ Run:
25
25
 
26
- CodeQL and OpenSSF Scorecard are enforced as gates, not merely uploaded as advisory output. The shared SARIF gate rejects every security result and fails closed when a result omits the rule metadata needed to prove it non-security. Any exception requires an exact rule/path entry, a substantive rationale, and a non-expired review date; rule-wide suppression is not acceptable. CodeQL has one exact, expiring accepted result for the authorized non-shell direct-process boundary; its fixed option set and metacharacter behavior are tested. Scorecard exceptions are limited to documented governance or time-dependent conditions that repository code cannot truthfully repair, while remediable dependency-pinning and fuzzing findings remain release-blocking.
27
-
28
- ## Core trust model
26
+ ```sh
27
+ npm run privacy:check
28
+ npm run privacy:history
29
+ ```
29
30
 
30
- The concise security model is in [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md), including assets, attacker classes, explicit non-goals, and residual risks.
31
+ Maintain private local identifiers in the ignored `.privacy-denylist`. Removing a value from the current branch does not remove it from Git history, caches, forks, or published packages. Rotate exposed credentials immediately.
31
32
 
32
- Trusted components are:
33
+ CodeQL and OpenSSF Scorecard are release gates. Exceptions must be exact, justified, time-bounded, and independently visible; rule-wide suppression is not accepted.
33
34
 
34
- 1. the local OS user running the runtime;
35
- 2. the installed package/source checkout and its dependencies;
36
- 3. for remote mode, the user's Cloudflare account and deployed Worker;
37
- 4. an MCP client explicitly authorized through OAuth or launched locally through trusted stdio configuration.
35
+ ## Core trust model
38
36
 
39
- An authorized client can invoke every tool exposed by the selected profile and receive its results.
37
+ The detailed model is in [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md).
40
38
 
41
- The Worker is a remote authentication and relay boundary. The local runtime is the filesystem and process boundary. Stdio bypasses the Worker and relies on local process/configuration trust.
39
+ Trusted components are:
42
40
 
43
- ### Accounts are authorization boundaries, not OS sandboxes
41
+ 1. the local OS account running Machine Bridge;
42
+ 2. the installed package or source checkout and its dependencies;
43
+ 3. the user's Cloudflare account and deployed Worker in remote mode;
44
+ 4. the explicitly authorized MCP client;
45
+ 5. the selected browser profile and extension installation when browser automation is enabled.
44
46
 
45
- Remote mode supports named accounts with independent passwords, roles, active state, versions, OAuth authorization codes, access tokens, and rotating refresh tokens. The roles `reviewer`, `editor`, `operator`, and `owner` map to the local review, edit, agent, and full policy profiles. The Worker intersects the account role with the connected daemon policy, and the local runtime validates the account role again before dispatch. Account suspension, role changes, password rotation, and removal revoke only that account.
47
+ The Worker authenticates and filters remote requests. The local runtime owns filesystem, process, browser, application, resource, and job authority. Stdio bypasses the Worker and relies on local process and configuration trust.
46
48
 
47
- An OAuth `client_id` still identifies client software and redirect URIs; it is not an account. One account can authorize several clients, and one client can be authorized by several accounts.
49
+ ## Effective remote authority
48
50
 
49
- All accounts ultimately reach one daemon running as one OS user. Application roles cannot isolate direct processes, shells, browser sessions, Accessibility actions, credential stores, or network authority inherited from that user. Mutually untrusted users or hard tenant boundaries require separate bridge instances and external isolation: dedicated low-privilege OS accounts, containers, or VMs, narrow workspaces, independent state roots, and separate Workers. See [Multi-account authorization and tenancy](docs/MULTI_ACCOUNT.md).
51
+ Remote authority is an intersection:
50
52
 
51
- ## Profiles are capability sets, not sandboxes
53
+ ```text
54
+ daemon capability ceiling
55
+ ∩ account role
56
+ ∩ trusted OAuth client binding
57
+ ∩ account version and refresh-token family
58
+ ∩ object ownership
59
+ ```
52
60
 
53
- The default for newly selected workspaces is `full`, which prioritizes ease of use over least privilege. Named profiles are canonical capability contracts. A stored `full` label is repaired on load to the complete maximum-permission field set and tool catalog; a deliberate per-capability override is represented as `custom`, not as a partially restricted `full`.
61
+ The roles are:
54
62
 
55
- - `full` exposes all tools, unrestricted direct filesystem paths, absolute path output, shell execution, and the complete parent process environment.
56
- - `agent` exposes file mutation, direct argv execution, and process sessions while keeping direct filesystem tools workspace-confined and the process environment isolated.
57
- - `edit` exposes read and mutation tools without process execution.
58
- - `review` exposes read-only workspace/Git/image tools.
63
+ - `reviewer`: read-only selected-workspace access;
64
+ - `editor`: selected-workspace reads and deterministic file mutation;
65
+ - `operator`: workspace-confined mutation and direct process execution;
66
+ - `owner`: complete bridge authority within the daemon policy ceiling.
59
67
 
60
- `run_process` avoids shell parsing, which removes one injection class, but an executable such as `node`, `python`, a package manager, compiler, test runner, or repository script can execute arbitrary code. Direct mode therefore has effectively broad local-user authority once an attacker controls argv or executed code.
68
+ No approval ID, refresh token, reconnect, client registration, or legacy lease can expand a role. Out-of-role operations fail with `authorization_denied`.
61
69
 
62
- `exec_command` has both executable authority and shell expansion. Use `--no-exec` or `review`/`edit` when process execution is unnecessary.
70
+ The Worker filters the tool catalog, and the local runtime independently recomputes the role boundary before dispatch. Account disablement, role change, password rotation, account removal, client revocation, token-version rotation, and refresh-family replay invalidate the appropriate credentials.
63
71
 
64
- For untrusted repositories or instructions, run the bridge inside a disposable VM/container or under a dedicated low-privilege OS account. On macOS and Windows, this external isolation is especially important. The project does not claim an in-process OS sandbox, CPU quota, resident-memory quota, or network egress policy. `server_info.runtime.execution_guardrails.operating_system_enforcement` reports these gaps explicitly.
72
+ An OAuth client is bound to one account, account version, and role after successful authorization. It cannot silently switch accounts. Use `machine-mcp account clients` to inspect clients and `machine-mcp account revoke-client CLIENT_ID` to revoke one client and its credentials.
65
73
 
66
- ## Agent instructions, skills, and command manifests
74
+ ## Profiles are capability sets, not sandboxes
67
75
 
68
- Machine Bridge prepends a package-controlled built-in working-agreement block and an optional bounded automatic project-context block before repository/user instructions. The built-in block is guidance, not a security boundary. Automatic context reads only recognized root filenames, package-manager/lockfile facts, package script names, runtime constraints, common documentation names, and CI filenames; it does not inject script bodies, dependency values, source contents, or execute discovered commands. Symbolic-link, oversized, invalid-UTF-8, and unsupported metadata is skipped conservatively.
76
+ The default `full` profile prioritizes owner automation over least privilege.
69
77
 
70
- Repository and user instruction files remain untrusted content from the model's perspective. `agent_context` returns their text in deterministic precedence order but does not certify correctness or safety. A malicious `AGENTS.md`, custom instruction file, filename, script name, or `SKILL.md` can attempt prompt injection or recommend destructive operations. Use only trusted repositories and skill roots, keep host approvals/policy enabled, or isolate the bridge externally.
78
+ - `full` exposes all tools, unrestricted paths, absolute path output, shell execution, browser/application automation, managed jobs, and the complete parent environment.
79
+ - `agent` exposes workspace-confined mutation and direct process execution with an isolated environment.
80
+ - `edit` exposes reads and file mutation without process execution.
81
+ - `review` exposes read-only workspace, Git, and image tools.
71
82
 
72
- Automatic `package.*` commands expose only validated script names and fixed package-manager argv; they do not expose script bodies. Executing one still runs repository-controlled package-script code with local-user authority and is not a sandbox or trust upgrade.
83
+ A stored `full` label is canonical. Per-capability narrowing is represented as `custom`, not as a partially restricted `full`.
73
84
 
74
- Remote Worker-health and relay proxy selection honors `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. Only HTTP(S) proxy URLs are accepted. The local browser-broker health probe never uses those proxy variables: it accepts only canonical `127.0.0.1`, uses a direct bounded HTTP request, and rejects alternate hosts, credentials, query strings, and fragments. Autostart installation persists an allowlist of proxy and custom-CA environment values in `service-environment.json` so a background daemon can reproduce the foreground network route; a proxy URL may itself contain credentials, so this file is sensitive local state and must remain protected with the rest of the state root. Proxy endpoints, credentials, certificate paths, and authorization headers are not returned through MCP or written to operational logs; service status exposes only configured environment key names and relay status exposes only coarse route state.
85
+ `run_process` avoids shell parsing but an invoked interpreter, package manager, compiler, test runner, or repository script can execute arbitrary code. `exec_command` additionally enables shell expansion.
75
86
 
76
- Skill loading is non-executing. `load_local_skill` returns an entrypoint and bounded file inventory; scripts remain inert until a separate process or command tool is called. Symlinked skill directories are followed only after canonical path-policy validation, while symbolic-link `SKILL.md` entrypoints are rejected. Traversal, cycles, content, summaries, and inventory are bounded.
87
+ Owner execution is not OS-sandboxed by Machine Bridge. Use a dedicated low-privilege account, container, or VM for mutually untrusted workloads.
77
88
 
78
- Registered commands are available only under direct-execution-capable policy. They use argv spawning rather than shell parsing, reject undeclared caller arguments, and enforce the manifest timeout as a ceiling. They are not an approval or sandbox boundary: a repository-controlled package script, interpreter, compiler, or executable can still run arbitrary code with local-user authority. Deeper manifests can override or remove inherited commands, so callers must obtain context for the actual target path rather than assuming the repository-root registry applies everywhere.
89
+ ## Delegated process isolation
79
90
 
80
- The remote MCP host remains an independent boundary. Machine Bridge can advertise these tools, append `model_instructions_file` during initialization, and recommend capabilities through `resolve_task_capabilities`, but it cannot force a host to preserve instructions, expose tools, approve calls, or invoke them.
91
+ An `operator` process must pass a behaviorally verified OS-sandbox boundary. Restricting only cwd and environment is insufficient because an ordinary same-user process can otherwise read the user's home, Machine Bridge state, Keychain, and desktop session.
81
92
 
82
- The global `model_instructions_file` is an explicit user trust decision. It is read for every profile and sent to the authorized host during session initialization; do not place credentials, private records, or content inappropriate for every connected session in it. Project manifests cannot override this global file or the global `builtin_instructions`/`automatic_project_context` controls. Other global manifest fields that would widen local scope are ignored under workspace-confined profiles.
93
+ The sandbox probe must demonstrate that the selected workspace is usable while protected roots remain unreadable. If the platform cannot demonstrate the negative boundary, delegated process execution fails closed.
83
94
 
84
- ## Browser and application automation
95
+ The existence of `sandbox-exec`, a container binary, or another sandbox command is not treated as proof of isolation.
85
96
 
86
- Canonical `full` exposes structured browser and desktop UI authority. The browser extension operates the user's existing Chromium profile, including active login state, and has broad host access plus Chromium `debugger` permission so it can inspect arbitrary pages, fill complex forms, and issue trusted input. An authorized client may therefore read page content, click controls, submit forms, upload registered files, and cause transactions with the user's browser identity. macOS Accessibility actions similarly operate applications with the local user's UI authority.
97
+ ## Machine Bridge control plane
87
98
 
88
- The browser loopback broker validates loopback `Host`, requires a random owner-only bearer subprotocol, accepts extension sockets only from a canonical 32-character Chromium extension ID, requires the pairing page and WebSocket endpoint to use the same loopback port, and authenticates additional local runtimes separately. Initial extension pairing is trust-on-first-use; after pairing, a different localhost page cannot replace the stored broker unless the user clicks the extension action while the genuine pairing page is active. The pairing token is never returned by MCP or written to operational logs. These controls defend against casual cross-origin and DNS-rebinding access; they do not protect against malicious code already running as the same OS user or a compromised browser extension profile.
99
+ Generic path-based file, image, search, and patch tools cannot target Machine Bridge control-plane roots, including device-root metadata, account-management state, audit state, service metadata, locks, native broker artifacts, resources, and profile state. This denial also applies to `owner/full` and prevents accidental export through structured file APIs.
89
100
 
90
- Caller-supplied JavaScript, AppleScript, JXA source, and arbitrary DevTools methods are deliberately unsupported. Actions use fixed implementation code and structured selectors. The debugger adapter is restricted to fixed `Input` commands, attaches only around one trusted action, and detaches in `finally`. `auto` falls back only before any Input dispatch; after dispatch begins, failure is reported as an unknown outcome and is never replayed through DOM. The broker and extension require the current protocol-3 `hello`/`hello_ack` exchange plus exact packaged-version and capability equality before either reports readiness. Pairing material is persisted only after acknowledgement, and an invalid replacement candidate cannot displace the current connection or overwrite its stored endpoint/token. This removes an avoidable arbitrary-evaluation surface but does not make DOM or Accessibility actions safe. Pages can contain prompt injection, misleading labels, hidden consequences, cross-origin frames unavailable to inspection, or state that changes between inspection and submission. High-impact account, financial, legal, medical, publishing, deletion, and purchase actions require contextual review and any host/user confirmation the client provides.
101
+ It is not an OS sandbox. `owner/full` shell or interpreter execution runs with the daemon OS user's ambient authority and can access same-user files outside Machine Bridge's path resolver. Protect mutually untrusted owner clients with a separate low-privilege OS account, VM, or container; do not describe the path check as protection from arbitrary owner code execution.
91
102
 
92
- Text and file resources can be injected locally so their contents do not appear in MCP arguments or results. The destination page/application still receives the value, and remote tool metadata/results still traverse the Worker and host. Page source and screenshots can themselves contain secrets. Source/inspection budgets are aggregate across frames, page-controlled metadata is bounded, URL userinfo is removed from semantic snapshots, and contenteditable controls with secret-like identity are treated as sensitive; these limits reduce accidental exposure but do not classify every possible secret. Browser/app tool arguments, source, screenshots, field values, and results are intentionally omitted from operational logs.
103
+ ## Device identity and user presence
93
104
 
105
+ Remote daemon authentication uses a long-term device root and a root-certified ephemeral session.
94
106
 
95
- ## Shared authorization contract
107
+ The default provider on every platform, including macOS, is an owner-only portable P-256 root. Its private JWK is exportable by the daemon OS user and is reported as such in `server_info`. The root signs a 24-hour ephemeral session certificate at daemon startup; the ephemeral private key remains in memory and signs WebSocket preflight, Worker challenge, reconnect, and account-administration requests. Portable startup does not access Keychain and does not request user presence.
96
108
 
97
- Policy revision 5 is a single source of truth shared by the local daemon and Worker. The catalog availability class controls both advertisement and execution; manager-level checks invoke the same gate as defense in depth. Custom policies are evaluated by capabilities, so a label cannot impersonate `full`. Persistent job start requires both write and direct-execution authority; read-only job/resource inventory does not imply mutation authority.
109
+ macOS can opt into a non-exportable Secure Enclave root only through `MBM_MACOS_TRUST_BROKER`. The configured executable must be an app-like broker signed by an Apple development or distribution identity with provisioning-profile-validated data-protection Keychain entitlements. Machine Bridge validates its canonical path, file mutability, strict code signature, signing identifier, Team ID, protocol responses, and a real create/delete Secure Enclave key probe before enrollment. The broker identity remains bound to the root and is revalidated before later use.
98
110
 
99
- Transport-visible failures use stable error codes and retryability. Unexpected implementation errors are not downgraded to ordinary resource state, and raw internal exceptions are not returned by the Worker. This reduces both authorization drift and accidental disclosure through error strings.
111
+ The prompt frequency is therefore:
100
112
 
101
- ## Filesystem exposure
113
+ - ordinary tool calls: none;
114
+ - portable-root daemon startup: none;
115
+ - provisioned Secure Enclave daemon startup: one user-presence operation;
116
+ - relay reconnect: none;
117
+ - independent local account administration: none with a portable root, or one with a provisioned Secure Enclave root;
118
+ - device-root rotation: one explicit operation, plus user presence only when the provisioned broker requires it.
102
119
 
103
- Direct filesystem scope is profile-dependent. The default `full` profile is unrestricted. The `agent`, `edit`, and `review` profiles confine direct filesystem tools to the canonical selected workspace, including symbolic-link resolution.
120
+ The packaged Swift source and ad-hoc build are development/protocol fixtures. The production validator deliberately rejects them because ad-hoc code has no provisioning-profile-validated data-protection Keychain access group.
104
121
 
105
- The default `full` profile returns absolute paths. Narrower profiles return workspace-relative paths to reduce username and directory-layout disclosure. Path display and access scope remain separate controls.
122
+ The broker path, signing identifier, Team ID, and capability are revalidated before use, but those checks cannot distinguish a malicious replacement signed by the same trusted Apple team and identifier. Install production brokers in a root-owned or otherwise daemon-user-non-writable location and protect the signing identity and update channel.
106
123
 
107
- The server does not maintain a sensitive-filename blacklist. Under `full`, direct read tools may access any UTF-8 regular file available to the local OS user, including files outside the selected workspace and names such as `.env`, password stores, private keys, credentials, database dumps, and production configuration. Narrower profiles confine direct filesystem tools but do not classify names inside that boundary.
124
+ ## Account administration
108
125
 
109
- Maximum local policy does not bypass Unix permissions, Windows ACLs, macOS TCC/SIP, container/VM boundaries, endpoint-security controls, shell restrictions, or security decisions made by the MCP host/platform. `full` guarantees the complete local daemon and relay-advertised catalog, not the set a connector host chooses to expose to one session. The server cannot observe that host-side subset. A host-side refusal is independent of Machine Bridge and cannot be disabled by local policy configuration. `diagnose_runtime` and `machine-mcp doctor` use fixed probes to distinguish requests that reached the daemon from local filesystem/process/shell failures; they cannot inspect a call blocked before delivery.
126
+ Version 3 has no long-lived `ACCOUNT_ADMIN_SECRET`. Account and OAuth-client administration uses P-256 requests signed by the root-certified ephemeral session. The signature binds:
110
127
 
111
- Processes are not confined by the filesystem-tool resolver. They can access paths, networks, processes, credential stores, and devices available to the local user.
128
+ - Worker origin;
129
+ - HTTP method and path;
130
+ - request-body hash;
131
+ - ephemeral key ID;
132
+ - timestamp;
133
+ - random nonce.
112
134
 
113
- ## Full-profile verification
135
+ The Worker verifies the root certificate, session signature, bounded timestamp, body hash, and nonce replay state. Nonce capacity fails closed instead of evicting live replay markers.
114
136
 
115
- `machine-mcp full-test` performs real local operations inside disposable temporary directories: unrestricted file access, direct and shell processes, inherited environment, SSH key generation/matching, a sandbox `authorized_keys` write, SSH client parsing, Google Cloud OS Login command discovery, a non-mutating sudo availability probe, and detached job cleanup. It makes no cloud or remote-server change and cannot prove that an MCP host will deliver a future request. The command verifies the Machine Bridge and local-machine portion of the authority chain only.
137
+ Account passwords are generated 256-bit tokens. The Worker stores independent salted verifiers, not plaintext passwords. A generated password is printed once by the command that creates or rotates it.
116
138
 
117
- A canonical `full` profile guarantees that Machine Bridge itself will not reject a catalogued tool because of its local profile, path scope, environment mode, or shell mode. It cannot override the MCP host/connector, operating-system access controls, endpoint-security policy, remote authentication, cloud IAM, `sudo`, or service-side authorization.
139
+ ## OAuth and DPoP
118
140
 
119
- ## Mutation integrity
141
+ Remote mode uses authorization code flow with PKCE S256, exact redirect and resource binding, bounded dynamic client registration, short-lived access tokens, one-time rotating refresh tokens, family lifetime limits, and replay-family revocation.
120
142
 
121
- Writes are bounded, reject symbolic-link/non-regular destinations, use same-directory staging, flush staged data, and commit atomically per file. Sensitive reads and mode changes use shared descriptor-first primitives: regular files are opened with no-follow where supported, validated, bounded before allocation, and permissioned through the descriptor; POSIX owner-only directories are opened with no-follow plus directory-only flags, `fchmod`ed to `0700`, and revalidated before use. Windows retains ACL semantics without pretending POSIX modes are enforceable. Create-only and lock claims fully write a private temporary file before a same-directory hard-link claim becomes visible; a concurrent destination fails without exposing partial content. Replacement writes use `fsync` plus atomic rename/replacement. Expected hashes and exact edits reduce accidental stale overwrites. Requested file modes are applied exactly on POSIX before commit; a mode-setting failure rolls the transaction back rather than silently publishing a semantically incomplete file.
143
+ Codes and tokens bind to client ID, account ID, account version, role, scope, resource, deployment token version, and refresh family.
122
144
 
123
- Startup, daemon, managed-job transition, recovery, and runner claims record ownership tokens and process start time. Reclamation validates process identity and a file snapshot before removal, limiting PID-reuse and stale-owner races. Recent malformed claims are not deleted immediately. Ordinary startup/state changes wait a bounded interval for a concurrent operation instead of turning a brief service-manager race into an operator error.
145
+ Supported clients may use DPoP ES256. The Worker verifies proof method, target URL, timestamp, unique identifier, public-key thumbprint, access-token hash, and supported JWS header semantics. Verification alone does not consume global replay capacity: the Worker stores the `jti` replay marker only after the access token or OAuth grant, client, account, and resource are valid. A copied DPoP-bound token is insufficient without the client private key.
124
146
 
125
- Patch operations prevalidate all paths/content, reject canonical collisions, recheck source hashes and destination absence, serialize bridge mutations, maintain backups, and roll back on ordinary commit errors. Existing reads and writes use canonical containment checks and final-component no-follow opens where the platform supports `O_NOFOLLOW`. On platforms without portable descriptor-relative `openat` traversal, a malicious process running as the same local account can still race a parent-directory replacement between validation and open/commit. These controls do not claim protection against a hostile same-user namespace, nor do they make a multi-directory patch power-loss atomic.
147
+ Bearer remains available for MCP hosts without DPoP. Bearer possession is therefore a residual risk until token expiry or revocation.
126
148
 
127
- A custom state root is rejected if it overlaps the selected workspace in either direction. Recursive state removal cross-checks the marker, global selection, profile state, daemon locks, active/unreadable locks, known directory shape, package/source/workspace exclusions, service removal, and managed-job state. Any unresolved condition fails closed and retains state.
149
+ Authorization pages display the validated client name and redirect URI. Enter an account password only after initiating the connection and recognizing both values.
128
150
 
129
- ## Credential exposure
151
+ Public health and discovery endpoints do not expose workspace, daemon, account, or tool state.
130
152
 
131
- Local state contains the account-administration secret, daemon secret, and deployment-wide token version. Account passwords are generated 256-bit tokens and are not stored locally; the Worker stores only independent salted HMAC-SHA-256 verifiers. The fixed high-entropy token format is mandatory, so the verifier does not rely on a CPU-intensive human-password KDF inside the Worker request budget. State, lock, temporary secret, runtime, pairing, and service-log files use owner-only permissions where supported. Worker deployment secrets are written only to an exclusive `0600` file whose name binds PID and process-start identity; stale cleanup removes only positively reclaimable owners, verifies file identity, retains ambiguous live owners, and reports cleanup failure. State writes are flushed and atomically replaced. A read/type/permission/size/symbolic-link failure is not treated as empty or corrupt state; only successfully read invalid JSON is moved to a bounded corrupt backup. The same rule applies to recursive state-root removal: unreadable or malformed config, profile state, or daemon ownership records block deletion.
153
+ ## Agent instructions, skills, and registered commands
132
154
 
133
- Logs recursively redact known credential fields, private-key headers, npm/GitHub/GitLab/Slack/Google/AWS/live-payment/API token forms, JWT-shaped bearer values, embedded-credential URLs, email addresses, user-home paths, and control characters. These patterns are defense in depth; unknown, transformed, split, encrypted, or application-specific secret forms can still pass through an explicitly requested tool result.
155
+ Built-in working agreements and bounded project facts are guidance, not a security boundary. Repository instructions, custom instruction files, script names, and skills are untrusted content and may attempt prompt injection.
134
156
 
135
- A new deployment prints the generated initial owner password once. Account creation and targeted password rotation also print the generated password once. JSON output includes a generated password only for the command that created it; status, diagnostics, and secret rotation never reveal stored secrets. The account-administration and daemon secrets are never printed. Avoid shared terminal logs, shell recordings, screenshots, CI output, or support tickets.
157
+ Automatic project context does not inject package-script bodies, dependency values, source contents, or execute discovered commands. Skill loading inventories bounded text; scripts remain inert until a separate execution tool is invoked.
136
158
 
137
- The default `full` profile passes the complete parent environment. Narrower profiles replace HOME, temp, and common cache paths and do not pass arbitrary parent variables. The isolated mode reduces accidental environment-secret leakage; it does not prevent code from explicitly accessing known resources.
159
+ Registered commands use fixed argv execution, reject undeclared arguments, and enforce configured timeouts. They are not a trust upgrade: a repository-controlled script or executable can still run arbitrary code within the caller's effective authority.
138
160
 
139
- ## Local resources and managed jobs
161
+ ## Browser and application automation
140
162
 
141
- Local resources are registered through the operator-controlled CLI or, only under canonical `full`, through `generate_ssh_key_resource`. State stores canonical paths, bounded registration-time aliases used only for redaction, and metadata—not file contents. Public status and resource results omit those aliases. The SSH generator creates or reuses an unencrypted automation key, verifies that the public and private files match, rejects symbolic links/incomplete pairs, applies `0600`/`0644` modes where supported, and returns no private bytes. Resource CLI output and `generate_ssh_key_resource` omit local paths by default; path disclosure requires `--show-paths` or `expose_paths=true`. Unix-like registration rejects group/other-readable private resource files unless explicitly overridden. Portable mode checks do not fully describe Windows ACLs or extended Unix ACLs; the operator remains responsible for platform permissions.
163
+ Only `owner` may control the existing browser profile, desktop applications, or export local data into them.
142
164
 
143
- At job acceptance, referenced resources are bounded and hashed. The detached runner reopens and verifies each hash before copying it to a private `0600` runtime file. Resource copies are removed after the finally phase. A changed or unavailable resource fails closed.
165
+ The browser broker:
144
166
 
145
- Resource injection modes have different exposure:
167
+ - listens only on canonical loopback;
168
+ - validates `Host` and extension origin;
169
+ - uses owner-only pairing material;
170
+ - requires protocol, package version, and capability equality;
171
+ - does not let an invalid replacement displace a healthy connection;
172
+ - restricts DevTools use to fixed input commands;
173
+ - does not accept caller-supplied JavaScript, AppleScript, JXA, or arbitrary DevTools methods.
146
174
 
147
- - private file-path substitution is generally preferred;
148
- - stdin avoids process arguments and environment variables;
149
- - environment injection can be visible to same-user process inspection and inherited child processes.
175
+ These controls do not make web content trustworthy. Pages may contain prompt injection, deceptive labels, hidden consequences, changing UI state, inaccessible cross-origin frames, or high-value authenticated sessions. Machine Bridge cannot prove the extension is loaded in an isolated profile.
150
176
 
151
- Managed jobs accept arbitrary argv and therefore retain local-user authority. They are a durability mechanism, not a sandbox or an authorization bypass. A running job snapshots execution authority and environment mode at acceptance. Later profile changes affect new jobs but do not silently revoke an accepted running job; explicitly cancel active jobs when revoking authority. The initial job submission remains subject to MCP-host approval and platform safety policy; each child remains subject to local OS and endpoint-security policy.
177
+ After trusted input dispatch begins, an ambiguous failure is reported as unknown outcome and is not automatically replayed.
152
178
 
153
- `stage_job` is non-executing and requires write capability. Local `machine-mcp job approve` is a separate operator authorization and may launch a staged plan even when the MCP profile itself has no execution capability. Operators must review the stored plan before approval. Cancelling before approval runs neither main nor finally steps.
179
+ Local resources may be injected without returning their bytes through MCP, but the destination page or application still receives them. Screenshots and page source can themselves contain secrets.
154
180
 
155
- Active plans are owner-only and may temporarily contain argv, non-secret stdin, temporary helper content, environment overrides, and resource source paths for crash recovery. A terminal runner deletes the full plan. Status and bounded results remain for up to seven days/50 jobs. If a runner crashes before terminal commit, the plan remains until recovery or retention cleanup.
181
+ ## Filesystem and mutation integrity
156
182
 
157
- Exact canonical and registration-time resource path aliases, exact resource bytes interpreted as text, and bounded exact base64/hex forms are redacted from retained output. This cannot detect partial, transformed, encrypted, compressed, or application-specific encodings. It also cannot redact unrelated secrets inherited through the full parent environment. Use `capture_output: "discard"` whenever a process may echo credentials, and never place a secret directly in argv, ordinary env, stdin, temporary-file content, or a JSON plan.
183
+ Workspace-confined profiles canonicalize existing paths and write ancestors. Final symbolic-link writes are rejected. Patch add, update, delete, and move destinations are classified before mutation.
158
184
 
159
- `finally_steps` run after ordinary success, failure, timeout, and cancellation. Cancellation uses an owner-only marker rather than signaling the runner process itself, so the coordinator remains alive to execute cleanup consistently across platforms. Timeout/cancellation target the process group/tree through one shared supervisor and keep a forced-termination escalation alive even if the direct child exits before a resistant descendant. Verified service-daemon stop uses the same graceful-then-force principle but revalidates the complete process identity immediately before escalation. Runner identity includes process start time; recovery does not trust a reused PID. A dead runner is detected on the next daemon or local job-CLI start; stale private resource copies are removed and cleanup is retried. This is best effort. Power loss, disk failure, permanent loss of credentials/network access, SIGKILL without later recovery, or security software denying the cleanup executable can prevent cleanup. Finally steps must be idempotent and safe to repeat. Automatic recovery is capped at three attempts so persistent endpoint-security or executable-policy denial cannot create an endless launch loop. Uninstall refuses to remove local state while managed jobs are active; operators must inspect or cancel them first.
185
+ Writes use bounded same-directory staging and atomic replacement. Expected hashes and exact edits reduce stale overwrites. Patch transactions prevalidate all operations, serialize mutation, maintain backups, and roll back ordinary commit errors.
160
186
 
161
- Job-scoped `temporary_files` should be used instead of loose helper scripts. They are materialized only below the private job runtime. Remote scripts should preferably be sent through a process stdin instead of written to the remote filesystem.
187
+ On systems without descriptor-relative traversal, a malicious same-user process can still race parent-directory replacement between validation and open. Machine Bridge does not claim protection from a hostile process with equivalent OS-user authority.
162
188
 
163
- Runner diagnostic logs are owner-only and do not receive child stdout/stderr. Existing runner logs are tail-trimmed before launch; only an absent file is ignored, while permission, type, symbolic-link, read, truncate, or write failures block launch instead of allowing unbounded append. Step output is stored only in bounded job results according to the selected capture mode.
189
+ Sensitive and persistence targets are owner-only. Generic remote file tools cannot access Machine Bridge's own control-plane state.
164
190
 
165
- ## OAuth and public endpoints
191
+ ## Processes and sessions
166
192
 
167
- Remote mode uses authorization code flow with PKCE S256, exact redirect/resource/client binding, protected-resource and authorization-server discovery, bounded dynamic client registration, `offline_access`, expiring authorization codes, access tokens, and refresh tokens, hashed bearer-token storage, per-account version checks, and deployment-wide token-version revocation. Authorization codes and both token classes are bound to one client ID, account ID, account version, role, scope, and resource. Public-client refresh tokens are single-use: a successful refresh atomically stores a new access/refresh pair and removes the presented refresh token; replay and account/version invalidation return RFC 6749 `invalid_grant`. Successful consent constructs the registered callback through the URL API and returns `303 See Other`; response parameters are encoded rather than concatenated into an unchecked header string.
193
+ Direct processes use argv without shell parsing. Shell expansion is available only through the explicit shell tool.
168
194
 
169
- The authorization page displays the validated client name and redirect URI. Enter an account name and password only after initiating the connection and recognizing both values.
195
+ Process counts, stdin, output, timeouts, retained sessions, and tool-call concurrency are bounded. Timeout, cancellation, disconnect, daemon replacement, and shutdown use process-tree termination with bounded graceful and forced phases.
170
196
 
171
- Password failures and pending, not-yet-authorized client registrations are limited by deployment-keyed HMAC source identity; successfully authorized DCR clients no longer consume that pending-registration quota, while the global client cap remains authoritative. Browser requests are same-origin unless an exact origin is listed in `MBM_ALLOWED_ORIGINS`; loopback OAuth redirect permission does not grant browser-origin access.
197
+ Interactive process sessions die with runtime disconnect or replacement. Retained output sessions and process control are bound to account, account version, OAuth client, and refresh family.
172
198
 
173
- Public health and metadata do not expose live workspace or daemon status. The daemon handshake omits workspace path/name/hash and process ID.
199
+ The daemon does not enforce universal CPU, memory, disk, or network quotas. An authorized owner process can still exhaust host or external resources.
174
200
 
175
- ## Relay and denial of service
201
+ ## Local resources and managed jobs
176
202
 
177
- Only one authenticated daemon is active. Candidates have a handshake deadline and cannot displace the current daemon before success. Authenticated sockets also carry a liveness deadline based on inbound traffic so half-open transports cannot remain the active daemon indefinitely. Pending calls are socket-bound, client-request-bound, concurrency-limited, size-limited, and timed out. Duplicate in-flight request IDs are rejected only within the same authenticated MCP session. Initialization returns a stateless HMAC-bound `MCP-Session-Id`; the signature binds the session nonce to the OAuth token identity, so one account can use multiple concurrent chat windows without sharing a cancellation or request-id namespace. Independent sessionless POST requests are not indexed by token and request id. A session id is an integrity/correlation token, not a second authorization credential.
203
+ Registered resources store canonical paths and bounded metadata, not file contents. Private resource files require restrictive permissions on Unix-like systems unless explicitly overridden.
178
204
 
179
- Request bodies, WebSocket messages, tool outputs, traversals, sessions, stdin writes, OAuth records, clients, codes, access tokens, refresh tokens, and failure identities are bounded. Disconnect/replacement terminates active child process trees.
205
+ At job acceptance, referenced resources are reopened, bounded, hashed, and copied into a private runtime area. Changed or unavailable resources fail closed. Environment injection may be visible to same-user process inspection; private file-path substitution or stdin is generally safer.
180
206
 
181
- These controls reduce accidental exhaustion and simple abuse. They do not replace Cloudflare account MFA, WAF/rate limits, usage alerts, or cost controls for an internet-facing Worker.
207
+ Managed jobs are durability, not sandboxing. Only `owner` may create remote persistent plans. Long-lived jobs bind to account, account version, OAuth client, and refresh family.
182
208
 
183
- ## Process sessions
209
+ `stage_job` is non-executing and cannot be promoted by a terminal approval command. `machine-mcp job approve` was removed. Execution requires trusted `start_job` authority or an explicit local `machine-mcp job submit PLAN.json` action.
184
210
 
185
- Process-session IDs are random and valid only inside one runtime. Output buffers and session counts are bounded. Sessions are killed on runtime stop or remote connection loss/replacement and expire from retained state after exit.
211
+ Job output and state are bounded. `finally_steps` are best effort and must be idempotent because recovery may repeat them. Power loss, disk failure, revoked external credentials, or endpoint-security denial can prevent cleanup.
186
212
 
187
- Sessions use pipes, not a PTY. Do not assume terminal-oriented programs will behave safely or correctly. Process output may contain secrets; it is returned to the authorized client but is not intentionally written to operational logs.
213
+ Use `capture_output: "discard"` whenever a process may echo credentials. Never put a secret directly in argv or ordinary JSON plan fields.
188
214
 
189
- Process sessions are interactive and intentionally die with runtime disconnect/replacement. Managed jobs are separate detached processes with owner-only persistent state and best-effort finally/recovery semantics.
215
+ ## State, locks, and rotation
190
216
 
191
- ## Images and rich content
217
+ State roots must be separate from workspaces. State and lock files are owner-only where supported, bounded, schema-validated, and atomically replaced. Process locks bind owner tokens to PID and process start time. Ambiguous or unreadable ownership fails closed.
192
218
 
193
- `view_image` accepts only signature-validated PNG, JPEG, GIF, and WebP under the size cap. SVG is intentionally excluded because it is active document content rather than a simple raster image. Image bytes pass through the Worker in remote mode and are visible to the authorized MCP client.
219
+ Device-root migration is two-phase: a pending public root is deployed and health-verified before local promotion. `--daemon-only` refuses to activate an undeployed pending root.
194
220
 
195
- ## Logs and privacy
221
+ Destructive state removal validates marker files, selected workspace, known layout, lock ownership, service state, and managed-job activity. Unresolved conditions retain state.
196
222
 
197
- Default operational logs record startup/deployment, relay, protocol, service, and infrastructure transitions. Every ordinary per-tool event—start, success, failure, cancellation, and duration—is debug-only. Tool arguments, command text, stdin, file/patch contents, and outputs are omitted. Messages and fields are bounded; unexpected daemon and Worker infrastructure exceptions are reduced to error classes. Static operator guidance uses sanitized plain output; raw plain output is reserved for explicitly requested credentials or local paths. Git author email is omitted from `git_log` unless explicitly requested.
223
+ ## Relay and denial of service
198
224
 
199
- No logging policy can prevent data from being returned to a client that explicitly invokes an enabled tool. The Worker necessarily relays remote tool arguments and results; this is not end-to-end encryption against the user's Cloudflare execution environment. Managed-job result files may contain remote command output and are owner-only local data, not operational logs.
225
+ Only one verified daemon is active. Candidates have preflight, hello, readiness, and liveness deadlines. A candidate cannot displace the current daemon before authentication and end-to-end readiness.
200
226
 
201
- ## Hardening checklist
227
+ Pending calls are bounded, socket-bound, request-bound, timed out, cancellable, and recoverable only for the same verified daemon instance during the documented reconnect grace period.
202
228
 
203
- For sensitive review:
229
+ Request bodies, messages, traversals, files, output, OAuth stores, nonce stores, sessions, and failure identities are bounded. These controls do not replace Cloudflare MFA, WAF/rate limits, billing alerts, or external cost controls.
204
230
 
205
- ```sh
206
- machine-mcp --workspace /narrow/project --profile review
207
- ```
231
+ ## Logs, audit, and privacy
208
232
 
209
- For controlled editing without execution:
233
+ Operational logs omit tool arguments, command text, stdin, file/patch contents, form values, and outputs. Known credential forms, private-key material, embedded-credential URLs, user-home paths, email addresses, and control characters are recursively redacted as defense in depth.
210
234
 
211
- ```sh
212
- machine-mcp --workspace /narrow/project --profile edit
213
- ```
235
+ The local security audit is a bounded SHA-256 hash chain. It records operation type, risk category, outcome, duration, byte counts, target digest, and salted principal references. It does not record commands, paths, contents, fields, or results.
214
236
 
215
- Also:
237
+ No logging policy prevents data from being returned to an authorized client that explicitly invokes an enabled tool. Remote arguments and results necessarily traverse the user's Worker and MCP host.
216
238
 
217
- - patch the OS and use the repository-pinned Node.js 26/npm 12 baseline;
218
- - enable MFA on Cloudflare, GitHub, and npm accounts;
219
- - do not configure broad CORS origins;
220
- - keep the state root completely separate from every workspace; never point `--state-dir` at a project directory or one of its ancestors;
221
- - treat an unreadable or malformed live lock as an incident to inspect, not a file to delete blindly;
222
- - select `agent`, `edit`, or `review` instead of the default `full` when broad authority is unnecessary;
223
- - inspect client names and OAuth redirect URIs;
224
- - rotate one account password after a targeted disclosure, or rotate deployment secrets after a bridge-wide incident;
225
- - inspect `status`, `doctor`, and service status;
226
- - register credential files as local resources instead of reading them into a model conversation;
227
- - use `capture_output: "discard"` for credential-consuming steps and idempotent finally steps for cleanup;
228
- - remove the Worker and state when remote access is no longer needed;
229
- - use external OS isolation for untrusted code.
239
+ ## Hardening checklist
230
240
 
231
- The full cross-cutting review and residual limitations are recorded in [docs/AUDIT.md](docs/AUDIT.md).
241
+ - Use `review` or `edit` when execution is unnecessary.
242
+ - Use a dedicated OS account, container, or VM for untrusted repositories, prompts, or clients.
243
+ - Enable MFA for Cloudflare, GitHub, npm, and Apple developer accounts.
244
+ - Keep the state root separate from every workspace.
245
+ - Inspect OAuth client names and redirect URIs.
246
+ - Inspect trusted clients and revoke stale records.
247
+ - Prefer DPoP-capable clients where available.
248
+ - Use the portable root unless a separately provisioned macOS trust broker has been installed and validated; never point `MBM_MACOS_TRUST_BROKER` at an ad-hoc or mutable executable.
249
+ - Register credentials as local resources instead of reading them into a model conversation.
250
+ - Use discard capture for credential-consuming jobs and idempotent finally steps.
251
+ - Inspect `status`, `doctor`, `server_info`, service state, delegated-sandbox status, and audit-chain health.
252
+ - Rotate an account password after targeted disclosure; revoke a client after client compromise; rotate the device root and global token version after bridge-wide compromise.
253
+ - Remove the Worker and local state when remote access is no longer required.
232
254
 
233
255
  ## Out of scope
234
256
 
235
- The project cannot prevent an authorized client from requesting data accessible to enabled tools, make arbitrary local executables safe, identify all sensitive content, guarantee cleanup across every power/storage/security failure, override MCP-host or endpoint-security policy, or neutralize model prompt injection. Operator approval, local resource hygiene, idempotent cleanup, and narrow capability selection remain primary controls.
257
+ Machine Bridge cannot make arbitrary local executables safe, identify all sensitive data, guarantee cleanup across every power/storage/security failure, override MCP-host or endpoint-security policy, neutralize prompt injection, protect against root or a fully compromised same-user account, or manufacture production signing and governance controls.
258
+
259
+ See [docs/AUDIT.md](docs/AUDIT.md) for historical findings and residual limitations.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Machine Bridge Browser",
4
- "version": "2.0.0",
4
+ "version": "3.0.0",
5
5
  "description": "Connects the current Chromium browser profile to the local Machine Bridge runtime for user-authorized automation.",
6
6
  "permissions": [
7
7
  "tabs",
@@ -30,5 +30,6 @@
30
30
  "action": {
31
31
  "default_title": "Machine Bridge Browser"
32
32
  },
33
- "version_name": "2.0.0"
33
+ "version_name": "3.0.0-beta.9",
34
+ "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxryYkpZhq8+VAQLHcGS9BAHQcyKX8RHGIpIwvtIVRU/rcOcE0bNdnM0aZJ/h6xWQsGDHlhvjT2+1aJaAn/9k8473BRWajzVXld961CdHYVFVHoce2hHiSJ0xydWrHMMZhAm0mN0UzjEpgZ0tMw209efcZHIvSwuxhteZMRy4kyiVjwFlOf5oXFCxRuCJnPj3AK9CmCf4XgEBuPIJ0TZmjGHOOdBvJmbCNnAWXYEo5/mf7MfCGhV4IJ1hNuhpoNQfOFKMUcw9/v/IpT62XpfXdGYTfGYCmCjC+gntK1spbkr2P4/2+sYMQtLpse71mpSNGXfcf3abU55Vpn+gncSxRQIDAQAB"
34
35
  }