Skip to content

Security: sentrybottale/OwnTransit

SECURITY.md

OwnTransit security policy

1.0.5: relay admission and publication hardening

Managed routes overwrite OwnTransit-Peer-IP with the original TCP peer on the private proxy-to-relay HTTP hop. The locally selected relay ingress admits that metadata only from loopback, or the packaged container's private bridge. One bounded canonical IP selects an availability bucket; duplicate values, address lists, ports and zones are rejected. Ordinary forwarding headers remain ignored. The header supplies no TLS, route, endpoint, enrollment or SSH authority. A malicious proxy can still lie or deny service, as the endpoint threat model allows.

Existing routes without the new metadata retain the old shared TCP-peer bucket until local Relay setup reconciles the selected route. That reconciliation must validate the provider configuration and retain protected rollback material. No endpoint state or authenticated carrier input changes. See relay upgrade and cache behavior.

Unapproved advertisements and offers share a bounded, evictable pending cache with a two-minute default lifetime. Approved or observed receivers with the exact persisted admission root use separate protected capacity. Public self-signatures cannot claim that capacity. Cached advertisements are never retained past their signed expiry. Public floods may disrupt pending setup, but cannot leave the publication cache full for a day or evict an approved receiver's entry.

These are defenses for an honestly operated Relay. They do not certify universal availability or change either independent TLS boundary or the fixed SSH target.

1.0.1: network retry policy

Network loss, DNS/connect failure and HTTP admission throttling remain transient unavailability. They never create, clear or replace an endpoint identity, alarm, pin, authorization floor or relay origin. All reconnects perform the existing fresh authentication before the fixed SSH dial. Failed active sessions close; they are never resumed by replaying bytes into a replacement carrier.

Independent worker loops use bounded exponential backoff with scheduling jitter. An HTTP 429 response may supply one Retry-After value of at most 64 bytes; integer seconds or an HTTP date are clamped locally to 5–30 seconds. Missing, ambiguous or invalid hints use five seconds. Only the fixed error category and bounded duration survive parsing: no response body, raw error or header text enters diagnostics. The malicious Relay still has denial-of-service capability; its retry hint grants no authentication authority and cannot indefinitely park a local worker. Cancellation and policy-alarm watchers interrupt sleeps.

Target notices are fixed text, shared across its loops and limited to one per minute. Backoff is per loop, not a host-wide quota across independent processes or tunnels. Reverse-proxy protections remain necessary. Older downloads do not include these changes, and independent recovery remains necessary for host/process failures beyond transport retry.

0.8 pending-connection recovery

Runtime endpoint connections have a local 45-second guard after the WebSocket dial, covering the preface, outer mTLS and the Relay READY response. The dial retains its existing DNS/connect/HTTP time bounds. A silent or trickling peer cannot park the Target's runtime-accept loop indefinitely. The guard aborts the underlying transport; timeout remains transient unavailability, not an alarm or permission to change keys. Its timer must be stopped successfully and its deadline cleared before a promoted stream is handed to inner TLS. It therefore adds no short lifetime limit to established SSH streams. Existing session, certificate-expiry and authorization-lease bounds remain independent.

This changes no authenticated wire fields or endpoint trust. A malicious Relay can still deny service; retry is recovery from a stalled attempt, not a promise of availability. Target timeout notices are fixed text, rate-limited to at most one per minute, and contain no peer errors, tokens or keys.

An existing exact /connects/enrollment location cannot override the distinct exact /connects URI. The Relay manager now recognizes that legacy sibling without modifying it. Other ambiguous/prefix/regex carrier matches, duplicate carrier locations and wrong-instance upstreams remain rejected.

Current 1.0 product boundary

1.0 retains the 0.8 runtime, local Client, Relay and Target roles and the canonical owntransit-client, owntransit-relay and owntransit-target commands. Their setup menus expose only local role operations. Earlier public names, preview aliases and the pair command prefix are not retained as CLI shims. Historical sections below describe their named release, not additional certification of product 1.0. The 1.x compatibility contract is documented in COMPATIBILITY.md. Independent assessment and universal availability are not claimed.

