The ~500-char opc1_ fragment is retired from every production surface; a relay session now shares one 10-char Crockford code (1 region char + 9 random, 45 bits). The full invite is sealed with a blake3 encrypt-then-MAC under keys derived from the code and stored on the locator control plane under an independent code_id; guests claim from exactly the region the code names, so neither the id nor the bearer ticket reaches uninvolved regions. The store tombstones exhausted claim budgets (an id can never be re-published under a burned code), caps codes per device key, and keeps per-route ingress body limits. Connect failures now distinguish invalid, expired, and relay-not-configured across all 15 locales, and the threat model documents the operator-grindable 45-bit residual risk.
536 lines
24 KiB
Bash
536 lines
24 KiB
Bash
# Mutation cases for check-collab-security-boundaries.test.sh.
|
|
# Sourced after the fixture and assertion helpers have been initialized.
|
|
|
|
new_fixture baseline
|
|
expect_pass "accepts the minimal safe collaboration boundary"
|
|
|
|
new_fixture wasm-native-dependency
|
|
: > "$fixture_root/.fake-wasm-forbidden"
|
|
expect_failure "rejects native dependencies in the wasm closure" \
|
|
"WASM boundary includes native/auth dependencies"
|
|
|
|
new_fixture credential-clone-assertion-removed
|
|
sed '/assert_not_impl_any!(OpaqueTicket: Clone);/d' \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs" \
|
|
> "$fixture_root/crates/op-collab/tests/credential_ownership.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs.next" \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs"
|
|
expect_failure "requires compile-time non-Clone credential assertions" \
|
|
"credential-bearing protocol type must remain non-Clone"
|
|
|
|
new_fixture dedicated-ticket-codec-removed
|
|
: > "$fixture_root/crates/op-collab/src/error.rs"
|
|
expect_failure "requires the dedicated credential codec failure" \
|
|
"dedicated credential codec failure"
|
|
|
|
new_fixture credential-preflight-moved-after-value
|
|
awk '
|
|
index($0, " declared_kind_rejecting_renew_ticket(bytes)?;") == 1 {
|
|
held = $0
|
|
next
|
|
}
|
|
held != "" && index($0, " let mut value = decode_json_value(bytes, limits)?;") == 1 {
|
|
print
|
|
print held
|
|
held = ""
|
|
next
|
|
}
|
|
{ print }
|
|
' \
|
|
"$fixture_root/crates/op-collab/src/codec.rs" \
|
|
> "$fixture_root/crates/op-collab/src/codec.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/src/codec.rs.next" \
|
|
"$fixture_root/crates/op-collab/src/codec.rs"
|
|
expect_failure "requires credential classification before generic Value decoding" \
|
|
"generic credential discriminator must run before JSON Value decoding"
|
|
|
|
new_fixture inbound-direction-budget-moved-after-discriminator
|
|
awk '
|
|
index($0, " enforce_inbound_envelope_limit(inbound_direction, bytes.len(), limits)?;") == 1 {
|
|
held = $0
|
|
next
|
|
}
|
|
held != "" && index($0, " declared_kind_rejecting_renew_ticket(bytes)?;") == 1 {
|
|
print
|
|
print held
|
|
held = ""
|
|
next
|
|
}
|
|
{ print }
|
|
' \
|
|
"$fixture_root/crates/op-collab/src/codec.rs" \
|
|
> "$fixture_root/crates/op-collab/src/codec.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/src/codec.rs.next" \
|
|
"$fixture_root/crates/op-collab/src/codec.rs"
|
|
expect_failure "requires trusted direction budgeting before wire discrimination" \
|
|
"trusted per-direction inbound envelope limit must run before discriminator and JSON Value decoding"
|
|
|
|
new_fixture dedicated-ticket-zeroizing-decoder-removed
|
|
sed '/Zeroizing::new(String::with_capacity/d' \
|
|
"$fixture_root/crates/op-collab/src/ticket_json.rs" \
|
|
> "$fixture_root/crates/op-collab/src/ticket_json.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/src/ticket_json.rs.next" \
|
|
"$fixture_root/crates/op-collab/src/ticket_json.rs"
|
|
expect_failure "requires direct zeroizing ticket string decoding" \
|
|
"direct zeroizing ticket string decoder"
|
|
|
|
new_fixture dedicated-ticket-ordinary-string-deserializer
|
|
printf '%s\n' \
|
|
'fn bad() { let _ = String::deserialize(deserializer); }' \
|
|
>> "$fixture_root/crates/op-collab/src/ticket_json.rs"
|
|
expect_failure "rejects ordinary String deserialization in the ticket decoder" \
|
|
"dedicated ticket decoder must not materialize ordinary strings or Values"
|
|
|
|
new_fixture opaque-ticket-generic-string-deserializer
|
|
printf '%s\n' \
|
|
'fn bad() { let _ = String::deserialize(deserializer); }' \
|
|
>> "$fixture_root/crates/op-collab/src/protocol.rs"
|
|
expect_failure "rejects ordinary String deserialization in OpaqueTicket" \
|
|
"OpaqueTicket must not deserialize through an ordinary String"
|
|
|
|
new_fixture generic-renewal-deserialize-assertion-removed
|
|
sed '/assert_not_impl_any!(RenewTicket: serde::de::DeserializeOwned);/d' \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs" \
|
|
> "$fixture_root/crates/op-collab/tests/credential_ownership.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs.next" \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs"
|
|
expect_failure "requires the generic renewal Deserialize compile-time boundary" \
|
|
"credential-bearing protocol type must not implement generic Deserialize"
|
|
|
|
new_fixture derived-collab-message-deserializer
|
|
printf '%s\n' \
|
|
'#[derive(PartialEq, Serialize, Deserialize)]' \
|
|
>> "$fixture_root/crates/op-collab/src/protocol.rs"
|
|
expect_failure "rejects derived adjacent-tag CollabMessage deserialization" \
|
|
"CollabMessage must not use derived Deserialize"
|
|
|
|
new_fixture direct-serde-renewal-serialization-regression-removed
|
|
sed '/direct_serde_renewal_serialization_is_fail_closed/d' \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs" \
|
|
> "$fixture_root/crates/op-collab/tests/credential_ownership.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs.next" \
|
|
"$fixture_root/crates/op-collab/tests/credential_ownership.rs"
|
|
expect_failure "requires the direct serde renewal serialization regression" \
|
|
"direct serde credential serialization rejection test"
|
|
|
|
new_fixture mislabeled-renewal-regression-removed
|
|
: > "$fixture_root/crates/op-collab-transport/src/frame.rs"
|
|
expect_failure "requires the mislabeled renewal transport regression" \
|
|
"mislabeled credential transport regression test"
|
|
|
|
new_fixture credential-transport-workflow-test-removed
|
|
sed '/cargo test --locked -p op-collab-transport frame::tests/d' \
|
|
"$fixture_root/.github/workflows/collab-security.yml" \
|
|
> "$fixture_root/.github/workflows/collab-security.yml.next"
|
|
mv \
|
|
"$fixture_root/.github/workflows/collab-security.yml.next" \
|
|
"$fixture_root/.github/workflows/collab-security.yml"
|
|
expect_failure "requires the credential transport codec workflow test" \
|
|
"credential transport codec workflow test"
|
|
|
|
new_fixture desktop-renewal-vec-copy
|
|
printf '%s\n' \
|
|
'fn bad(ticket: Ticket) { let _ = ticket.expose().as_bytes().to_vec(); }' \
|
|
>> "$fixture_root/crates/op-host-desktop/src/collab_runtime/types.rs"
|
|
expect_failure "rejects ordinary Vec copies in desktop renewal commands" \
|
|
"desktop renewal commands must move OpaqueTicket"
|
|
|
|
new_fixture non-mit-crate
|
|
cat > "$fixture_root/crates/op-collab-transport/Cargo.toml" <<'EOF'
|
|
[package]
|
|
name = "op-collab-transport"
|
|
version = "0.0.0"
|
|
license = "Apache-2.0"
|
|
EOF
|
|
expect_failure "rejects a non-MIT collaboration crate" \
|
|
"must inherit or declare the MIT license"
|
|
|
|
new_fixture deterministic-production-seed
|
|
printf '%s\n' \
|
|
'const PRODUCTION_SIGNING_SEED: [u8; 32] = [9; 32];' \
|
|
>> "$fixture_root/crates/op-collab/src/protocol.rs"
|
|
expect_failure "rejects deterministic key material in production source" \
|
|
"deterministic signing/key seed leaked"
|
|
|
|
new_fixture deterministic-production-seed-after-test-module
|
|
printf '%s\n' \
|
|
'const PRODUCTION_SIGNING_SEED: [u8; 32] = [9; 32];' \
|
|
>> "$fixture_root/crates/op-auth-bridge/src/collab_verifier.rs"
|
|
expect_failure "scans production items after an inline cfg(test) module" \
|
|
"deterministic signing/key seed leaked"
|
|
|
|
new_fixture deterministic-external-test-without-cfg
|
|
sed '/#!\[cfg(test)\]/d' \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache_cancellation_tests.rs" \
|
|
> "$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache_cancellation_tests.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache_cancellation_tests.rs.next" \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache_cancellation_tests.rs"
|
|
expect_failure "requires an explicit cfg(test) boundary for external unit tests" \
|
|
"deterministic signing/key seed leaked"
|
|
|
|
new_fixture deterministic-path-test-without-parent-cfg
|
|
sed '/#\[cfg(test)\]/d' \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache.rs" \
|
|
> "$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache.rs.next" \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_jwks_cache.rs"
|
|
expect_failure "requires cfg(test) on path-based external unit-test modules" \
|
|
"deterministic signing/key seed leaked"
|
|
|
|
new_fixture production-root-fixture-regression-removed
|
|
sed '/verifies_the_frozen_go_production_root_fixture/d' \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_union_policy_tests.rs" \
|
|
> "$fixture_root/crates/op-auth-bridge/src/collab_union_policy_tests.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_union_policy_tests.rs.next" \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_union_policy_tests.rs"
|
|
expect_failure "requires the split production root fixture regression" \
|
|
"production trust-root fixture regression test"
|
|
|
|
new_fixture production-policy-fail-closed-regression-removed
|
|
sed '/production_signed_policy_path_never_falls_back_to_raw_jwks/d' \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_verifier.rs" \
|
|
> "$fixture_root/crates/op-auth-bridge/src/collab_verifier.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_verifier.rs.next" \
|
|
"$fixture_root/crates/op-auth-bridge/src/collab_verifier.rs"
|
|
expect_failure "requires the split production policy fail-closed regression" \
|
|
"production/test issuer isolation regression test"
|
|
|
|
new_fixture sensitive-key-file
|
|
: > "$fixture_root/crates/op-collab-transport/peer.key"
|
|
expect_failure "rejects key-shaped repository fixtures" \
|
|
"sensitive key/token-shaped files are forbidden"
|
|
|
|
new_fixture sealed-relay-key-json
|
|
: > "$fixture_root/deploy/collab-relay/relay-x25519-keys.json"
|
|
expect_failure "rejects sealed Relay private-key JSON in the repository" \
|
|
"sensitive key/token-shaped files are forbidden"
|
|
|
|
new_fixture relay-key-dockerignore-removed
|
|
sed '/relay-x25519-keys/d' \
|
|
"$fixture_root/.dockerignore" \
|
|
> "$fixture_root/.dockerignore.next"
|
|
mv "$fixture_root/.dockerignore.next" "$fixture_root/.dockerignore"
|
|
expect_failure "requires private Relay key JSON exclusion from Docker builds" \
|
|
"Docker build-context private-key exclusion"
|
|
|
|
new_fixture relay-key-gitignore-removed
|
|
sed '/relay-x25519-keys/d' \
|
|
"$fixture_root/.gitignore" \
|
|
> "$fixture_root/.gitignore.next"
|
|
mv "$fixture_root/.gitignore.next" "$fixture_root/.gitignore"
|
|
expect_failure "requires private Relay key JSON exclusion from Git staging" \
|
|
"Git private-key exclusion"
|
|
|
|
new_fixture compact-token
|
|
mkdir -p "$fixture_root/crates/op-collab/fixtures"
|
|
printf '%s\n' \
|
|
'"abcdefghijklmnop.qrstuvwxyzABCDEF.abcdefghijklmnopqrstuvwxyzABCDEF0123456789"' \
|
|
> "$fixture_root/crates/op-collab/fixtures/captured-ticket.txt"
|
|
expect_failure "rejects compact bearer tokens in non-source fixtures" \
|
|
"high-signal credential/private-key material detected"
|
|
|
|
new_fixture smoke-compact-token
|
|
printf '%s\n' \
|
|
'"abcdefghijklmnop.qrstuvwxyzABCDEF.abcdefghijklmnopqrstuvwxyzABCDEF0123456789"' \
|
|
> "$fixture_root/crates/op-collab-smoke/captured-ticket.txt"
|
|
expect_failure "rejects compact bearer tokens in the smoke crate" \
|
|
"high-signal credential/private-key material detected"
|
|
|
|
new_fixture desktop-sensitive-file
|
|
: > "$fixture_root/crates/op-host-desktop/src/collab_runtime/runtime-ticket.token"
|
|
expect_failure "rejects sensitive files in desktop collaboration integration" \
|
|
"sensitive key/token-shaped files are forbidden"
|
|
|
|
new_fixture avatar-redirect-limit-removed
|
|
sed '/MAX_REDIRECTS/d' \
|
|
"$fixture_root/crates/op-host-services/src/profile_avatar_fetch.rs" \
|
|
> "$fixture_root/crates/op-host-services/src/profile_avatar_fetch.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-host-services/src/profile_avatar_fetch.rs.next" \
|
|
"$fixture_root/crates/op-host-services/src/profile_avatar_fetch.rs"
|
|
expect_failure "requires the shared avatar redirect limit" \
|
|
"bounded collaboration avatar fetch"
|
|
|
|
new_fixture desktop-public-avatar-delegation-removed
|
|
sed '/fetch_profile_avatar_blocking(request.url())/d' \
|
|
"$fixture_root/crates/op-host-desktop/src/collab_avatar_host.rs" \
|
|
> "$fixture_root/crates/op-host-desktop/src/collab_avatar_host.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-host-desktop/src/collab_avatar_host.rs.next" \
|
|
"$fixture_root/crates/op-host-desktop/src/collab_avatar_host.rs"
|
|
expect_failure "requires public-only desktop collaboration avatar delegation" \
|
|
"desktop avatar security-policy delegation"
|
|
|
|
new_fixture avatar-proxy-bypass-removed
|
|
: > "$fixture_root/crates/op-host-services/src/provider_dial.rs"
|
|
expect_failure "requires proxy-free pinned avatar dialing" \
|
|
"public HTTPS proxy bypass prevention"
|
|
|
|
new_fixture auth-artifact-integrity-removed
|
|
: > "$fixture_root/crates/op-auth-bridge/build.rs"
|
|
expect_failure "requires authentication artifact integrity verification" \
|
|
"authentication artifact integrity gate"
|
|
|
|
new_fixture auth-artifact-signature-removed
|
|
: > "$fixture_root/crates/op-auth-bridge/prebuilt_provenance.rs"
|
|
expect_failure "requires authentication artifact signature verification" \
|
|
"authentication artifact signature verification"
|
|
|
|
new_fixture auth-matrix-test-removed
|
|
sed \
|
|
'/cargo test --locked -p op-auth-bridge --test prebuilt_provenance/d' \
|
|
"$fixture_root/.github/workflows/collab-security.yml" \
|
|
> "$fixture_root/.github/workflows/collab-security.yml.next"
|
|
mv \
|
|
"$fixture_root/.github/workflows/collab-security.yml.next" \
|
|
"$fixture_root/.github/workflows/collab-security.yml"
|
|
expect_failure "requires the committed authentication matrix test" \
|
|
"committed authentication matrix test"
|
|
|
|
new_fixture integration-line-cap
|
|
awk 'BEGIN { for (line = 1; line <= 801; line++) print "// integration line" }' \
|
|
> "$fixture_root/crates/op-editor-host-core/src/collab/oversized.rs"
|
|
expect_failure "enforces the line cap across collaboration integration source" \
|
|
"has 801 lines; maximum is 800"
|
|
|
|
new_fixture missing-workflow-trigger
|
|
awk '
|
|
!removed && index($0, "crates/op-host-desktop/**") {
|
|
removed = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' \
|
|
"$fixture_root/.github/workflows/collab-security.yml" \
|
|
> "$fixture_root/.github/workflows/collab-security.yml.next"
|
|
mv \
|
|
"$fixture_root/.github/workflows/collab-security.yml.next" \
|
|
"$fixture_root/.github/workflows/collab-security.yml"
|
|
expect_failure "rejects removal of either integration workflow trigger" \
|
|
"collaboration security workflow path trigger"
|
|
|
|
new_fixture relay-edge-mtls-verification-removed
|
|
sed '/proxy_ssl_verify on;/d' \
|
|
"$fixture_root/deploy/collab-relay-edge/global-nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay-edge/global-nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-edge/global-nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-edge/global-nginx.conf"
|
|
expect_failure "requires Global-to-CN outer-mTLS server verification" \
|
|
"Global-to-CN inner-TLS passthrough boundary"
|
|
|
|
new_fixture relay-edge-client-crl-removed
|
|
awk '!index($0, "ssl_crl /run/secrets/global-edge-client-crl.pem;")' \
|
|
"$fixture_root/deploy/collab-relay-edge/cn-federation-nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay-edge/cn-federation-nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-edge/cn-federation-nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-edge/cn-federation-nginx.conf"
|
|
expect_failure "requires revocation checking for Global edge client certificates" \
|
|
"CN outer-mTLS federation boundary"
|
|
|
|
new_fixture relay-edge-crl-production-validation-removed
|
|
sed '/OPENPENCIL_RELAY_EDGE_VALIDATION_MODE=production/d' \
|
|
"$fixture_root/deploy/collab-relay-edge/rotate-cn-crl.sh" \
|
|
> "$fixture_root/deploy/collab-relay-edge/rotate-cn-crl.sh.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-edge/rotate-cn-crl.sh.next" \
|
|
"$fixture_root/deploy/collab-relay-edge/rotate-cn-crl.sh"
|
|
expect_failure "requires production validation before Relay CRL activation" \
|
|
"relay federation CRL activation boundary"
|
|
|
|
new_fixture relay-edge-source-rate-removed
|
|
awk '!index($0, "limit rate over 60/minute burst 20 packets")' \
|
|
"$fixture_root/deploy/collab-relay-edge/install-global-new-connection-rate.sh" \
|
|
> "$fixture_root/deploy/collab-relay-edge/install-global-new-connection-rate.sh.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-edge/install-global-new-connection-rate.sh.next" \
|
|
"$fixture_root/deploy/collab-relay-edge/install-global-new-connection-rate.sh"
|
|
expect_failure "requires the overseas relay per-source connection-rate gate" \
|
|
"overseas relay per-source connection-rate boundary"
|
|
|
|
new_fixture relay-edge-auto-restart-enabled
|
|
sed 's/restart: "no"/restart: unless-stopped/' \
|
|
"$fixture_root/deploy/collab-relay-edge/compose.global.yaml" \
|
|
> "$fixture_root/deploy/collab-relay-edge/compose.global.yaml.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-edge/compose.global.yaml.next" \
|
|
"$fixture_root/deploy/collab-relay-edge/compose.global.yaml"
|
|
expect_failure "requires supervised relay startup after the nftables gate" \
|
|
"overseas relay supervised fixed-port boundary"
|
|
|
|
new_fixture relay-edge-verifier-not-executable
|
|
chmod -x "$fixture_root/deploy/collab-relay-edge/verify-rate-rules.py"
|
|
expect_failure "requires executable deployment gate helpers" \
|
|
"deployment gate executable boundary"
|
|
|
|
new_fixture relay-bearer-header-buffer-removed
|
|
awk '
|
|
!removed && /client_header_buffer_size 64k;/ {
|
|
removed = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay/nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf"
|
|
expect_failure "requires 48 KiB bearer buffers on both relay ingresses" \
|
|
"48 KiB relay bearer ingress header boundary"
|
|
|
|
new_fixture cn-federation-aggregate-limit-removed
|
|
sed '/limit_conn relay_federation_connections 512;/d' \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay/nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay/nginx.conf"
|
|
expect_failure "keeps the trusted federation backhaul off the public per-IP ceiling" \
|
|
"CN WSS/federation ingress boundary"
|
|
|
|
new_fixture locator-hsm-boundary-removed
|
|
sed '/OPENPENCIL_COLLAB_LOCATOR_HSM_SOCKET:/d' \
|
|
"$fixture_root/deploy/collab-relay-locator/compose.yaml" \
|
|
> "$fixture_root/deploy/collab-relay-locator/compose.yaml.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator/compose.yaml.next" \
|
|
"$fixture_root/deploy/collab-relay-locator/compose.yaml"
|
|
expect_failure "requires the external locator HSM socket boundary" \
|
|
"locator production container boundary"
|
|
|
|
new_fixture locator-per-source-limit-removed
|
|
sed '/limit_req_zone.*openpencil_locator_per_source/d' \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-http-limits.conf" \
|
|
> "$fixture_root/deploy/collab-relay-locator/nginx-http-limits.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-http-limits.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-http-limits.conf"
|
|
expect_failure "requires per-source locator ingress throttling" \
|
|
"locator per-source ingress boundary"
|
|
|
|
new_fixture locator-pairing-route-removed
|
|
awk '!index($0, "location = /v1/pairing-code {")' \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-location.conf" \
|
|
> "$fixture_root/deploy/collab-relay-locator/nginx-location.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-location.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-locator/nginx-location.conf"
|
|
expect_failure "requires the pairing publish route at the locator ingress" \
|
|
"locator exact-route ingress boundary"
|
|
|
|
new_fixture locator-edge-crl-secure-ownership-removed
|
|
awk '!index($0, "CRL/CA files must be root:101 mode 0440")' \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/rotate-cn-crl.sh" \
|
|
> "$fixture_root/deploy/collab-relay-locator-edge/rotate-cn-crl.sh.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/rotate-cn-crl.sh.next" \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/rotate-cn-crl.sh"
|
|
expect_failure "requires secure ownership before locator CRL activation" \
|
|
"locator federation CRL activation boundary"
|
|
|
|
new_fixture mutable-relay-container-base
|
|
awk '
|
|
/^FROM rust:/ {
|
|
print "FROM rust:1.94-bookworm AS build"
|
|
next
|
|
}
|
|
{ print }
|
|
' \
|
|
"$fixture_root/deploy/collab-relay/Dockerfile" \
|
|
> "$fixture_root/deploy/collab-relay/Dockerfile.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay/Dockerfile.next" \
|
|
"$fixture_root/deploy/collab-relay/Dockerfile"
|
|
expect_failure "requires immutable digests for relay container base images" \
|
|
"relay container base images must use reviewed immutable SHA-256 digests"
|
|
|
|
new_fixture locator-edge-mtls-verification-removed
|
|
sed '/proxy_ssl_verify on;/d' \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/global-nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay-locator-edge/global-nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/global-nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/global-nginx.conf"
|
|
expect_failure "requires outer-mTLS verification on the overseas locator ingress" \
|
|
"overseas locator inner-TLS passthrough boundary"
|
|
|
|
new_fixture locator-edge-exact-host-removed
|
|
awk '!index($0, "if ($http_host != locator.example.cn) {")' \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf"
|
|
expect_failure "requires an exact inner HTTPS Host at the CN locator terminator" \
|
|
"CN locator exact inner-HTTPS boundary"
|
|
|
|
new_fixture locator-edge-pairing-claim-route-removed
|
|
awk '!index($0, "location = /v1/pairing-code/claim {")' \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf" \
|
|
> "$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf.next" \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/cn-locator-https-nginx.conf"
|
|
expect_failure "requires the pairing claim route at the CN locator terminator" \
|
|
"CN locator exact inner-HTTPS boundary"
|
|
|
|
new_fixture locator-edge-source-rate-removed
|
|
awk '!index($0, "limit rate over 60/minute burst 20 packets")' \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/install-global-new-connection-rate.sh" \
|
|
> "$fixture_root/deploy/collab-relay-locator-edge/install-global-new-connection-rate.sh.next"
|
|
mv \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/install-global-new-connection-rate.sh.next" \
|
|
"$fixture_root/deploy/collab-relay-locator-edge/install-global-new-connection-rate.sh"
|
|
expect_failure "requires the overseas locator per-source connection-rate gate" \
|
|
"overseas locator per-source connection-rate boundary"
|
|
|
|
new_fixture missing-hard-limit
|
|
awk '!/MAX_OPS_PER_TXN/' \
|
|
"$fixture_root/crates/op-collab/src/protocol.rs" \
|
|
> "$fixture_root/crates/op-collab/src/protocol.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab/src/protocol.rs.next" \
|
|
"$fixture_root/crates/op-collab/src/protocol.rs"
|
|
expect_failure "rejects removal of a protocol hard-limit anchor" \
|
|
"protocol hard limit"
|
|
|
|
new_fixture public-transport-queue
|
|
sed \
|
|
's/pub(crate) struct BoundedTransferQueue/pub struct BoundedTransferQueue/' \
|
|
"$fixture_root/crates/op-collab-transport/src/queue.rs" \
|
|
> "$fixture_root/crates/op-collab-transport/src/queue.rs.next"
|
|
mv \
|
|
"$fixture_root/crates/op-collab-transport/src/queue.rs.next" \
|
|
"$fixture_root/crates/op-collab-transport/src/queue.rs"
|
|
expect_failure "rejects exposing the transport queue implementation" \
|
|
"bounded queue/rate type"
|
|
|
|
new_fixture untyped-boundary-error
|
|
printf '%s\n' \
|
|
'fn bad_boundary() -> Result<(), String> { Ok(()) }' \
|
|
>> "$fixture_root/crates/op-collab/src/protocol.rs"
|
|
expect_failure "rejects untyped public boundary errors" \
|
|
"untyped Result<_, String/&str>"
|
|
|
|
if [[ "$failure_count" -ne 0 ]]; then
|
|
printf '%s\n' \
|
|
"check-collab-security-boundaries.test.sh: $failure_count mutation test(s) failed." \
|
|
>&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s\n' \
|
|
"check-collab-security-boundaries.test.sh: all $test_index mutation tests pass."
|