How GridWeave is designed to be secure, and what is proven

The security rules, where each one is enforced, and an honest account of what tests and an internal review have shown. GridWeave is under construction and not released; this page describes mechanisms, not a guarantee.

Read this first.

No external penetration test has been done, nothing is code-signed, and the continuous integration service is disabled. The only review so far was done by the project itself. The list of what is not proven yet is part of this page, not a footnote.

The main security rules, how each is enforced, and its status. Status words follow the product's own status pages as of 2026-11-13.
RuleEnforced byStatus
The agent verifies authorization itselfSigned command envelope, checked on the deviceBuilt
The server never sends code to the agentAgent protocol design and a test on the contractBuilt
Device identityMutual TLS, enrolment tokens, a private certificate authorityPartial
Tenant isolationPostgreSQL row-level security on every tenant tableBuilt
Audit of every changeTransactional outbox and a hash-chained logPartial
Sign-in securityOne verification path, throttles, TOTP, single sign-on, tokensPartial
Secrets stay secretWrapped at rest, redacted in logs, never in a response or URLBuilt
Key managementFile, encrypted file or OpenBao Transit, scoped per rolePartial
Remote sessionsSingle-use signed grants, consent on the device, revocationPartial
Update integrityEd25519-signed manifests, keys pinned in the agent, staged rollouts, automatic rollbackPartial
Clean-room build, permissive licencesRepository checks that fail the buildBuilt

The agent

The device does not trust the server on its word

Both rules below are built. The first is covered by a 25-test forgery suite; that suite uses test keys and no live server.

  • Signed commands, verified by the agent

    Built

    Every command arrives as an envelope the server signed. The agent checks the certificate chain to the root it pinned at enrolment, the signature (before it reads the envelope), that the device and the tenant are its own, the time (an envelope lives at most two minutes), that the command id has not been seen before, and that the envelope carries every permission the command needs. Only a verified command can be executed; the compiler refuses any path that runs an unverified one.

    The command signer comes from its own certificate authority that signs nothing else. A device certificate, or a server certificate, cannot sign a command.

    Limits: the agent's own audit entries describe what a working agent did; they are not a control against a compromised agent.

  • No server-supplied code

    Built

    The agent protocol has no message that delivers code to run. The one field that carries text for an interpreter is an operator's script inside a verified envelope that names a user who holds the permission to run scripts. A test fails if a contract change adds a field that looks like code delivery, or a new opaque bytes field, without review.

    Updates follow the same rule: the agent checks a signed manifest and the file against keys compiled into its build. No server message starts an update or carries an address to fetch from; an installed agent asks for a version and downloads from the server it enrolled with (see update integrity below).

Identity

Devices, enrolment and tenants

  • Mutual TLS and enrolment tokens

    Partial

    A device enrols once with a token and then connects with a client certificate from a private certificate authority. Its identity is the hash of its public key. The agent trusts only the platform root from its configuration (optionally checked against a pinned fingerprint) and refuses any other authority before it sends the token. Tenant and device group are never claimed by the agent; the server reads them from the database on every connection.

    An enrolment token is stored only as a hash. Unknown, expired, revoked and used-up tokens look the same to the caller, and attempts are rate limited per address. Device certificates last 90 days and renew in the second half of their life. Revoking a device closes its connection and refuses it afterwards.

    Limits: the agent keeps its key in a file readable only by its account, not in a TPM or the macOS Keychain. Revocation and renewal were tested against a real database and two nodes in one process, not on separate hosts.

  • Tenant isolation in the database

    Built

    Every tenant table carries a tenant id and a forced row-level security policy from the migration that creates it. Request handlers run as a database role that is subject to those policies, and the tenant is set per transaction so nothing leaks through the connection pool. Another tenant’s resource is reported as not found, even to a full administrator.

    A test discovers every table with a tenant column from the database catalogue and checks that one tenant cannot read, move, insert or delete another’s rows. A table added later is covered without anyone listing it. It runs against real PostgreSQL.

    Limits: a deployment that uses one database login for all roles lets a SQL injection switch role, so operators should set separate logins. The review read every handler’s SQL and found no query built from request values. The cross-tenant suite with the application’s own tenant check switched off is not described as built.

Accountability