Tight reverse-proxy upgrade quotas can cause HTTP 429 and prevent reconnection; the existing retry cadence does not adapt to that response and some failures are reported only as a generic transport error. This is a disclosed operational limitation, not fixed by the 1.0 version change. A Relay cannot administer a Target through a broken tunnel; retain independent maintenance access.

The private Target code remains available only to its local authority owner and the independently chosen Client. The Relay stores public planning and admission metadata only. Neither a menu name, public Target ID, relay approval nor a relay observation supplies endpoint trust or proves a working tunnel. Only the Client's actual authenticated carrier and fixed SSH-socket check may report TUNNEL READY. Both TLS 1.3 mTLS boundaries, exact endpoint authorization, the fixed tcp4 127.0.0.1:22 destination and OpenSSH ownership are unchanged.

Endpoint removal uses a separate private owntransit.local-removal.v1 record. Its durable denial applies to new admissions and running policy watchers before shutdown is acknowledged. Removal retains keys and policy generations; it does not invoke the terminal alarm or peer revocation. Interrupted removal remains denied until retried. Explicit restore waits for worker shutdown, then checks the retained alarm and Target authority under the local policy mutation boundary before committing restoration. A committed alarm cannot be cleared by restore. Target service operations validate the exact owned unit, reject overrides and coordinate with package maintenance. Shared software and other tunnels remain outside the selected removal.

An honest Relay persists removal of the selected admission and closes its tracked carriers. This is an availability operation, not endpoint revocation: the threat model allows a compromised Relay to ignore it. Use an endpoint's Killswitch for its terminal authorization denial. An endpoint alarm still cannot guarantee immediate peer cutoff across a malicious Relay or stop SSH-started jobs; the existing authorization-lease bound and host-recovery responsibilities remain in force. No menu or installer edits SSH keys, accounts or configuration.

0.6.1 local code recovery and readiness

New one-code setup retains a mode-0600 cache only under the receiver's private authority directory. Explicit owner-only retrieval verifies the exact live attempt, code digest, advertisement, origin, expiry, policy and public offer. No worker RPC or relay operation can reveal the code. Claim/retirement denial remains authoritative even if a stale cache survives deletion or is restored. Older uncached codes require explicit replacement, never a guessed recovery. See local cache and rollback semantics.

Ordinary setup retries retain identities. --replace explicitly selects new receiver identities and reapproval; paired replacements still require consent. Public receiver IDs are bounded local lookup hints, not new trust authority. Client readiness uses the existing full carrier handshake and fixed SSH-dial acknowledgement. No cached state, relay approval, or suppressed probe failure can report end-to-end readiness. SSH authentication remains operator-owned.

0.6.0 relay migration

Unqualified setup selects only the operator-entered URL's protected local instance. Explicit instance selection remains restrictive. Recognized manual relay migration requires exact unit/container/state/port/confinement ownership, the matching existing website route and public identity, and explicit local confirmation revalidated before mutation. The v2 binding permits only a derived, validated historical data root, not arbitrary paths or shared/default state. Prepared/committed journal phases cover reservation replacement, old-service restart guards, managed cutover, exact cleanup and recovery. No secrets are copied or reset and unrelated relays/sites are not cleanup targets. Other management cannot bypass an unfinished migration. Full contract.

An admin-only, authenticated HTTPS 403 may produce a distinctly reported local-verification result after exact local route, image, confinement, identity and key-digest checks. It is not public reachability proof and never fabricates relay information. Migration consent discloses that limitation; endpoint setup must still verify the public path from an allowed network. Other transport, certificate, protocol or identity failures remain fatal. No endpoint dialer, access-control rule, SSH policy or cryptographic check is weakened.

0.5.0 one-code setup

The short private code retains 256-bit randomness. An independent full HMAC authenticates the receiver's exact signed advertisement before its recipient key is used or a secret-bearing request is sent. The VPS approval path retains local admission control but no longer makes users copy its public routing blob. Versioned offer operations remain bounded by relay pre-auth limits and expiry; public token restoration cannot mint or extend admission. There is no automatic fallback, origin switch, trust reset or alarm recovery on setup/network failure. See the protocol and downgrade analysis.

