4.8 KiB
Protected connection credentials
The existing systemd 256+ backend uses owner-scoped encrypted credentials and
systemd-creds decrypt --user. Existing installation records without a backend
field retain that behavior. The systemd 255 backend preserves the same user
service and uses a separately installed, privileged credential helper. Node
startup without a ChatGPT connection does not need a runtime connection key.
Installation and authorization
The package supplies these root-owned files:
/usr/lib/framebridge-expanded/bin/framebridge-credential-helper/usr/lib/framebridge-expanded/expanded/framebridge_expanded/credential_helper.py
The launcher executes the fixed system interpreter with -I -S; the helper uses
only the standard library and absolute systemd-creds/visudo paths. Merely
installing the package does not enable a connection or install a sudoers grant.
On systemd 255, connection setup requires ordinary administrative sudo
authorization. It writes host-encrypted ciphertext and principal metadata under
/var/lib/framebridge-expanded/credentials, owned by root with private access.
It also installs one validated file in /etc/sudoers.d per credential version.
That file permits exactly the recorded owner's literal helper decrypt command
and fixed profile/cipher digest arguments, with NOSETENV. It does not permit
arbitrary systemd-creds commands, paths, shell execution, account selection,
provisioning, revocation or unrestricted root execution without authentication.
This narrow permission is necessary for unattended reconnection after reboot.
The owner must review this permission change before production setup is activated. Building the package and running synthetic unit tests do not activate the helper, create a host encryption key, alter sudoers or enable a service.
Scope and recovery
The helper derives the caller from sudo's UID, username and primary group; it does not accept a caller-selected UID. Its records bind the UID, username, home identity, profile digest, ciphertext digest and randomized cryptographic name. Only fixed root-owned paths are opened. Symlinks, unexpected hardlinks, writable parents, broad metadata permissions and unrecognized arguments are rejected.
Provisioning keeps the old credential usable until the replacement connection
commits. Retired versions remain listed until revocation succeeds. Directory
fsync orders durable ciphertext registration before the decrypt grant, and
grant revocation before ciphertext removal. Failed output delivery rolls back a
new grant. After SIGKILL or power loss, administrative prune reconciles orphan
versions even if the owner never received their ciphertext digest. New setup
preserves known current versions while pruning orphans; explicit disable prunes
all versions for its owner/profile, including when no manifest was committed.
This reconciliation also runs after an upgrade to the systemd 256+ backend.
Uninstall uses administrative purge-all after the user workers have stopped.
Recognized root-owned staging files from interrupted publication are recovered.
Administrative interface (run the installed launcher, never a user checkout):
protect PROFILE_SHA256: read a bounded printable synthetic/runtime key from stdin and return only encrypted ciphertext on stdout.decrypt PROFILE_SHA256 CIPHER_SHA256: return the registered owner's key on a pipe; this is the only operation granted passwordless sudo.revoke PROFILE_SHA256 CIPHER_SHA256: idempotently revoke one owner version.prune PROFILE_SHA256 KEEP_DIGESTS: remove other versions for this owner and profile;KEEP_DIGESTSis a comma-separated digest allowlist, or-for none.purge-all: root administrative removal of all helper-owned records/grants.
Security limits
No plaintext key is intentionally stored in an environment variable, command argument, log or disk file. Plaintext exists in process and pipe memory while used; this is not a guarantee against memory inspection, swap, a compromised owner session or root. Both credential backends trust the owner Unix principal.
UID reuse with another username or home is rejected. Recreating exactly the same UID, username and home can recreate the same Unix principal; Linux does not supply an account-generation identity here. Administrators must revoke or purge the grants before deleting/recycling an account, and before changing its identity/home in a way that would prevent ordinary owner cleanup. A randomized credential name is not proof of an account's generation.
The helper backend is not a Wayland capture/input backend and does not remove Python ABI, architecture, libc, PAM, user-systemd, cgroup, sudo or X11 capability requirements. Synthetic tests validate interfaces and failure handling; a support claim additionally requires clean-system installation, real systemd credential operations, boot/lifecycle and feature-specific acceptance tests.