Audit, sign-in and secrets

  • Audit through a transactional outbox

    Partial

    Every state change, sign-in event and permission denial writes an entry to an outbox in the same database transaction as the change, so a rolled-back change leaves no entry. A relay then appends it to the audit log exactly once. The log refuses update, delete and truncate for every role, and each tenant’s entries form a SHA-256 hash chain that gridweave-admin audit verify recomputes. A command is recorded before it is sent.

    Not built: a daily external anchor of the chain, so removing rows from the very end of the log and its chain head would not be detected.

  • Sign-in security

    Partial

    Passwords use Argon2id. One code path verifies every credential, does the same work whether or not the account exists, compares in constant time and takes a minimum time. Failure counters are shared across nodes and kept per account and per source network. A TOTP code cannot be replayed. Sessions are opaque, stored server side, revocable at once, carried in a __Host- cookie, with a CSRF token on every change.

    OpenID Connect (with PKCE), LDAP and SAML 2.0 end in the same session-creating function. LDAP always verifies the server certificate and has no off switch; SAML refuses unsigned, wrapped, replayed, expired and misdirected responses. Personal access tokens are stored as hashes, sent in a header only, and act as their creator with the creator’s live permissions narrowed by the token’s own list, so a token can never exceed its creator. Tokens cannot manage credentials or sessions.

    Limits: LDAP and SAML were proven against OpenLDAP and Keycloak only, not Active Directory or another SAML provider. Passkeys, recovery codes and other second factors are not built. The server requires the current password (and a current code if a factor exists) to add an authenticator. In the current web source, the enrolment dialog still sends neither, so enrolment from the screen is refused until it does (read from the source, not run).

  • Secrets are never logged or returned

    Built

    Configuration secrets are given by reference and printed redacted. Password hashes and TOTP secrets are stored wrapped by the key store. Reset and invitation links are single use, stored hashed and carried in the URL fragment, not the query. A check on the API contract fails the build if a credential appears in a response. Session grants, tokens and links are kept out of logs and audit entries, and tests search for them.

Keys

Key management

Three key stores exist. The default is the one meant for development.

The three key store drivers. Source: the product’s key management page.
DriverWhere keys liveMeant for
file (default)One key file each, mode 0600. Anyone who can read the data directory can copy them.Development. It raises a system warning.
file-encryptedThe same files, encrypted under a master secret kept outside the key directory.One host without OpenBao.
openbaoOpenBao Transit. Keys are non-exportable and never leave it.Production.

With OpenBao the server holds only a token, and the policy is per role. The agent-gateway token can sign only with the device and service authority keys. The API token can sign only with the command authority and command-signing keys, and wrap and unwrap secrets. A compromised gateway host therefore cannot ask OpenBao to sign a command. The policies were tested against a real OpenBao. The store fails closed: if OpenBao is unreachable, signing and unwrapping are refused and nothing falls back to another store. Each process loads only the signing keys its role names. Rotating the wrapping key without downtime is built and tested.

Not met: the file drivers cannot separate roles, because there is one directory and one operating-system user; the root authority is online in the same store, with no offline root ceremony; OpenBao’s own audit device is the operator’s to enable; there is no layer of per-tenant data keys; recovery with dual control is not built.

Remote sessions

Terminal and file sessions

Built for terminal and files only. There is no remote desktop. Every point below is partial, and the gaps are listed.

  • Single-use signed grants

    Partial

    A session starts with a signed offer to the agent and a grant for each side. A grant is Ed25519-signed, valid for at most 60 seconds to connect, bound to one relay, one session and one role, and usable once across relays. It travels in the first frame, never in a URL, a log or an audit entry. A relay can verify a grant but cannot mint one. Every refusal is audited.

    The agent checks the offer as a signed command, then the grant, then the relay’s identity (a pinned key, or a chain to the platform root, over TLS 1.3) before it sends a byte.

  • Consent on the device

    Partial

    The grant carries a consent policy: none, notify or prompt. The agent enforces it and drops all input until the session has started, and in a view-only session it drops input throughout; the relay drops it as well.

    Limits: there is no helper application on Linux or macOS, so a prompt is refused unless the device is configured to allow headless sessions. Consent answers are accepted from any peer the local endpoint serves. The Windows terminal and consent prompt were written but never run.

  • Revocation

    Partial

    A live session ends when its permission goes: within two seconds on an event, within five seconds without one. In tests, deleting a role binding closed both sides in 64 to 484 milliseconds. A suspended tenant, a revoked device, a disabled user or a revoked login session also end it.

    Limits: tested with one message bus server and one relay process per test, not a cluster. The relay connects to PostgreSQL as the application role, so a compromised relay can read what that role can.

  • Recording integrity

    Partial

    A recording is split into chunks that are verified against a manifest and a hash chain before a byte is returned. A finished recording is frozen by a database trigger, every read is audited before the first byte, and a recording that must exist but cannot be made either refuses the session or ends it. Recordings reach the object store through the authenticated, audited endpoint, with no signed URLs.

    Limits: no agent shows a notice that a session is recorded. Object lock does not exist. Server-side encryption depends on the storage driver and was never verified against a real service.

  • Guest links

    Partial

    A person without an account can join one terminal session through a link. The link is 256 random bits, shown once and stored hashed, never in a query string, log or audit entry. Redeeming it is rate limited across nodes. The guest’s grant names the share and is accepted only by the relay for that session, never by the control API. The guest gets only what the creator holds at that moment, and the session ends when the link is revoked, runs out, or its creator loses the rights.

    Limits: no agent shows a notice that a guest has joined.

Updates and supply chain