0.4.0 managed relay instance isolation

Instance names select only local relay deployment resources. They do not select an SSH target, authorize a peer, replace a pairing's origin, or add relay switching. The original default relay retains its state paths, keys and port 9087. Named instances require bounded lowercase labels, distinct canonical URLs and reserved loopback host ports. Their protected local binding records precede activation; ports and URLs are not freed by failed setup or non-purging removal. Registration can explicitly select the exact protected local instance by URL instead of name. Unknown/unavailable URLs fail; no network discovery, relay fallback or endpoint-origin update is performed by that lookup.

Named setup never adopts a discovered legacy/default relay. Container ownership, cleanup hooks, saved configuration and upgrade journals bind the exact instance, URL, port, state mount, image and unit. Old local schemas apply only to default. Only the selected HTTPS site's exact route may be added; an existing route to a different instance is a conflict, including aliases of one virtual host.

A host-wide manager lock serializes shared website and instance operations. Package mutation holds an exclusive coordination lock; normal management shares it. Package-removal helpers validate their inherited descriptor's protected inode and make it close-on-exec without unlocking the parent's reference. Systemd cleanup hooks avoid recursive lock acquisition and act only on exact stopped managed containers. Removing one instance retains shared software; whole-role removal validates all recognized instances before stopping them.

These are operational isolation properties on a shared VPS, not a defense against its root administrator or shared resource exhaustion. The entire relay host remains malicious in the endpoint threat model. Inner authentication, end-to-end encryption, fixed SSH destination and alarm rules are unchanged.

0.3.0 named tunnel isolation

Named tunnels reuse the one-to-one pairing profile. Multiple independently authorized receiver instances may run beside the same SSH server, all with the same build-fixed loopback target. They do not share issuer or client keys. The relay sees independent opaque receiver/route IDs; a local name grants no trust.

Names are bounded lowercase path components; traversal, shell/systemd tokens and ambiguous --tunnel/--state selection are rejected. default retains the original state path. Named state roots are private and reject symlink traversal. List/status output describes local pairing state, not peer availability.

Receiver setup derives an instance unit from the installed root-protected template and refuses a modified or overridden unit. Package changes take an exclusive maintenance lock; setup/restart shares it. Named units keep the same confinement, outbound-only worker and fixed SSH dial. Package removal stops only recognized units and retains all pairing/alarm state. Root compromise of an endpoint still compromises that host; per-tunnel state is not a sandbox against a hostile host administrator.

0.2.0 installation and diagnostic scope

The receiver-owned 0.2.0 release retains its existing signed capsule format and key. Exact-version bootstraps reject old or malformed inventories; the Mac bootstrap additionally authenticates its selected archive before installing an unprivileged per-user client. Initial script delivery still trusts GitHub HTTPS. No Apple signing subscription is required. An installer does not edit SSH keys, configuration or accounts, and non-purging uninstall retains pairing state.

Normal aliases never overwrite an unrelated legacy command. Linux package removal validates owned package bytes before removing only the selected local role. Connector removal refuses modified units/overrides. Managed relay removal validates saved ownership, stops/disables the unit and removes only the stopped managed container; it retains its disabled unit configuration, relay keys, website route and cached rollback images for explicit reinstall/setup.

Diagnostic messages use fixed local error classes, never raw causes or relay strings. Unavailability is not a security alarm. Fast tests shorten fixture-only timers; production authorization leases, clock checks, pending/session limits and terminal alarm semantics are unchanged. Extended soak and independent security assessment are not claimed for this bounded release.

Concurrent client startups wait only on the known busy local operation lock, inside the existing opening deadline and policy watcher. Ownership/permission errors are not retried. Cancellation or a local alarm still terminates the wait.

0.1.8 active-carrier lifetime fix

