From 84cc80b99b9570e332f86bd1f99bf56a7359a33a Mon Sep 17 00:00:00 2001 From: dzeusking-dev Date: Fri, 4 Sep 2026 15:36:12 +0200 Subject: [PATCH 1/2] chore: add OpenSSF trust baseline --- .bestpractices.json | 32 +++ .github/workflows/scorecard.yml | 42 ++++ GOVERNANCE.md | 5 + MAINTAINERS.md | 7 + README.md | 348 ++++++++++++++++---------------- docs/SECURITY-TRUST.md | 11 + security-insights.yml | 64 ++++++ 7 files changed, 336 insertions(+), 173 deletions(-) create mode 100644 .bestpractices.json create mode 100644 .github/workflows/scorecard.yml create mode 100644 GOVERNANCE.md create mode 100644 MAINTAINERS.md create mode 100644 docs/SECURITY-TRUST.md create mode 100644 security-insights.yml diff --git a/.bestpractices.json b/.bestpractices.json new file mode 100644 index 0000000..23c8fa9 --- /dev/null +++ b/.bestpractices.json @@ -0,0 +1,32 @@ +{ + "osps_do_01_01": "Met", + "osps_do_01_01_justification": "Install, configuration and tool usage are documented in README.md and docs/.", + "osps_do_02_01": "Met", + "osps_do_02_01_justification": "Defects use public issues under the process in SUPPORT.md.", + "osps_gv_02_01": "Met", + "osps_gv_02_01_justification": "Public issues and pull requests are enabled.", + "osps_gv_03_01": "Met", + "osps_gv_03_01_justification": "See https://github.com/gexiro-global/pc-filebridge/blob/main/CONTRIBUTING.md", + "osps_le_02_01": "Met", + "osps_le_02_01_justification": "Apache-2.0 source license.", + "osps_le_02_02": "Met", + "osps_le_02_02_justification": "Release artifacts include the Apache-2.0 license.", + "osps_le_03_01": "Met", + "osps_le_03_01_justification": "See https://github.com/gexiro-global/pc-filebridge/blob/main/LICENSE", + "osps_le_03_02": "Met", + "osps_le_03_02_justification": "The license is included in release source and runtime packages.", + "osps_qa_01_01": "Met", + "osps_qa_01_01_justification": "Canonical public source: https://github.com/gexiro-global/pc-filebridge", + "osps_qa_01_02": "Met", + "osps_qa_01_02_justification": "GitHub publishes the repository commit history.", + "osps_qa_02_01": "Met", + "osps_qa_02_01_justification": "Direct dependencies are declared in package.json and package-lock.json.", + "osps_qa_04_01": "N/A", + "osps_qa_04_01_justification": "PC FileBridge is a single-repository project.", + "osps_qa_05_01": "Met", + "osps_qa_05_01_justification": "Generated executables and packages are built in CI and not committed.", + "osps_qa_05_02": "Met", + "osps_qa_05_02_justification": "The repository contains source and reviewable configuration, not executable binaries.", + "osps_vm_02_01": "Met", + "osps_vm_02_01_justification": "See https://github.com/gexiro-global/pc-filebridge/blob/main/SECURITY.md" +} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..503cb99 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,42 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + schedule: + - cron: "49 5 * * 3" + push: + branches: [main] + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + security-events: write + id-token: write + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Run OpenSSF Scorecard + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + - name: Preserve SARIF result + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: openssf-scorecard-sarif + path: results.sarif + retention-days: 5 + if-no-files-found: error + - name: Upload SARIF to code scanning + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: results.sarif diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..d5f96ac --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,5 @@ +# Governance + +PC FileBridge is maintained by Gexiro Global Enterprises Ltd. The maintainer reviews issues and pull requests, decides scope and releases, and may reject changes that weaken create-only filesystem semantics, root confinement, identity checks, bounded operations or secret handling. + +Changes are proposed through GitHub pull requests and must pass CI. The current single-maintainer structure is disclosed in [MAINTAINERS.md](MAINTAINERS.md); no independent review, response-time guarantee or certification is claimed. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..ba56d32 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,7 @@ +# Maintainers + +| Maintainer | Role | Contact | +|---|---|---| +| `@dzeusking-dev` | Project owner and release maintainer | [GitHub](https://github.com/dzeusking-dev) | + +Security reports must use [SECURITY.md](SECURITY.md), not public issues. diff --git a/README.md b/README.md index e1259c7..6b6f35e 100644 --- a/README.md +++ b/README.md @@ -1,175 +1,177 @@ -# PC FileBridge - -[![CI](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml) -[![CodeQL](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml) +# PC FileBridge + +[![CI](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml) +[![CodeQL](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml) [![Release](https://github.com/gexiro-global/pc-filebridge/actions/workflows/release.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/release.yml) -PC FileBridge is a local Model Context Protocol (MCP) server that gives ChatGPT, Codex, and other MCP clients bounded access to operator-selected folders. It can read UTF-8 text and create new files or directories, but it cannot overwrite, append, rename, move, link, or delete. - -The create-only guarantee is enforced by the server. New files use operating-system exclusive create mode (`wx`), so an existing target returns `TARGET_EXISTS` and remains unchanged. - -## Security properties - -- Every operation uses a configured `root_id` and a relative path. -- Absolute paths, UNC paths, traversal, alternate data streams, reserved Windows names, symlinks, junctions, and reparse-point escapes are blocked. -- Each existing component is matched to the filesystem-stored directory entry by exact file identity. Windows 8.3 and other alternate spellings are rejected; case-only spelling differences remain allowed on Windows. -- Missing, zero, unstable, or ambiguous file identity fails closed. Regular files with multiple hard links are rejected. -- Sensitive folders and credential filenames are hidden and rejected, including `.ssh`, `.aws`, `.azure`, `.codex`, `.git`, `AppData`, `.env*`, private-key formats, PuTTY `.ppk`, Java keystores, and SSH `id_*` private-key names. -- Text reads are UTF-8 only, byte-bounded, and redact common credential patterns. -- Directory listings and filename searches are bounded. -- The server has no network client and does not execute shell commands. -- A complete drive root requires an exact, explicit risk opt-in. - -These controls reduce risk but cannot determine whether every ordinary document is private. Configure the narrowest useful roots and treat returned file content as untrusted data. Portable Node.js cannot provide race-free Windows `openat2` semantics, so pre/post-operation identity checks reduce but do not eliminate attacks by a more-privileged process that can mutate the filesystem concurrently. - -## MCP tools - -| Tool | Purpose | -|---|---| -| `list_roots` | List configured roots without revealing absolute host paths | -| `list_directory` | List bounded, non-sensitive directory entries | -| `stat_path` | Read metadata for one existing path | -| `read_text_file` | Read a bounded, redacted UTF-8 prefix | -| `search_file_names` | Search names, never file contents | -| `create_directory` | Create exactly one new directory | -| `create_text_file` | Create exactly one new UTF-8 file with exclusive create | - -There are no delete, overwrite, append, patch, rename, move, remove, or unlink tools. - -## Requirements - -- Node.js 22 or newer -- Windows for the supplied Task Scheduler helpers, or Docker on Linux for the always-on VPS deployment -- An MCP-compatible client - -The core server and policy tests also run on Linux and macOS. The hardened Docker deployment pins Node.js and the official Secure MCP Tunnel runtime by immutable OCI digest. - -## Install and configure - -```powershell -git clone https://github.com/gexiro-global/pc-filebridge.git -Set-Location pc-filebridge -npm ci --ignore-scripts -Copy-Item .\config\roots.example.json .\config\roots.local.json -``` - -Edit `config\roots.local.json` and replace the example path with one or more folders you control. The local file is ignored by Git. - -Build and verify: - -```powershell -npm run verify -``` - -Run over stdio: - -```powershell -$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.local.json).Path -node .\mcp\server.mjs -``` - -The repository includes `.mcp.json` and a Codex plugin manifest. Make sure `FILEBRIDGE_CONFIG` is available to the spawned MCP process. If no configuration exists, startup fails closed with `CONFIG_UNAVAILABLE`. - -## ChatGPT Secure MCP Tunnel - -For ChatGPT, create a dedicated Secure MCP Tunnel and a dedicated runtime API key. Keep the key outside the repository. The helper scripts expect the tunnel client at `%LOCALAPPDATA%\PCFileBridge\bin\tunnel-client.exe` and store the key in `%LOCALAPPDATA%\PCFileBridge\private\.env.local` with a restricted ACL. - -```powershell -.\scripts\Initialize-PCFileBridgeRuntimeKey.ps1 -.\scripts\Connect-PCFileBridgeTunnel.ps1 -TunnelId 'tunnel_...' -.\scripts\Get-PCFileBridgeTunnelStatus.ps1 -``` - -The tunnel runtime must run on the computer that owns the configured folders. A VPS deployment can remain available while personal devices are offline, but it exposes files stored in its persistent server volume; it does not make a powered-off PC disk remotely readable. See [VPS deployment](docs/VPS_DEPLOYMENT.md). - -Version 0.2.2 separates the main PC, laptop, and infrastructure into three role-bound tunnels. Their tunnel identifiers, runtime aliases, and root ids must never be reused across roles. The Windows and Docker launchers verify the operator-visible tunnel name before starting, and local ChatGPT connectors require an explicit `armed` operator gate. This prevents a PC and VPS poller from silently serving different backends through one connector. - -ChatGPT cannot securely infer which physical device opened a conversation. Operators must select the clearly named PC, laptop, or infrastructure connector. Local Codex can instead use its device-local stdio configuration. - -Windows local roles automatically discover healthy, online NTFS volumes on internal NVMe, SATA, SAS, RAID, Storage Spaces, or SCM buses. Each volume gets a stable opaque id derived from host, disk, partition, volume, and serial identity. A drive-letter change keeps the same volume id while changing the role-bound root id, for example `pc-e` to `pc-f`. Labels and raw hardware identifiers are never exposed. - -File Backed Virtual, USB, SD, MMC, 1394, and removable volumes are blocked until the operator approves the exact opaque volume id in the ACL-protected private registry. Network, optical, unknown, ReFS, unhealthy, offline, incomplete-identity, and identity-collision candidates always fail closed. - -```powershell -.\scripts\Get-PCFileBridgeVolumeCandidates.ps1 -Role pc-local -.\scripts\Approve-PCFileBridgeVolume.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -BusType 'File Backed Virtual' -Reason 'Authorized lab VHDX' -.\scripts\Revoke-PCFileBridgeVolumeApproval.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -``` - -The monitor requires three identical topology snapshots, writes a separate candidate, runs a real local seven-tool MCP probe, and only then promotes the candidate and last-known-good state. Failed and crash-interrupted candidates roll back or recover transactionally and are suppressed until topology changes. The connector is not reinstalled: callers discover the live set through `list_roots`. - -See [tunnel roles and device isolation](docs/TUNNEL_ROLES.md) for the exact role contract, gate workflow, split-brain recovery, and availability limits. - -For an always-on private deployment, use `deploy/docker/compose.example.yml`. It runs on digest-pinned Node.js 24 LTS as a non-root user with a read-only root filesystem, no published ports or Linux capabilities, bounded resources, external data and secret volumes, warning-only tunnel logs with rotation, and a tunnel-aware healthcheck. The runtime key and tunnel ID are mounted from files and never embedded in the image or Compose configuration. - -The helper defaults to the configured narrow roots. Full-drive mode is never enabled by default. - -## Optional autostart - -After a successful manual connection: - -```powershell -.\scripts\Install-PCFileBridgeAutostart.ps1 -TunnelId 'tunnel_...' -``` - -The installer creates a new per-user scheduled task and refuses to replace an existing task. - -For role-bound automatic volume discovery, install the dedicated per-user task: - -```powershell -.\scripts\Install-PCFileBridgeRoleAutostart.ps1 -Role pc-local -``` - -If the protected tunnel runtime intentionally uses a separate local application-data directory, pass its absolute path with `-RuntimeLocalAppData`. The task script runs a singleton monitor and does not contain a tunnel identifier or API key in its arguments. Both installers create long-running tasks with no finite execution limit, do not stop them on battery or idle transitions, and add a five-minute recovery trigger for externally interrupted runtimes; they refuse to replace an existing task. - -## Full-drive mode - -Exposing an entire drive materially increases disclosure risk. The server refuses a filesystem root unless both the full-drive configuration and this exact process variable are supplied: - -```powershell -$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.full-drive.example.json).Path -$env:FILEBRIDGE_ALLOW_DRIVE_ROOT = 'I_ACCEPT_FULL_DRIVE_ACCESS_RISK' -node .\mcp\server.mjs -``` - -The Windows tunnel helper performs the same opt-in only when explicitly called with `-EnableFullDrive $true`. - -## Development - -```powershell -npm ci --ignore-scripts -npm run check -npm pack --dry-run --ignore-scripts -``` - -`npm run check` performs a tracked-file secret scan, type checking, policy tests, a production build, license and package-content checks, and a real MCP stdio smoke test that requires exactly seven tools and zero forbidden mutation tools. Pull requests run on Ubuntu and Windows with Node.js 22 and 24. Windows jobs must create and reject a real 8.3 alternate-name fixture and cannot silently skip that check. - -## Release verification - -Official releases contain four downloadable files: - -- `pc-filebridge-vX.Y.Z-runtime-npm.tgz` -- `pc-filebridge-vX.Y.Z-source.tar.gz` -- `pc-filebridge-vX.Y.Z-sbom.cdx.json` -- `SHA256SUMS` - -Download all files into one empty directory and verify the hashes before installation. On Windows: - -```powershell -Get-Content .\SHA256SUMS | ForEach-Object { - $hash, $name = $_ -split ' ', 2 - if ((Get-FileHash -Algorithm SHA256 -LiteralPath $name).Hash.ToLowerInvariant() -ne $hash) { - throw "Checksum mismatch: $name" - } -} -``` - -The GitHub release also carries build-provenance attestations. See [Release verification](docs/RELEASE_VERIFICATION.md), [container image security](docs/IMAGE_SECURITY.md), and [Release process](docs/RELEASE_PROCESS.md). - -## Privacy and security - -PC FileBridge is self-hosted and includes no telemetry. Data requested through MCP is sent to the connected client and is then subject to that client's provider and workspace policies. Read [ARCHITECTURE.md](ARCHITECTURE.md), [PRIVACY.md](PRIVACY.md), [SECURITY.md](SECURITY.md), [SUPPORT.md](SUPPORT.md), and [THREAT_MODEL.md](THREAT_MODEL.md) before exposing sensitive folders. - -## License - -Apache-2.0. Copyright 2026 Gexiro Global Enterprises Ltd. +[Security and trust evidence](docs/SECURITY-TRUST.md) documents the project's policies and automated checks. No certification or badge level is claimed. + +PC FileBridge is a local Model Context Protocol (MCP) server that gives ChatGPT, Codex, and other MCP clients bounded access to operator-selected folders. It can read UTF-8 text and create new files or directories, but it cannot overwrite, append, rename, move, link, or delete. + +The create-only guarantee is enforced by the server. New files use operating-system exclusive create mode (`wx`), so an existing target returns `TARGET_EXISTS` and remains unchanged. + +## Security properties + +- Every operation uses a configured `root_id` and a relative path. +- Absolute paths, UNC paths, traversal, alternate data streams, reserved Windows names, symlinks, junctions, and reparse-point escapes are blocked. +- Each existing component is matched to the filesystem-stored directory entry by exact file identity. Windows 8.3 and other alternate spellings are rejected; case-only spelling differences remain allowed on Windows. +- Missing, zero, unstable, or ambiguous file identity fails closed. Regular files with multiple hard links are rejected. +- Sensitive folders and credential filenames are hidden and rejected, including `.ssh`, `.aws`, `.azure`, `.codex`, `.git`, `AppData`, `.env*`, private-key formats, PuTTY `.ppk`, Java keystores, and SSH `id_*` private-key names. +- Text reads are UTF-8 only, byte-bounded, and redact common credential patterns. +- Directory listings and filename searches are bounded. +- The server has no network client and does not execute shell commands. +- A complete drive root requires an exact, explicit risk opt-in. + +These controls reduce risk but cannot determine whether every ordinary document is private. Configure the narrowest useful roots and treat returned file content as untrusted data. Portable Node.js cannot provide race-free Windows `openat2` semantics, so pre/post-operation identity checks reduce but do not eliminate attacks by a more-privileged process that can mutate the filesystem concurrently. + +## MCP tools + +| Tool | Purpose | +|---|---| +| `list_roots` | List configured roots without revealing absolute host paths | +| `list_directory` | List bounded, non-sensitive directory entries | +| `stat_path` | Read metadata for one existing path | +| `read_text_file` | Read a bounded, redacted UTF-8 prefix | +| `search_file_names` | Search names, never file contents | +| `create_directory` | Create exactly one new directory | +| `create_text_file` | Create exactly one new UTF-8 file with exclusive create | + +There are no delete, overwrite, append, patch, rename, move, remove, or unlink tools. + +## Requirements + +- Node.js 22 or newer +- Windows for the supplied Task Scheduler helpers, or Docker on Linux for the always-on VPS deployment +- An MCP-compatible client + +The core server and policy tests also run on Linux and macOS. The hardened Docker deployment pins Node.js and the official Secure MCP Tunnel runtime by immutable OCI digest. + +## Install and configure + +```powershell +git clone https://github.com/gexiro-global/pc-filebridge.git +Set-Location pc-filebridge +npm ci --ignore-scripts +Copy-Item .\config\roots.example.json .\config\roots.local.json +``` + +Edit `config\roots.local.json` and replace the example path with one or more folders you control. The local file is ignored by Git. + +Build and verify: + +```powershell +npm run verify +``` + +Run over stdio: + +```powershell +$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.local.json).Path +node .\mcp\server.mjs +``` + +The repository includes `.mcp.json` and a Codex plugin manifest. Make sure `FILEBRIDGE_CONFIG` is available to the spawned MCP process. If no configuration exists, startup fails closed with `CONFIG_UNAVAILABLE`. + +## ChatGPT Secure MCP Tunnel + +For ChatGPT, create a dedicated Secure MCP Tunnel and a dedicated runtime API key. Keep the key outside the repository. The helper scripts expect the tunnel client at `%LOCALAPPDATA%\PCFileBridge\bin\tunnel-client.exe` and store the key in `%LOCALAPPDATA%\PCFileBridge\private\.env.local` with a restricted ACL. + +```powershell +.\scripts\Initialize-PCFileBridgeRuntimeKey.ps1 +.\scripts\Connect-PCFileBridgeTunnel.ps1 -TunnelId 'tunnel_...' +.\scripts\Get-PCFileBridgeTunnelStatus.ps1 +``` + +The tunnel runtime must run on the computer that owns the configured folders. A VPS deployment can remain available while personal devices are offline, but it exposes files stored in its persistent server volume; it does not make a powered-off PC disk remotely readable. See [VPS deployment](docs/VPS_DEPLOYMENT.md). + +Version 0.2.2 separates the main PC, laptop, and infrastructure into three role-bound tunnels. Their tunnel identifiers, runtime aliases, and root ids must never be reused across roles. The Windows and Docker launchers verify the operator-visible tunnel name before starting, and local ChatGPT connectors require an explicit `armed` operator gate. This prevents a PC and VPS poller from silently serving different backends through one connector. + +ChatGPT cannot securely infer which physical device opened a conversation. Operators must select the clearly named PC, laptop, or infrastructure connector. Local Codex can instead use its device-local stdio configuration. + +Windows local roles automatically discover healthy, online NTFS volumes on internal NVMe, SATA, SAS, RAID, Storage Spaces, or SCM buses. Each volume gets a stable opaque id derived from host, disk, partition, volume, and serial identity. A drive-letter change keeps the same volume id while changing the role-bound root id, for example `pc-e` to `pc-f`. Labels and raw hardware identifiers are never exposed. + +File Backed Virtual, USB, SD, MMC, 1394, and removable volumes are blocked until the operator approves the exact opaque volume id in the ACL-protected private registry. Network, optical, unknown, ReFS, unhealthy, offline, incomplete-identity, and identity-collision candidates always fail closed. + +```powershell +.\scripts\Get-PCFileBridgeVolumeCandidates.ps1 -Role pc-local +.\scripts\Approve-PCFileBridgeVolume.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -BusType 'File Backed Virtual' -Reason 'Authorized lab VHDX' +.\scripts\Revoke-PCFileBridgeVolumeApproval.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' +``` + +The monitor requires three identical topology snapshots, writes a separate candidate, runs a real local seven-tool MCP probe, and only then promotes the candidate and last-known-good state. Failed and crash-interrupted candidates roll back or recover transactionally and are suppressed until topology changes. The connector is not reinstalled: callers discover the live set through `list_roots`. + +See [tunnel roles and device isolation](docs/TUNNEL_ROLES.md) for the exact role contract, gate workflow, split-brain recovery, and availability limits. + +For an always-on private deployment, use `deploy/docker/compose.example.yml`. It runs on digest-pinned Node.js 24 LTS as a non-root user with a read-only root filesystem, no published ports or Linux capabilities, bounded resources, external data and secret volumes, warning-only tunnel logs with rotation, and a tunnel-aware healthcheck. The runtime key and tunnel ID are mounted from files and never embedded in the image or Compose configuration. + +The helper defaults to the configured narrow roots. Full-drive mode is never enabled by default. + +## Optional autostart + +After a successful manual connection: + +```powershell +.\scripts\Install-PCFileBridgeAutostart.ps1 -TunnelId 'tunnel_...' +``` + +The installer creates a new per-user scheduled task and refuses to replace an existing task. + +For role-bound automatic volume discovery, install the dedicated per-user task: + +```powershell +.\scripts\Install-PCFileBridgeRoleAutostart.ps1 -Role pc-local +``` + +If the protected tunnel runtime intentionally uses a separate local application-data directory, pass its absolute path with `-RuntimeLocalAppData`. The task script runs a singleton monitor and does not contain a tunnel identifier or API key in its arguments. Both installers create long-running tasks with no finite execution limit, do not stop them on battery or idle transitions, and add a five-minute recovery trigger for externally interrupted runtimes; they refuse to replace an existing task. + +## Full-drive mode + +Exposing an entire drive materially increases disclosure risk. The server refuses a filesystem root unless both the full-drive configuration and this exact process variable are supplied: + +```powershell +$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.full-drive.example.json).Path +$env:FILEBRIDGE_ALLOW_DRIVE_ROOT = 'I_ACCEPT_FULL_DRIVE_ACCESS_RISK' +node .\mcp\server.mjs +``` + +The Windows tunnel helper performs the same opt-in only when explicitly called with `-EnableFullDrive $true`. + +## Development + +```powershell +npm ci --ignore-scripts +npm run check +npm pack --dry-run --ignore-scripts +``` + +`npm run check` performs a tracked-file secret scan, type checking, policy tests, a production build, license and package-content checks, and a real MCP stdio smoke test that requires exactly seven tools and zero forbidden mutation tools. Pull requests run on Ubuntu and Windows with Node.js 22 and 24. Windows jobs must create and reject a real 8.3 alternate-name fixture and cannot silently skip that check. + +## Release verification + +Official releases contain four downloadable files: + +- `pc-filebridge-vX.Y.Z-runtime-npm.tgz` +- `pc-filebridge-vX.Y.Z-source.tar.gz` +- `pc-filebridge-vX.Y.Z-sbom.cdx.json` +- `SHA256SUMS` + +Download all files into one empty directory and verify the hashes before installation. On Windows: + +```powershell +Get-Content .\SHA256SUMS | ForEach-Object { + $hash, $name = $_ -split ' ', 2 + if ((Get-FileHash -Algorithm SHA256 -LiteralPath $name).Hash.ToLowerInvariant() -ne $hash) { + throw "Checksum mismatch: $name" + } +} +``` + +The GitHub release also carries build-provenance attestations. See [Release verification](docs/RELEASE_VERIFICATION.md), [container image security](docs/IMAGE_SECURITY.md), and [Release process](docs/RELEASE_PROCESS.md). + +## Privacy and security + +PC FileBridge is self-hosted and includes no telemetry. Data requested through MCP is sent to the connected client and is then subject to that client's provider and workspace policies. Read [ARCHITECTURE.md](ARCHITECTURE.md), [PRIVACY.md](PRIVACY.md), [SECURITY.md](SECURITY.md), [SUPPORT.md](SUPPORT.md), and [THREAT_MODEL.md](THREAT_MODEL.md) before exposing sensitive folders. + +## License + +Apache-2.0. Copyright 2026 Gexiro Global Enterprises Ltd. diff --git a/docs/SECURITY-TRUST.md b/docs/SECURITY-TRUST.md new file mode 100644 index 0000000..e56748c --- /dev/null +++ b/docs/SECURITY-TRUST.md @@ -0,0 +1,11 @@ +# Security and trust evidence + +This page is an evidence index, not a certification. The evidence does not prove the project is vulnerability-free, does not establish a SLSA level, and does not imply OpenSSF affiliation or endorsement. Tool output describes observed posture; it is not proof of compromise or absence of compromise. + +- [Security policy](../SECURITY.md), [threat model](../THREAT_MODEL.md), [architecture](../ARCHITECTURE.md) and [privacy policy](../PRIVACY.md) +- [Contribution process](../CONTRIBUTING.md), [governance](../GOVERNANCE.md), [maintainers](../MAINTAINERS.md) and [support](../SUPPORT.md) +- CI verifies type safety, tests, secret scanning, package contents, configuration contracts, MCP surface and image vulnerability policy. +- CodeQL, dependency review, Dependabot, secret scanning and OpenSSF Scorecard are configured. +- Third-party actions are pinned to immutable commit SHAs with version comments. + +The Scorecard badge is intentionally withheld until a successful default-branch run has produced a public API result. `.bestpractices.json` contains evidence-backed automation proposals only; it is not an OpenSSF Best Practices or OSPS Baseline claim. A human must review any badge submission. diff --git a/security-insights.yml b/security-insights.yml new file mode 100644 index 0000000..18a27ec --- /dev/null +++ b/security-insights.yml @@ -0,0 +1,64 @@ +header: + schema-version: 2.2.0 + last-updated: '2026-09-04' + last-reviewed: '2026-09-04' + url: https://raw.githubusercontent.com/gexiro-global/pc-filebridge/main/security-insights.yml + comment: This single-repository file reports current practices and makes no certification claim. +project: + name: PC FileBridge + homepage: https://github.com/gexiro-global/pc-filebridge + administrators: + - name: dzeusking-dev + affiliation: Gexiro Global Enterprises Ltd. + social: https://github.com/dzeusking-dev + primary: true + documentation: + quickstart-guide: https://github.com/gexiro-global/pc-filebridge#install-and-configure + detailed-guide: https://github.com/gexiro-global/pc-filebridge/blob/main/ARCHITECTURE.md + code-of-conduct: https://github.com/gexiro-global/pc-filebridge/blob/main/CODE_OF_CONDUCT.md + release-process: https://github.com/gexiro-global/pc-filebridge/blob/main/docs/RELEASE_PROCESS.md + support-policy: https://github.com/gexiro-global/pc-filebridge/blob/main/SUPPORT.md + signature-verification: https://github.com/gexiro-global/pc-filebridge/blob/main/docs/RELEASE_VERIFICATION.md + repositories: + - name: pc-filebridge + url: https://github.com/gexiro-global/pc-filebridge + comment: Canonical source and release repository. + vulnerability-reporting: + reports-accepted: true + bug-bounty-available: false + policy: https://github.com/gexiro-global/pc-filebridge/blob/main/SECURITY.md +repository: + url: https://github.com/gexiro-global/pc-filebridge + status: active + accepts-change-request: true + accepts-automated-change-request: true + no-third-party-packages: false + core-team: + - name: dzeusking-dev + affiliation: Gexiro Global Enterprises Ltd. + social: https://github.com/dzeusking-dev + primary: true + documentation: + contributing-guide: https://github.com/gexiro-global/pc-filebridge/blob/main/CONTRIBUTING.md + review-policy: https://github.com/gexiro-global/pc-filebridge/blob/main/GOVERNANCE.md + security-policy: https://github.com/gexiro-global/pc-filebridge/blob/main/SECURITY.md + governance: https://github.com/gexiro-global/pc-filebridge/blob/main/GOVERNANCE.md + dependency-management-policy: https://github.com/gexiro-global/pc-filebridge/blob/main/docs/SECURITY-TRUST.md + license: + url: https://github.com/gexiro-global/pc-filebridge/blob/main/LICENSE + expression: Apache-2.0 + release: + changelog: https://github.com/gexiro-global/pc-filebridge/blob/main/CHANGELOG.md + automated-pipeline: true + distribution-points: + - uri: https://github.com/gexiro-global/pc-filebridge/releases + comment: Versioned GitHub release assets. + attestations: + - name: GitHub build provenance + predicate-uri: https://slsa.dev/provenance/v1 + location: https://github.com/gexiro-global/pc-filebridge/attestations + comment: Verify the selected release asset against this repository and tag. + security: + assessments: + self: + comment: Maintainer self-assessment only; no independent audit is claimed. From 4ff2feb261c8697f3080393a5271dfe0f6e7601e Mon Sep 17 00:00:00 2001 From: dzeusking-dev Date: Fri, 4 Sep 2026 15:37:20 +0200 Subject: [PATCH 2/2] chore: keep README diff minimal Signed-off-by: Bartosz Joachimiak <262029076+dzeusking-dev@users.noreply.github.com> --- README.md | 348 +++++++++++++++++++++++++++--------------------------- 1 file changed, 174 insertions(+), 174 deletions(-) diff --git a/README.md b/README.md index 6b6f35e..67e2ed8 100644 --- a/README.md +++ b/README.md @@ -1,177 +1,177 @@ -# PC FileBridge - -[![CI](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml) -[![CodeQL](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml) +# PC FileBridge + +[![CI](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/ci.yml) +[![CodeQL](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/codeql.yml) [![Release](https://github.com/gexiro-global/pc-filebridge/actions/workflows/release.yml/badge.svg)](https://github.com/gexiro-global/pc-filebridge/actions/workflows/release.yml) [Security and trust evidence](docs/SECURITY-TRUST.md) documents the project's policies and automated checks. No certification or badge level is claimed. - -PC FileBridge is a local Model Context Protocol (MCP) server that gives ChatGPT, Codex, and other MCP clients bounded access to operator-selected folders. It can read UTF-8 text and create new files or directories, but it cannot overwrite, append, rename, move, link, or delete. - -The create-only guarantee is enforced by the server. New files use operating-system exclusive create mode (`wx`), so an existing target returns `TARGET_EXISTS` and remains unchanged. - -## Security properties - -- Every operation uses a configured `root_id` and a relative path. -- Absolute paths, UNC paths, traversal, alternate data streams, reserved Windows names, symlinks, junctions, and reparse-point escapes are blocked. -- Each existing component is matched to the filesystem-stored directory entry by exact file identity. Windows 8.3 and other alternate spellings are rejected; case-only spelling differences remain allowed on Windows. -- Missing, zero, unstable, or ambiguous file identity fails closed. Regular files with multiple hard links are rejected. -- Sensitive folders and credential filenames are hidden and rejected, including `.ssh`, `.aws`, `.azure`, `.codex`, `.git`, `AppData`, `.env*`, private-key formats, PuTTY `.ppk`, Java keystores, and SSH `id_*` private-key names. -- Text reads are UTF-8 only, byte-bounded, and redact common credential patterns. -- Directory listings and filename searches are bounded. -- The server has no network client and does not execute shell commands. -- A complete drive root requires an exact, explicit risk opt-in. - -These controls reduce risk but cannot determine whether every ordinary document is private. Configure the narrowest useful roots and treat returned file content as untrusted data. Portable Node.js cannot provide race-free Windows `openat2` semantics, so pre/post-operation identity checks reduce but do not eliminate attacks by a more-privileged process that can mutate the filesystem concurrently. - -## MCP tools - -| Tool | Purpose | -|---|---| -| `list_roots` | List configured roots without revealing absolute host paths | -| `list_directory` | List bounded, non-sensitive directory entries | -| `stat_path` | Read metadata for one existing path | -| `read_text_file` | Read a bounded, redacted UTF-8 prefix | -| `search_file_names` | Search names, never file contents | -| `create_directory` | Create exactly one new directory | -| `create_text_file` | Create exactly one new UTF-8 file with exclusive create | - -There are no delete, overwrite, append, patch, rename, move, remove, or unlink tools. - -## Requirements - -- Node.js 22 or newer -- Windows for the supplied Task Scheduler helpers, or Docker on Linux for the always-on VPS deployment -- An MCP-compatible client - -The core server and policy tests also run on Linux and macOS. The hardened Docker deployment pins Node.js and the official Secure MCP Tunnel runtime by immutable OCI digest. - -## Install and configure - -```powershell -git clone https://github.com/gexiro-global/pc-filebridge.git -Set-Location pc-filebridge -npm ci --ignore-scripts -Copy-Item .\config\roots.example.json .\config\roots.local.json -``` - -Edit `config\roots.local.json` and replace the example path with one or more folders you control. The local file is ignored by Git. - -Build and verify: - -```powershell -npm run verify -``` - -Run over stdio: - -```powershell -$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.local.json).Path -node .\mcp\server.mjs -``` - -The repository includes `.mcp.json` and a Codex plugin manifest. Make sure `FILEBRIDGE_CONFIG` is available to the spawned MCP process. If no configuration exists, startup fails closed with `CONFIG_UNAVAILABLE`. - -## ChatGPT Secure MCP Tunnel - -For ChatGPT, create a dedicated Secure MCP Tunnel and a dedicated runtime API key. Keep the key outside the repository. The helper scripts expect the tunnel client at `%LOCALAPPDATA%\PCFileBridge\bin\tunnel-client.exe` and store the key in `%LOCALAPPDATA%\PCFileBridge\private\.env.local` with a restricted ACL. - -```powershell -.\scripts\Initialize-PCFileBridgeRuntimeKey.ps1 -.\scripts\Connect-PCFileBridgeTunnel.ps1 -TunnelId 'tunnel_...' -.\scripts\Get-PCFileBridgeTunnelStatus.ps1 -``` - -The tunnel runtime must run on the computer that owns the configured folders. A VPS deployment can remain available while personal devices are offline, but it exposes files stored in its persistent server volume; it does not make a powered-off PC disk remotely readable. See [VPS deployment](docs/VPS_DEPLOYMENT.md). - -Version 0.2.2 separates the main PC, laptop, and infrastructure into three role-bound tunnels. Their tunnel identifiers, runtime aliases, and root ids must never be reused across roles. The Windows and Docker launchers verify the operator-visible tunnel name before starting, and local ChatGPT connectors require an explicit `armed` operator gate. This prevents a PC and VPS poller from silently serving different backends through one connector. - -ChatGPT cannot securely infer which physical device opened a conversation. Operators must select the clearly named PC, laptop, or infrastructure connector. Local Codex can instead use its device-local stdio configuration. - -Windows local roles automatically discover healthy, online NTFS volumes on internal NVMe, SATA, SAS, RAID, Storage Spaces, or SCM buses. Each volume gets a stable opaque id derived from host, disk, partition, volume, and serial identity. A drive-letter change keeps the same volume id while changing the role-bound root id, for example `pc-e` to `pc-f`. Labels and raw hardware identifiers are never exposed. - -File Backed Virtual, USB, SD, MMC, 1394, and removable volumes are blocked until the operator approves the exact opaque volume id in the ACL-protected private registry. Network, optical, unknown, ReFS, unhealthy, offline, incomplete-identity, and identity-collision candidates always fail closed. - -```powershell -.\scripts\Get-PCFileBridgeVolumeCandidates.ps1 -Role pc-local -.\scripts\Approve-PCFileBridgeVolume.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -BusType 'File Backed Virtual' -Reason 'Authorized lab VHDX' -.\scripts\Revoke-PCFileBridgeVolumeApproval.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -``` - -The monitor requires three identical topology snapshots, writes a separate candidate, runs a real local seven-tool MCP probe, and only then promotes the candidate and last-known-good state. Failed and crash-interrupted candidates roll back or recover transactionally and are suppressed until topology changes. The connector is not reinstalled: callers discover the live set through `list_roots`. - -See [tunnel roles and device isolation](docs/TUNNEL_ROLES.md) for the exact role contract, gate workflow, split-brain recovery, and availability limits. - -For an always-on private deployment, use `deploy/docker/compose.example.yml`. It runs on digest-pinned Node.js 24 LTS as a non-root user with a read-only root filesystem, no published ports or Linux capabilities, bounded resources, external data and secret volumes, warning-only tunnel logs with rotation, and a tunnel-aware healthcheck. The runtime key and tunnel ID are mounted from files and never embedded in the image or Compose configuration. - -The helper defaults to the configured narrow roots. Full-drive mode is never enabled by default. - -## Optional autostart - -After a successful manual connection: - -```powershell -.\scripts\Install-PCFileBridgeAutostart.ps1 -TunnelId 'tunnel_...' -``` - -The installer creates a new per-user scheduled task and refuses to replace an existing task. - -For role-bound automatic volume discovery, install the dedicated per-user task: - -```powershell -.\scripts\Install-PCFileBridgeRoleAutostart.ps1 -Role pc-local -``` - -If the protected tunnel runtime intentionally uses a separate local application-data directory, pass its absolute path with `-RuntimeLocalAppData`. The task script runs a singleton monitor and does not contain a tunnel identifier or API key in its arguments. Both installers create long-running tasks with no finite execution limit, do not stop them on battery or idle transitions, and add a five-minute recovery trigger for externally interrupted runtimes; they refuse to replace an existing task. - -## Full-drive mode - -Exposing an entire drive materially increases disclosure risk. The server refuses a filesystem root unless both the full-drive configuration and this exact process variable are supplied: - -```powershell -$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.full-drive.example.json).Path -$env:FILEBRIDGE_ALLOW_DRIVE_ROOT = 'I_ACCEPT_FULL_DRIVE_ACCESS_RISK' -node .\mcp\server.mjs -``` - -The Windows tunnel helper performs the same opt-in only when explicitly called with `-EnableFullDrive $true`. - -## Development - -```powershell -npm ci --ignore-scripts -npm run check -npm pack --dry-run --ignore-scripts -``` - -`npm run check` performs a tracked-file secret scan, type checking, policy tests, a production build, license and package-content checks, and a real MCP stdio smoke test that requires exactly seven tools and zero forbidden mutation tools. Pull requests run on Ubuntu and Windows with Node.js 22 and 24. Windows jobs must create and reject a real 8.3 alternate-name fixture and cannot silently skip that check. - -## Release verification - -Official releases contain four downloadable files: - -- `pc-filebridge-vX.Y.Z-runtime-npm.tgz` -- `pc-filebridge-vX.Y.Z-source.tar.gz` -- `pc-filebridge-vX.Y.Z-sbom.cdx.json` -- `SHA256SUMS` - -Download all files into one empty directory and verify the hashes before installation. On Windows: - -```powershell -Get-Content .\SHA256SUMS | ForEach-Object { - $hash, $name = $_ -split ' ', 2 - if ((Get-FileHash -Algorithm SHA256 -LiteralPath $name).Hash.ToLowerInvariant() -ne $hash) { - throw "Checksum mismatch: $name" - } -} -``` - -The GitHub release also carries build-provenance attestations. See [Release verification](docs/RELEASE_VERIFICATION.md), [container image security](docs/IMAGE_SECURITY.md), and [Release process](docs/RELEASE_PROCESS.md). - -## Privacy and security - -PC FileBridge is self-hosted and includes no telemetry. Data requested through MCP is sent to the connected client and is then subject to that client's provider and workspace policies. Read [ARCHITECTURE.md](ARCHITECTURE.md), [PRIVACY.md](PRIVACY.md), [SECURITY.md](SECURITY.md), [SUPPORT.md](SUPPORT.md), and [THREAT_MODEL.md](THREAT_MODEL.md) before exposing sensitive folders. - -## License - -Apache-2.0. Copyright 2026 Gexiro Global Enterprises Ltd. + +PC FileBridge is a local Model Context Protocol (MCP) server that gives ChatGPT, Codex, and other MCP clients bounded access to operator-selected folders. It can read UTF-8 text and create new files or directories, but it cannot overwrite, append, rename, move, link, or delete. + +The create-only guarantee is enforced by the server. New files use operating-system exclusive create mode (`wx`), so an existing target returns `TARGET_EXISTS` and remains unchanged. + +## Security properties + +- Every operation uses a configured `root_id` and a relative path. +- Absolute paths, UNC paths, traversal, alternate data streams, reserved Windows names, symlinks, junctions, and reparse-point escapes are blocked. +- Each existing component is matched to the filesystem-stored directory entry by exact file identity. Windows 8.3 and other alternate spellings are rejected; case-only spelling differences remain allowed on Windows. +- Missing, zero, unstable, or ambiguous file identity fails closed. Regular files with multiple hard links are rejected. +- Sensitive folders and credential filenames are hidden and rejected, including `.ssh`, `.aws`, `.azure`, `.codex`, `.git`, `AppData`, `.env*`, private-key formats, PuTTY `.ppk`, Java keystores, and SSH `id_*` private-key names. +- Text reads are UTF-8 only, byte-bounded, and redact common credential patterns. +- Directory listings and filename searches are bounded. +- The server has no network client and does not execute shell commands. +- A complete drive root requires an exact, explicit risk opt-in. + +These controls reduce risk but cannot determine whether every ordinary document is private. Configure the narrowest useful roots and treat returned file content as untrusted data. Portable Node.js cannot provide race-free Windows `openat2` semantics, so pre/post-operation identity checks reduce but do not eliminate attacks by a more-privileged process that can mutate the filesystem concurrently. + +## MCP tools + +| Tool | Purpose | +|---|---| +| `list_roots` | List configured roots without revealing absolute host paths | +| `list_directory` | List bounded, non-sensitive directory entries | +| `stat_path` | Read metadata for one existing path | +| `read_text_file` | Read a bounded, redacted UTF-8 prefix | +| `search_file_names` | Search names, never file contents | +| `create_directory` | Create exactly one new directory | +| `create_text_file` | Create exactly one new UTF-8 file with exclusive create | + +There are no delete, overwrite, append, patch, rename, move, remove, or unlink tools. + +## Requirements + +- Node.js 22 or newer +- Windows for the supplied Task Scheduler helpers, or Docker on Linux for the always-on VPS deployment +- An MCP-compatible client + +The core server and policy tests also run on Linux and macOS. The hardened Docker deployment pins Node.js and the official Secure MCP Tunnel runtime by immutable OCI digest. + +## Install and configure + +```powershell +git clone https://github.com/gexiro-global/pc-filebridge.git +Set-Location pc-filebridge +npm ci --ignore-scripts +Copy-Item .\config\roots.example.json .\config\roots.local.json +``` + +Edit `config\roots.local.json` and replace the example path with one or more folders you control. The local file is ignored by Git. + +Build and verify: + +```powershell +npm run verify +``` + +Run over stdio: + +```powershell +$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.local.json).Path +node .\mcp\server.mjs +``` + +The repository includes `.mcp.json` and a Codex plugin manifest. Make sure `FILEBRIDGE_CONFIG` is available to the spawned MCP process. If no configuration exists, startup fails closed with `CONFIG_UNAVAILABLE`. + +## ChatGPT Secure MCP Tunnel + +For ChatGPT, create a dedicated Secure MCP Tunnel and a dedicated runtime API key. Keep the key outside the repository. The helper scripts expect the tunnel client at `%LOCALAPPDATA%\PCFileBridge\bin\tunnel-client.exe` and store the key in `%LOCALAPPDATA%\PCFileBridge\private\.env.local` with a restricted ACL. + +```powershell +.\scripts\Initialize-PCFileBridgeRuntimeKey.ps1 +.\scripts\Connect-PCFileBridgeTunnel.ps1 -TunnelId 'tunnel_...' +.\scripts\Get-PCFileBridgeTunnelStatus.ps1 +``` + +The tunnel runtime must run on the computer that owns the configured folders. A VPS deployment can remain available while personal devices are offline, but it exposes files stored in its persistent server volume; it does not make a powered-off PC disk remotely readable. See [VPS deployment](docs/VPS_DEPLOYMENT.md). + +Version 0.2.2 separates the main PC, laptop, and infrastructure into three role-bound tunnels. Their tunnel identifiers, runtime aliases, and root ids must never be reused across roles. The Windows and Docker launchers verify the operator-visible tunnel name before starting, and local ChatGPT connectors require an explicit `armed` operator gate. This prevents a PC and VPS poller from silently serving different backends through one connector. + +ChatGPT cannot securely infer which physical device opened a conversation. Operators must select the clearly named PC, laptop, or infrastructure connector. Local Codex can instead use its device-local stdio configuration. + +Windows local roles automatically discover healthy, online NTFS volumes on internal NVMe, SATA, SAS, RAID, Storage Spaces, or SCM buses. Each volume gets a stable opaque id derived from host, disk, partition, volume, and serial identity. A drive-letter change keeps the same volume id while changing the role-bound root id, for example `pc-e` to `pc-f`. Labels and raw hardware identifiers are never exposed. + +File Backed Virtual, USB, SD, MMC, 1394, and removable volumes are blocked until the operator approves the exact opaque volume id in the ACL-protected private registry. Network, optical, unknown, ReFS, unhealthy, offline, incomplete-identity, and identity-collision candidates always fail closed. + +```powershell +.\scripts\Get-PCFileBridgeVolumeCandidates.ps1 -Role pc-local +.\scripts\Approve-PCFileBridgeVolume.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' -BusType 'File Backed Virtual' -Reason 'Authorized lab VHDX' +.\scripts\Revoke-PCFileBridgeVolumeApproval.ps1 -Role pc-local -VolumeId 'vol-0123456789abcdef' +``` + +The monitor requires three identical topology snapshots, writes a separate candidate, runs a real local seven-tool MCP probe, and only then promotes the candidate and last-known-good state. Failed and crash-interrupted candidates roll back or recover transactionally and are suppressed until topology changes. The connector is not reinstalled: callers discover the live set through `list_roots`. + +See [tunnel roles and device isolation](docs/TUNNEL_ROLES.md) for the exact role contract, gate workflow, split-brain recovery, and availability limits. + +For an always-on private deployment, use `deploy/docker/compose.example.yml`. It runs on digest-pinned Node.js 24 LTS as a non-root user with a read-only root filesystem, no published ports or Linux capabilities, bounded resources, external data and secret volumes, warning-only tunnel logs with rotation, and a tunnel-aware healthcheck. The runtime key and tunnel ID are mounted from files and never embedded in the image or Compose configuration. + +The helper defaults to the configured narrow roots. Full-drive mode is never enabled by default. + +## Optional autostart + +After a successful manual connection: + +```powershell +.\scripts\Install-PCFileBridgeAutostart.ps1 -TunnelId 'tunnel_...' +``` + +The installer creates a new per-user scheduled task and refuses to replace an existing task. + +For role-bound automatic volume discovery, install the dedicated per-user task: + +```powershell +.\scripts\Install-PCFileBridgeRoleAutostart.ps1 -Role pc-local +``` + +If the protected tunnel runtime intentionally uses a separate local application-data directory, pass its absolute path with `-RuntimeLocalAppData`. The task script runs a singleton monitor and does not contain a tunnel identifier or API key in its arguments. Both installers create long-running tasks with no finite execution limit, do not stop them on battery or idle transitions, and add a five-minute recovery trigger for externally interrupted runtimes; they refuse to replace an existing task. + +## Full-drive mode + +Exposing an entire drive materially increases disclosure risk. The server refuses a filesystem root unless both the full-drive configuration and this exact process variable are supplied: + +```powershell +$env:FILEBRIDGE_CONFIG = (Resolve-Path .\config\roots.full-drive.example.json).Path +$env:FILEBRIDGE_ALLOW_DRIVE_ROOT = 'I_ACCEPT_FULL_DRIVE_ACCESS_RISK' +node .\mcp\server.mjs +``` + +The Windows tunnel helper performs the same opt-in only when explicitly called with `-EnableFullDrive $true`. + +## Development + +```powershell +npm ci --ignore-scripts +npm run check +npm pack --dry-run --ignore-scripts +``` + +`npm run check` performs a tracked-file secret scan, type checking, policy tests, a production build, license and package-content checks, and a real MCP stdio smoke test that requires exactly seven tools and zero forbidden mutation tools. Pull requests run on Ubuntu and Windows with Node.js 22 and 24. Windows jobs must create and reject a real 8.3 alternate-name fixture and cannot silently skip that check. + +## Release verification + +Official releases contain four downloadable files: + +- `pc-filebridge-vX.Y.Z-runtime-npm.tgz` +- `pc-filebridge-vX.Y.Z-source.tar.gz` +- `pc-filebridge-vX.Y.Z-sbom.cdx.json` +- `SHA256SUMS` + +Download all files into one empty directory and verify the hashes before installation. On Windows: + +```powershell +Get-Content .\SHA256SUMS | ForEach-Object { + $hash, $name = $_ -split ' ', 2 + if ((Get-FileHash -Algorithm SHA256 -LiteralPath $name).Hash.ToLowerInvariant() -ne $hash) { + throw "Checksum mismatch: $name" + } +} +``` + +The GitHub release also carries build-provenance attestations. See [Release verification](docs/RELEASE_VERIFICATION.md), [container image security](docs/IMAGE_SECURITY.md), and [Release process](docs/RELEASE_PROCESS.md). + +## Privacy and security + +PC FileBridge is self-hosted and includes no telemetry. Data requested through MCP is sent to the connected client and is then subject to that client's provider and workspace policies. Read [ARCHITECTURE.md](ARCHITECTURE.md), [PRIVACY.md](PRIVACY.md), [SECURITY.md](SECURITY.md), [SUPPORT.md](SUPPORT.md), and [THREAT_MODEL.md](THREAT_MODEL.md) before exposing sensitive folders. + +## License + +Apache-2.0. Copyright 2026 Gexiro Global Enterprises Ltd.