terminal-ssh
SSH broker overview
Kutrion brokers SSH and SFTP sessions: no standing keys on the connecting device, the credential is injected just-in-time and decrypted in memory only for the authorized session, and every byte is attributable in the audit trail.
Updated Oct 10, 2026
Kutrion doesn’t hand you a key and wish you luck. It is an audited access broker: when you open a session to a host, the server uses a vault credential to authenticate you, then tears everything down afterward. The connecting device never holds a standing key, and the whole session is on the record.
How a brokered session works
- You request a host. You pick a connection profile (host, port, login user, auth method) — see Connecting to hosts. You never paste a key into a terminal.
- The broker injects the credential just-in-time. The server reads the referenced credential from the vault, decrypts it in memory for that one authorized action, and uses it to authenticate to the target. With envelope encryption there is no plaintext credential material at rest; the decrypted secret lives only for the life of the session.
- The session runs. Interactive shells, single commands, port forwards, and file transfers all run over the same brokered SSH path. The connecting device exchanges terminal bytes with the broker, not the host’s private key.
- It tears down. When the session ends, the in-memory secret is discarded. Nothing is left behind on the laptop, browser, or CLI to rotate later.
What the injection-only flag means
A credential can be flagged injection-only. The broker still decrypts it in memory to authenticate a session, but the reveal, copy, share, borrow and export paths all refuse it: it does not appear in the interface, in a share link, in a vault export, or in a client’s offline copy. Every injection is recorded in the audit trail.
Read the flag as one sentence, and read both halves of it:
the broker may use the secret without revealing it, to a destination recorded on the credential.
The second half is the part that decides how much the flag is worth. Withholding the value from display says who does not get to see the secret. It says nothing about where the secret is sent; the credential’s own destinations decide that.
What the flag is not. It is not a barrier against the people who are allowed to change the credential. It keeps a working secret off the screen and out of copies and exports; where the secret may be sent is decided by the credential’s destinations, below.
Each credential carries its own destinations. The broker presents a credential only to a host and port recorded on the credential itself, not to whatever a connection profile names. When someone with write access to the credential’s vault first points an SSH connection at a credential that has no destinations yet, that host becomes its first one. Any further destination is added on the credential, with the secret re-supplied, and the addition is recorded in the audit trail. A credential used anywhere else is refused before the broker connects, and so is a credential with no destinations at all. So a vault member who can read a credential but not change it, and who points a connection at a host they control, gets a refusal rather than the secret.
Self-hosted installs can turn off the refusal for credentials with no destinations
(CREDENTIAL_DESTINATION_ENFORCE=0). A credential that has destinations is held to them either way.
What the broker does before it opens your shell
Before it asks the host for a terminal, the broker runs one true command on the connection, with no
terminal attached. It does this to find out whether the host is about to demand a password change, which
sshd would otherwise run on your terminal and which cannot work through a broker. If the host answers that
a change is required, the session is refused with a message saying so, and no terminal output from the
host reaches you. Every session records the outcome as pre_shell_probe in its audit entry (change,
clear, no_verdict or timeout).
Two things follow for administrators.
- ForceCommand and
command=hosts run the forced command once extra. On a host that forces a command (sshdForceCommand, or acommand=key option), the probe’strueis replaced by the forced command, so it runs once without a terminal before the real session (if the probe times out, see the next point: that run may still be in progress when the interactive session starts). A wrapper with side effects, such as a menu, a notifier or a session logger, fires twice per connect. You can recognise the probe in the host’s logs: it runs withSSH_ORIGINAL_COMMAND=trueand no TTY, immediately before the interactive session from the same address. There is no per-connection setting to turn the probe off; make such a wrapper ignoreSSH_ORIGINAL_COMMAND=truewithout a TTY. - A slow host skips the check. The probe waits 10 seconds. If the host has not answered by then (for
example slow PAM or sssd session setup), the broker proceeds without a verdict and records
pre_shell_probe=timeout. On such a host an account whose password has expired still gets sshd’s change-password conversation on the terminal, which the broker cannot complete. Fix the host’s session setup latency, or have the account’s password changed outside the broker. On a host with a forced command, a timed-out probe also means the forced command may still be running when your interactive session starts.
On a host with a forced command and an expired password, the refusal still works. In OpenSSH 10.0p2
do_child in session.c checks force_pwchange and exits through do_pwchange (“Password change
required but no TTY available.”) before it builds the argument list for the shell or the forced command,
so the forced command does not run when a change is pending
(session.c, tag V_10_0_P2).
do_exec only substitutes the forced command into command earlier; nothing executes it before that
check. force_pwchange is set by PAM (sshpam_password_change_required in auth-pam.c) or by the
shadow-expiry check in auth-passwd.c. This was read from the source of that release; it was not run
against a live sshd with an expired account and a ForceCommand. It also holds only when the probe gets
an answer: if the probe times out, there is no verdict and the session proceeds.
Everything is attributable
Brokered actions are written to the hash-chained audit trail, tied to a specific user:
- Connecting, running a command, and opening an interactive shell are each recorded.
- SFTP operations — list, download, upload, mkdir, rename, delete — are recorded with the path and size.
- Commands sent from the run bar, checked with validate, or run by an AI agent over MCP are risk-checked before they run. A high-risk command from the run bar requires a fresh WebAuthn step-up, and the block is itself audited (proven presence, not a self-declared flag). Keystrokes typed into an interactive shell are not risk-checked: they go straight to the host.
- On Team and above, the terminal output of a shell you open on your own is captured for review. A shared session is not recorded yet, so sharing is off on those plans; see Session recording.
This is the difference between “someone on the team has access” and “this person ran this command on this host at this time.” Kutrion gives you the second.
SFTP runs through the same path
File transfer isn’t a side door. SFTP uses the same brokered connection, the same vault credential, the same RBAC check on that credential’s vault, and the same audit trail as an interactive shell. There is no separate set of keys to manage for file movement.
Contrast: scattered private keys
The traditional alternative is a private key on every laptop and an authorized_keys file on every
host. That model fails exactly where it matters:
| Concern | Scattered private keys | Kutrion broker |
|---|---|---|
| Where the key lives | On each device | In the vault, under envelope encryption |
| Rotation | Touch every host and device | Rotate centrally; nothing on devices to chase |
| Attribution | A shared key says nothing about who | Every session is tied to a user in the audit trail |
| Revocation | Hunt down copies and edit authorized_keys | Remove access centrally; no standing key to revoke |
| Secret exposure | The user holds the plaintext key | The secret stays in the vault; the injection-only flag also keeps it out of the interface and exports |
For a fully keyless model on the host side, pair the broker with the SSH certificate authority, which mints short-lived certificates instead of distributing static keys.
Where to go next
- Connecting to hosts — create a connection profile and open a session.
- Session recording — capture and replay terminal and SFTP activity.
- SSH certificate authority — short-lived certs, no static keys on hosts.