The relay's pending-receiver timeout previously ended the receiver's HTTP handler even after a client claimed that leg, aborting active carriers within the pending window. The fix makes expiry and promotion a single mutex-protected ownership decision. Unclaimed legs still expire and release capacity; claimed handlers wait for exchange completion or relay shutdown. Their socket deadlines still enforce the earlier token expiry and applicable session-lifetime limit. Pairing exchanges retain their own short deadline. No authentication, quota, endpoint lease, clock check or security-alarm rule is relaxed.

0.1.5 candidate hardening

The receiver-owned relay bounds its initial frame and outer admission handshake with an absolute deadline (10 seconds by default). Public operation writes are bounded too; error replies have a one-second write deadline and rejected WebSockets are aborted promptly. Admitted pairing/runtime operations move to their own bounded lifetimes, not a short deadline on an established SSH session.

Before authentication, concurrency is capped at 32 globally and eight per actual TCP peer. Token buckets bound accepted connection creation to 64/second with a burst of 128 globally, and 16/second with a burst of 64 per peer. Peer bookkeeping is capped at 256 entries and idle entries expire. Forwarding headers are not trusted: clients behind a reverse proxy/NAT share its TCP-peer bucket. These are resource controls for an honestly operated relay, not volumetric network flood protection or a promise of availability against a compromised relay.

Both receiver-owned WebSocket adapters restore their message limit after websocket.NetConn construction, before reads start, and split larger local writes. Whole and fragmented oversized-message tests use the actual adapter. These changes preserve independent TLS/SSH authentication and existing wire profiles; no new protocol, endpoint key or trust-reset operation is introduced.

Managed relay upgrades validate the exact saved unit, reject custom drop-ins, retain keys and website routing, and verify the running image as well as the public protocol response. A root-private journal allows restoration after failure/interruption; it never carries endpoint issuer material. Upgrades do not invoke the website route editor for an already managed installation.

Managed relay setup

Managed service pre/post hooks clean up only a stopped container whose name, image, executable and state bind match the managed relay. Cleanup never uses force removal and never deletes volumes or images. Upgrade bridges also handle stopped containers left by older units. Rollback retains the exact previous unit template in a v2 local journal; recovery still accepts earlier v1 journals.

The explicit relay setup command is local administration. It accepts the public URL, selects a recognized site configuration, verifies container ownership before replacement, and tests the actual v2 WebSocket endpoint against the local relay identity. That is routing verification, not endpoint enrollment authority.

The managed container runs as UID/GID 65532 with no capabilities, no privilege gain, a read-only root filesystem and a loopback-only host port. Docker or Podman may be invoked by the root setup/service process; the relay itself is non-root. No SSH account is created. Private state ownership and local control-socket peer credentials must match the relay UID even when it is unprivileged.

Existing correct routing is reused. Recognized Nginx, Apache and Caddy sites may receive one selected-site route after a private backup and configuration check. Failed public verification restores the previous relay and modified site; errors during rollback are reported. Custom configurations and unrelated port owners are not silently replaced. The setup stores no endpoint issuer material.

Receiver-owned pairing development profile

The pair commands implement a separately selected 0.1.1 development profile; they do not change the published 0.1.0 enrollment rules below. See RECEIVER_PAIRING.md and PAIRING_INSTALL.md for its authority and testing boundaries. An independently transferred 256-bit one-use receiver code binds the exact advertisement and intended receiver. Public IDs and relay codes cannot issue inner credentials. Code possession authorizes a device, not a human identity.

Receiver issuance happens in a root-owned local process with a bounded pipe interface. Its separate Linux network worker drops to UID/GID 65534, clears supplementary groups, disables dumps and gaining privileges, and cannot read the root-private issuer/signing/age store. Client operational keys are generated on the client. Both TLS 1.3 mTLS boundaries remain independent; inner exact names, SPKIs, ALPN and fresh exporter-bound leases gate the fixed SSH dial. Relay keys cannot forge those checks. Root/endpoint compromise and whole-state rollback or cloning remain outside this profile's guarantee.