Update integrity and a clean-room build

  • Signed update manifests

    Partial

    A release manifest lists each file with its hash and size and is signed with Ed25519. The agent pins two public keys compiled into its build; no flag, file or environment variable changes them, and one signature by either key is enough. The agent verifies the manifest and the file before it stages or applies anything. The server serves files and signs nothing. Two builds of the Linux agent were byte-identical.

    Limits: the two pinned keys in the repository are development keys, and the offline key ceremony has not been performed. Nothing is code-signed. Linux was proven on a real machine, macOS was built and inspected but not installed, and the Windows part was not run.

  • Staged rollouts and rollback

    Partial

    The agent fetches updates itself, so the rule is that nothing the server answers can steer it. The server names a version and never an address. The agent builds every address from the server URL it enrolled with, accepts only a plain version and a plain file name, follows no redirect, cuts a body off at the signed size, hashes the finished file whole and verifies the signed manifest and the artifact again when staging and when applying, before one rename swaps its binary. If the new build does not stay connected within its window, the previous build is restored, either by the new build or by a watchdog that the previous binary arms first, so a build that never runs cannot disable its own rollback. A health gate halts a rollout when too many devices fail or roll back. Every refusal and outcome is audited, and the agent answers a scripted hostile server (tampered bytes, an unpinned key, an expired manifest, a redirect, an oversize body) in its tests.

    Limits: proven on Linux under systemd only. The macOS launchd job and Windows are unverified, and a rollout was never tried on more than a handful of devices.

  • Clean room and permissive licences

    Built

    GridWeave is built from a behavioural specification alone. The earlier product the specification came from has never had its source opened, copied or ported, and a repository check fails the build if its name appears outside the specification. Every dependency must be MIT, BSD, Apache-2.0, ISC or an unmodified MPL-2.0 library, and a check fails the build otherwise. Five build-time or development-only packages pass by a named exception approved by the owner. GridWeave itself is licensed under Apache-2.0.

Review

The internal security review

One review has been done, by the project’s own team on 2026-11-13. It covered enrolment, identity and command authorization. It was not independent. It predates the relay sessions, staged rollouts and self-update, recording and guest sharing, none of which has had a review of its own.

The review built a threat model and read the sign-in, authorization and tenancy code. It then probed a live server and a real agent. Every API operation that takes a resource identifier (103 at the time) was called by a session of one tenant with identifiers from another tenant. Each answered with a refusal or not found, bulk operations reported not found per device instead of acting, and list endpoints returned only the caller’s own rows. The agent-plane probes and a flood of 6,000 forged messages did not corrupt the audit chain.

A follow-up added a forgery suite of 25 tests in the agent. It feeds forged commands to the agent’s verifier: a key the command authority did not certify, another root, a device certificate used as a signer, an envelope changed by one bit, another device or tenant, replays and expired windows, and 6,000 random mutations. Each is refused and nothing executes, with controls showing that a good command does run. It uses test keys inside the test process, not a live gateway or agent. No production defect was found by it. Dependency scans of the agent, the server and the web application found nothing reachable, apart from one moderate advisory in the web lint toolchain that is not fixed.

The four findings of security review 1. No finding was Critical. Source: the product’s security review page.
FindingSeverityWhat it wasStatus
SEC-001HighAdding a TOTP second factor needed no re-authentication.Fixed on the server The web dialog is not yet updated.
SEC-002Medium-HighThe sign-in throttle was keyed by the identifier typed, so alternating username and e-mail doubled the guesses.Fixed
SEC-003MediumEvery server role loaded the command authority’s signer, narrowing the guarantee that a compromised gateway cannot forge a command.Fixed Fully effective with OpenBao only.
SEC-004LowNo limit on distinct messages from one agent connection; 6,000 forged messages were accepted.Fixed

The review’s own recommendation was that the product was safe for an internal pilot once the first two findings were fixed, and not ready for production. It did not cover remote desktop, the terminal and file sessions, extensions, Intel AMT, fuzzing of the gateway’s message decoding, or the Windows service and installer.

Honest status

What is not proven yet

Any one of these means the product should not be run where its security matters.

  • Not doneNo external penetration test. It is planned for a late milestone that has not started.
  • Not doneNothing is code-signed. No Authenticode, Developer ID or other certificate exists, and installers are unsigned.
  • Not doneThe offline key ceremony for update signing has not been performed, and no offline root ceremony exists for the certificate authority.
  • UnverifiedThe Windows parts of sessions, the installer and update staging were written and never run, or not completed. The Windows virtual machine became unreachable on 2026-11-13. On macOS the launchd restart and the update watchdog job were never run.
  • OpenThe web dialog that adds a second factor does not send the password the server requires (SEC-001 follow-up).
  • Simulator onlyIntel AMT was built against a simulator, never real hardware, so its protocol behaviour is unconfirmed.
  • DisabledContinuous integration is disabled, so nothing re-runs the tests or the dependency scans automatically. The local checks are the gate.
  • UnmeasuredLoad limits were not measured on a reference host. The 10,000-agent run happened once on a shared Mac.
  • NarrowThe product has run on one macOS machine and one Ubuntu virtual machine only.

Disclosure

Reporting a vulnerability

If you believe you have found a security problem in GridWeave, please report it privately and give the maintainers reasonable time to respond before you share details. Do not post it in a public place.

The contact for vulnerability reports will be published here before release.