Addresses a security review of the collaboration subsystem. No auth bypass, key leak, or document-plaintext exposure was found; every finding below is availability or trust-boundary hardening. Landed as one commit because the pieces are not separable: the inbound-direction ceiling spans op-collab, op-collab-transport, and the desktop host atomically, the guarded accept spans transport, smoke, and the desktop host, and the boundary-gate rules only hold against the final state. Splitting would produce commits that fail to build or fail the gate. Relay server (public, internet-facing): - Charge pre-pairing capacity per source address. The auth-concurrency semaphore was taken before the WebSocket upgrade and the peer address was discarded, so one host could pin every permit by connecting and going silent. - Give renewals their own budget. Reauthentication competed for the same semaphore, so an unauthenticated flood progressively closed live tunnels with a policy error. - Release the pair registration when the ready status fails to send; the counterpart only reclaims it if it reads its pairing notice. - Require the X25519 key file to be owned by the running user; mode bits alone do not establish trust. - Summarise capacity rejections instead of logging one line each. Locator service: - Rate-limit publishes per client instead of process-wide. One unauthenticated caller could consume the whole budget and 429 every tenant's invite issuance. Collaboration protocol: - Size the inbound envelope ceiling from the authenticated remote role rather than sharing the 64 MiB snapshot ceiling in both directions, so an admitted guest cannot force a 64 MiB JSON parse per frame. The ceiling is applied before the discriminator and before the generic value decode; a peer-declared snapshot kind cannot raise it. - Reject display names carrying Unicode format characters, which render identically to an existing participant's name. - Reject avatar URLs pointing at non-globally-routable addresses. Transport: - Reclaim a pending-handshake seat from a peer that has not produced a valid first handshake message, and raise the global ceiling. Sixteen seats held for the full handshake window let four addresses deny every join. - Put inbound reassembly under an aggregate budget; only the outbound aggregate was bounded. - Stop heartbeats from refreshing the idle deadline in receive_transfer. - Filter IPv4 link-local discovery advertisements, matching IPv6. Relay client and trust roots: - Bound server-initiated reauthentication per connection by count and minimum interval, sized from the protocol's own cadence. - Close the policy-file TOCTOU window by identity-checking the opened file, and reject group/world-writable or foreign-owned policy files. - Stop discarding bootstrap cache-write failures, which silently disabled the anti-rollback generation floor.
162 lines
6.3 KiB
YAML
162 lines
6.3 KiB
YAML
name: P2P collaboration security boundaries
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- 'Cargo.toml'
|
|
- 'Cargo.lock'
|
|
- '.dockerignore'
|
|
- '.gitignore'
|
|
- 'rust-toolchain.toml'
|
|
- 'crates/op-collab/**'
|
|
- 'crates/op-collab-smoke/**'
|
|
- 'crates/op-collab-transport/**'
|
|
- 'crates/op-collab-relay-protocol/**'
|
|
- 'crates/op-collab-relay-client/**'
|
|
- 'crates/op-collab-relay-server/**'
|
|
- 'crates/op-collab-relay-control-plane/**'
|
|
- 'crates/op-collab-policy-file/**'
|
|
- 'crates/op-collab-relay-locator-server/**'
|
|
- 'crates/op-auth-bridge/**'
|
|
- 'crates/op-util/**'
|
|
- 'crates/op-editor-core/**'
|
|
- 'crates/op-editor-host-core/**'
|
|
- 'crates/op-editor-ui/**'
|
|
- 'crates/op-host-native/**'
|
|
- 'crates/op-host-desktop/**'
|
|
- 'crates/op-host-services/**'
|
|
- 'crates/op-i18n/**'
|
|
- 'deploy/collab-relay/**'
|
|
- 'deploy/collab-relay-edge/**'
|
|
- 'deploy/collab-relay-locator/**'
|
|
- 'deploy/collab-relay-locator-edge/**'
|
|
- 'docs/security/p2p-collaboration-threat-model.md'
|
|
- 'docs/testing/p2p-collaboration-platform-acceptance.md'
|
|
- 'tools/check-collab-security-boundaries.sh'
|
|
- 'tools/check-collab-security-boundaries.test.sh'
|
|
- 'tools/check-op-auth-prebuilt.sh'
|
|
- 'tools/check-op-auth-prebuilt.test.sh'
|
|
- 'tools/package-op-auth-prebuilt.sh'
|
|
- '.github/workflows/collab-security.yml'
|
|
- '.github/workflows/collab-platform-acceptance.yml'
|
|
push:
|
|
branches: ['**']
|
|
paths:
|
|
- 'Cargo.toml'
|
|
- 'Cargo.lock'
|
|
- '.dockerignore'
|
|
- '.gitignore'
|
|
- 'rust-toolchain.toml'
|
|
- 'crates/op-collab/**'
|
|
- 'crates/op-collab-smoke/**'
|
|
- 'crates/op-collab-transport/**'
|
|
- 'crates/op-collab-relay-protocol/**'
|
|
- 'crates/op-collab-relay-client/**'
|
|
- 'crates/op-collab-relay-server/**'
|
|
- 'crates/op-collab-relay-control-plane/**'
|
|
- 'crates/op-collab-policy-file/**'
|
|
- 'crates/op-collab-relay-locator-server/**'
|
|
- 'crates/op-auth-bridge/**'
|
|
- 'crates/op-util/**'
|
|
- 'crates/op-editor-core/**'
|
|
- 'crates/op-editor-host-core/**'
|
|
- 'crates/op-editor-ui/**'
|
|
- 'crates/op-host-native/**'
|
|
- 'crates/op-host-desktop/**'
|
|
- 'crates/op-host-services/**'
|
|
- 'crates/op-i18n/**'
|
|
- 'deploy/collab-relay/**'
|
|
- 'deploy/collab-relay-edge/**'
|
|
- 'deploy/collab-relay-locator/**'
|
|
- 'deploy/collab-relay-locator-edge/**'
|
|
- 'docs/security/p2p-collaboration-threat-model.md'
|
|
- 'docs/testing/p2p-collaboration-platform-acceptance.md'
|
|
- 'tools/check-collab-security-boundaries.sh'
|
|
- 'tools/check-collab-security-boundaries.test.sh'
|
|
- 'tools/check-op-auth-prebuilt.sh'
|
|
- 'tools/check-op-auth-prebuilt.test.sh'
|
|
- 'tools/package-op-auth-prebuilt.sh'
|
|
- '.github/workflows/collab-security.yml'
|
|
- '.github/workflows/collab-platform-acceptance.yml'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
collaboration-security:
|
|
name: Static boundaries and targeted tests
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
steps:
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
submodules: recursive
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable, pinned 2026-07-28
|
|
with:
|
|
toolchain: '1.94'
|
|
targets: wasm32-unknown-unknown
|
|
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
|
with:
|
|
shared-key: collab-security
|
|
|
|
- name: Check boundary-script syntax
|
|
run: |
|
|
bash -n tools/check-collab-security-boundaries.sh
|
|
bash -n tools/check-collab-security-boundaries.test.sh
|
|
bash -n tools/check-collab-security-boundaries-cases.sh
|
|
bash -n tools/check-collab-deployment-boundaries.sh
|
|
bash -n tools/check-op-auth-prebuilt.sh
|
|
bash -n tools/check-op-auth-prebuilt.test.sh
|
|
bash -n tools/package-op-auth-prebuilt.sh
|
|
|
|
- name: Mutation-test the boundary gate
|
|
run: |
|
|
bash tools/check-collab-security-boundaries.test.sh
|
|
bash tools/check-op-auth-prebuilt.test.sh
|
|
|
|
- name: Verify public/private and secret boundaries
|
|
run: |
|
|
bash tools/check-collab-security-boundaries.sh
|
|
bash tools/check-op-auth-prebuilt.sh
|
|
bash deploy/collab-relay-edge/validate.sh
|
|
bash deploy/collab-relay-locator/validate.sh
|
|
bash deploy/collab-relay-locator-edge/validate.sh
|
|
|
|
- name: Compile the public protocol core for wasm
|
|
run: |
|
|
cargo check --locked --target wasm32-unknown-unknown \
|
|
-p op-collab --no-default-features
|
|
cargo check --locked --target wasm32-unknown-unknown \
|
|
-p op-collab-relay-protocol --no-default-features
|
|
|
|
- name: Test protocol state machines, properties, and resource limits
|
|
run: |
|
|
cargo test --locked -p op-collab
|
|
cargo test --locked -p op-collab-transport
|
|
cargo test --locked -p op-collab-transport config::tests
|
|
cargo test --locked -p op-collab-transport frame::tests
|
|
cargo test --locked -p op-collab-relay-protocol --all-features
|
|
cargo test --locked -p op-collab-relay-client
|
|
cargo test --locked -p op-collab-relay-server
|
|
cargo test --locked -p op-collab-relay-control-plane
|
|
cargo test --locked -p op-collab-policy-file
|
|
cargo test --locked -p op-collab-relay-locator-server
|
|
|
|
- name: Test production/test trust-root isolation
|
|
run: |
|
|
cargo test --locked -p op-auth-bridge --features test-issuer \
|
|
verifies_the_frozen_go_production_root_fixture
|
|
cargo test --locked -p op-auth-bridge --features test-issuer \
|
|
production_signed_policy_path_never_falls_back_to_raw_jwks
|
|
cargo test --locked -p op-auth-bridge --features test-issuer \
|
|
--test collab_verifier
|
|
|
|
- name: Verify every committed authentication archive
|
|
run: cargo test --locked -p op-auth-bridge --test prebuilt_provenance
|
|
|
|
- name: Exercise two-process authenticated collaboration
|
|
run: |
|
|
cargo run --locked -p op-collab-smoke --features test-issuer -- run
|