Explicit local security alarms are terminal and survive restart. They cannot be cleared to revive old identities; recovery requires a deliberate fresh pairing. Ordinary network, relay or authentication failure is transient unavailability, not a permanent alarm. A successful alarm acknowledges persistence and closure of the local active-worker gate. Peer shutdown can be delayed by a malicious relay until the remaining authorization lease expires. It is not a guarantee of simultaneous shutdown, termination of SSH-started jobs or erasure of bytes already delivered. Source integration tests are not an independent security assessment or signed release qualification. CI self-test artifacts are explicitly unsigned development outputs and do not replace stable assets. The separately signed preview capsules use the isolated development namespace documented in scripts/development/README.md.

Receiver pair setup --replace is an explicit local trust replacement, not a restart. It prepares fresh receiver/route/issuer/operational identities, permanently locks the old pairing and waits for its active workers to exit before atomically exchanging directory generations. Old state stays private and locked; no failed replacement, relay response or ordinary reconnect may reactivate it. Existing paired receivers require local confirmation before replacement. Installation alone never replaces endpoint identities.

The receiver broker retains CAP_SETUID to create its unprivileged worker and CAP_KILL to enforce shutdown of that different-UID process. The network worker has no effective, permitted or ambient capabilities after dropping credentials. The systemd service uses readiness notification: fresh setup does not report advertising until the worker observes relay acknowledgement. This is a delivery check, not proof that the relay is honest or that a client is authenticated.

Release and assurance status

OwnTransit 0.1.0 is the candidate release line for Apple-silicon macOS (arm64), 64-bit x86 Linux (amd64/x86_64), and 64-bit ARM Linux (arm64/aarch64) within the documented SSH-only boundary. Intel macOS is not a supported 0.1.0 target. The tunnel, route-capability profile, guided target-generated enrollment, signed verifier-first lifecycle policy, route-rotation issuance, revocation overlays, external rollback anchor, exact-record rollback, signed release/policy verification and manager-bound package activation exist in source. The release tooling can turn one clean candidate commit into a signed, installable handoff for qualification.

That statement neither authenticates this checkout nor claims that the required release checks passed. An official stable handoff must bind the exact source, signed artifacts and release policy to an independently verified signed qualification record containing literal schema=owntransit.qualification.v1, gate_set=owntransit-0.1.0-minimal.v1 and status=PASS. That overall status requires all four bounded 0.1.0 results to pass and both unresolved finding counts to be zero. The results cover the complete source/security/publication gate, independent signature and inventory verification, the bounded native artifact smoke described below, and real SSH plus SCP through the untrusted relay using the exact signed client and connector. No such record, independent external security assessment, penetration-test certification or universal suitability is claimed here. SSH and host recovery remain operator responsibilities; keep them independently available throughout qualification and deployment canarying.

Retained 0.1.0-rc.* package state is not a supported stable-install source. Those lifecycle binaries recognize the older exact-nine artifact profile and must fail closed on the exact-fourteen stable manifest. Ordinary uninstall is intentionally non-purging, and a destructive RC trust-reset is not implemented. Release qualification uses existing or operator-provided hosts and does not represent them as pristine; retained RC state still cannot be treated as a supported in-place stable installation. The bounded macOS gate therefore stays read-only and makes no stable macOS client-install or lifecycle claim.

Reporting a vulnerability

Use the canonical GitHub repository's private security-advisory feature. Do not open a public issue for a suspected vulnerability, secret or deployment exposure. Include:

  • affected revision and component;
  • minimal reproduction or malformed input;
  • expected and observed security boundary;
  • whether endpoint, relay or local privileges are required; and
  • any evidence that a credential or real deployment may be affected.

If that private channel is unavailable, keep the report private and use only a maintainer contact independently verified from the canonical repository. Do not send secrets through ordinary issue trackers.

Security boundary

OwnTransit assumes the public reverse proxy, relay host, process, configuration and relay keys are fully compromised. They may observe metadata, ignore admission rules, cross-wire attempts and deny service. They must remain unable to decrypt or forge the independently keyed inner client-to-connector TLS stream.

Each endpoint-to-relay leg uses an outer TLS carrier, and the endpoints create a separate inner TLS 1.3 mTLS stream through it. SSH is independently encrypted inside that stream. Compromise of the relay can therefore expose metadata and availability, but it must not collapse either the inner OwnTransit boundary or the separate SSH boundary.

Both endpoint roles originate every OwnTransit connection. Neither exposes an OwnTransit listener or requires a public address; only the relay is publicly reachable.

Reverse-proxy connection and request limits are availability hygiene, never an authentication boundary. The supplied Nginx policy keys its per-peer buckets on the original TCP peer address retained before RealIP header processing and keeps independent virtual-server-wide ceilings. This prevents a request header from selecting a quota identity even under unsafe ambient RealIP trust, while deliberately grouping clients behind the same immediate CDN or proxy. A fully compromised reverse proxy may still ignore every limit or deny service without weakening the inner endpoint-authentication and confidentiality boundary.

The client, connector, offline issuers and software/deployment signers are explicit OwnTransit trust anchors. OpenSSH host/user keys and policy form a separate, operator-owned security boundary inside the carried stream; they are not OwnTransit credentials. A compromise of either endpoint is not hidden by the relay threat model.

OwnTransit owns only the encrypted byte carrier and its endpoint credentials. It never creates, selects, stores or edits SSH identities, accounts, authorization, client/server configuration, forwarding or recovery.

See ARCHITECTURE.md for the component and key boundaries.

Security invariants

  • TLS 1.3 only; mutual authentication on both outer and inner boundaries. Outer mTLS is admission defense in depth, not trusted authorization once the relay is malicious.
  • Exact OwnTransit role, EKU and SAN authorization everywhere. Outer profiles and the client's connector check retain exact SPKI pins. A capability-profile connector instead requires the exact route-specific client CA plus strict connector/route/epoch SAN binding and local revocation state; it has no positive client list.
  • Newly enrolled runtimes validate each local key/leaf against its explicit issuer, exact configured role name and validity window before opening a network connection.
  • Session resumption disabled for the authenticated profiles. The capability profile uses a distinct ALPN, so it cannot fall back to legacy exact-pin TLS.
  • Connector local dial occurs only after successful inner authentication.
  • Production target is build-fixed to literal tcp4 127.0.0.1:22.
  • Strict fixed-size rendezvous frames and bounded state/time/resource use, including fixed-cardinality DNS-keyed client admission state, a one-per-second OPEN rate with burst four, relay per-client pending/active quotas, and a post-handshake connector per-client active quota whose zero-count entries are deleted.
  • No endpoint, issuer, release or deployment secrets on the relay.
  • No relay-controlled enrollment, target, software update or rollback channel.
  • Proxy stdout contains only SSH bytes.
  • Unique endpoint keys per physical installation.
  • A distinct offline client-capability root per connector/route; never a global capability issuer. One root is normal and a second is accepted only during an explicit signed-state rotation overlap.
  • Signed, sequenced and reversible release/config/credential tuples for 0.1.0.

Initial public trust may be transported tentatively through the invitation, but the exact transcript becomes trusted only through an independently established, bidirectionally authenticated out-of-band procedure. The relay and enrollment response may carry no authority to replace issuer roots, the deployment verifier, release trust or rollback floors. There is no TOFU mode for those anchors.

The route-capability profile intentionally accepts any unrevoked client leaf issued by that route root. This removes connector-side per-client configuration and leaves OpenSSH to decide login authorization, but it makes theft of that route issuer sufficient to mint new capabilities for the route. The legacy exact-pin migration profile has stronger issuer-compromise resistance because a new leaf also needs a preinstalled SPKI pin. This tradeoff is explicit, scoped to one connector/route, and not hidden behind an empty allowlist.

Installation trust

There are two installation paths with different bootstrap trust assumptions:

  • The Linux quick install trusts the canonical GitHub repository and HTTPS delivery of a commit-pinned bootstrap script. That script runs as root, pins the exact v0.1.0 downloads by size and SHA-256, and invokes the signed native installer. A fixed commit avoids following later changes to main, but it does not protect against a compromised GitHub delivery channel replacing the initial script. Such a replacement can run arbitrary root code before any embedded check. Those checks authenticate the downloaded payload only after the bootstrap itself is trusted.
  • The independent/offline handoff authenticates its distribution signer and trust statement through a separately established channel before privileged execution. It remains available for operators who do not accept GitHub as their bootstrap authority. Its instructions are in INSTALL.md.

The quick bootstrap was added after the immutable v0.1.0 release; it is not part of that release's signed inventories or qualification record. The release binaries, signatures and runtime authorization are unchanged. Neither installation path uses an OwnTransit relay as a software authority. A compromised installer compromises its endpoint; the malicious-relay construction does not protect a compromised endpoint.

Release integrity and additional assurance

Every official 0.1.0 artifact handoff must provide authenticated native distribution and an exact release and policy binding. A separately executed verifier must authenticate every handoff, policy, manifest and inventory byte. On matching macOS arm64, Linux amd64 and Linux arm64 hosts, the bounded artifact result must execute and version-check every ordinary native executable, authenticate and inspect both relay OCI archives and the Darwin launcher, record the launcher's expected fail-closed fixed-path rejection, and perform no macOS system mutation. On both Linux architectures it must install and activate the exact signed connector, verify its binary identity and systemd confinement, prove it owns no OwnTransit listener, restart the enabled service, perform an actual host reboot, reacquire the host directly, and prove the enabled connector is running or retrying post-boot. The separate live result must carry a real SSH session and integrity-checked SCP transfer through the deployed untrusted relay with the exact signed macOS client and connector, using the pre-existing operator-supplied client configuration and SSH key. It must perform no macOS system mutation and leave those client inputs plus the deployed connector configuration and endpoint credentials unchanged. A known unresolved Critical or High security defect is a release block.

This is deliberately a bounded first-release claim. It does not prove candidate macOS client installation or launcher activation, macOS provisioner package lifecycle, Linux client, provisioner, or relay package lifecycle, pristine installation, every lifecycle transition, every host policy, or portability to an untested environment. The Linux connector reboot result is specific to the two exercised existing hosts, not a clean-host or universal recovery claim. Those stronger claims require the additional assurance below.

For the independently authenticated handoff, the OpenSSH distribution signer authorized as owntransit-release is the privileged package-bootstrap authority: it authenticates the outer asset inventory and the native checksum inventory containing the installer entry point. Because the first privileged program cannot retroactively authenticate itself, compromise of that distribution key can authenticate malicious root installer code even without the distinct release-manifest or release-policy keys. Those keys preserve separate lifecycle and rollback authorities; they do not form a threshold signature for package bootstrap. Protected staging must use fresh root-created inodes on a local filesystem, never a chown of an untrusted extraction tree or a FUSE/network/reused writable tree.

Client, connector, relay and offline provisioner software use the same manager-bound signed release/policy transaction, external rollback anchor, immutable release directories and authenticated current selector. The provisioner handoff invokes its authenticated role-local owntransitctl only for package apply, rollback, recovery and (on macOS) detach. Installing or updating that role creates no runtime reader, service, target state, endpoint credential or SSH material.

On macOS, a single persistent root-only package-mutation.v1.lock covers both client and provisioner transitions, public-entry publication and lifecycle-owned detach. The provisioner release tree remains non-user-traversable at root:wheel mode 0750; only a distinct digest-matched mode-0755 copy is publicly executable. On Linux, one persistent empty root-only /var/lib/owntransit/package-supervisor/platform.v1.lock serializes complete installer and non-purging uninstaller integration windows. Connector and relay detach additionally holds the existing role supervisor lock so a concurrent lifecycle action cannot restart a service while its unit is removed. The provisioner tree is mode 0755 and package operations fail closed unless fs.protected_hardlinks=1; the legacy directory mode migration is Linux-only.

For connector and relay mutations, a root-only <role>.intent record blocks systemd activation until authenticated package mutation and role activation finish. The supervisor then atomically renames and directory-syncs the record to <role>.restart before asking systemd to start the role. That second state allows activation but preserves a durable restart obligation until the service is verified active. Recovery returns a surviving restart record to the blocked intent state and replays the exact idempotent operation. Simultaneous intent and restart records are treated as conflicting residue and fail closed.

The packaged relay mailbox accepts only the Podman private-bridge peer as deployment plumbing. The exact signed units' --network=bridge and --publish=127.0.0.1:9087:9087/tcp settings are the exposure boundary; mailbox reachability grants no release trust, enrollment authority, endpoint identity or plaintext access. The repository supplies a packaged mailbox qualification harness; per-architecture public-relay exchange labs are additional assurance rather than a 0.1.0 publication gate.

The following work improves assurance and operations but is not represented as missing tunnel, client, connector or relay functionality:

  • independent implementation review and authorized penetration testing;
  • pristine or factory-clean macOS and per-architecture Linux lifecycle labs;
  • dual public relay-exchange qualification and exhaustive composite dossiers;
  • broader hostile-filesystem, disk-full, power-loss and recovery exercises;
  • independent clean-builder reproduction and external public-history scans;
  • expiry monitoring, authenticated revocation operations and third-generation retirement procedures;
  • two-location issuer/signing custody and clean-room recovery rehearsals; and
  • operator canary, burn-in and environment-specific recovery exercises.

No completion or certification of those external activities is claimed for 0.1.0. The connector's lack of a positive client list makes offline route-issuer custody, bounded revocation state and a rehearsed issuer-rotation procedure particularly important operator responsibilities.

Known limitations in the 0.1.0 candidate scope

The candidate scope retains these fail-closed limitations; release wording must not turn bounded existing-host smoke into a clean-room or exhaustive platform qualification claim:

  • Endpoint lifecycle activation relies on descriptor-held runtime generations, a final pre-network check, root-published read-only views and a separately rooted exact-state rollback anchor. It does not defend against a compromised platform package manager or host root. Clean-host package, privilege, reboot and interruption matrices are additional assurance beyond the 0.1.0 smoke.
  • Release bundle and policy verification, external release-policy anchor compare-and-swap and selector publication are bound by one manager-held transaction. A detached verified decision remains intentionally unusable as install authorization. Both Linux connector install/activation/reboot runs exercise the manager boundary; the read-only macOS checks do not. These checks do not claim candidate macOS client installation or launcher activation, macOS provisioner package lifecycle, Linux client, provisioner, or relay package lifecycle, an exhaustive lifecycle, or hostile-filesystem qualification.
  • Bootstrap release ID, artifact digest, platform and architecture are authenticated operator inputs; owntransitctl does not yet measure the installed executable and derive those values itself.
  • Initial route enrollment supports exactly one client. Later-client enrollment is not implemented, and route rotation changes authenticated route state for the existing deployment; it is not a substitute for adding another client.
  • Anchor-first endpoint recovery can finish an exact interrupted transition, but authenticated garbage collection, third-record retirement and complete clean-room recovery policy are not integrated or qualified.
  • The initial provisioner creates distinct keys but stores the three issuer keys and deployment signer unencrypted beneath one private 0700 directory. This proves logical key separation, not two-location custodial separation.
  • Consumed-request history is bounded at 4096 entries and then fails closed; authenticated compaction has not been designed.

These are local endpoint, lifecycle and custody concerns. They do not give a malicious relay inner-stream plaintext, accepted endpoint-forgery authority or connector target-selection authority.

Secrets and examples

Never commit real keys, tokens, passwords, passphrases, endpoint bundles, fingerprints, hostnames, public IPs or deployment logs. Public examples use only reserved names and documentation address ranges.

If a real secret ever enters a commit, deleting the working-tree file is not remediation. Revoke/rotate it first, then clean the publication history through a separately reviewed process.

Cryptography policy

Use the standard-library TLS 1.3 implementation and reviewed standard envelope and signing constructions. Do not introduce custom encryption, home-grown key derivation, ambiguous signed serialization or a new handshake pattern without a written threat analysis, test vectors, negative tests and independent review.

There aren't any published security advisories