Activity Search & SIEM Export
Session recordings answer “what happened in this session”. They are the wrong tool for “who ran that command anywhere last month” - that means opening sessions one at a time until you find it.
Bridge also writes session activity to a searchable index, so the second question is a search rather than an excavation. The same stream of events can be sent to your SIEM, so Bridge activity lands next to the rest of your security telemetry.
What gets indexed
As a recorded session runs, Bridge indexes the things a reviewer looks for:
- Commands run in shell sessions - SSH, telnet, Kubernetes exec - and on network devices (NETCONF, RESTCONF, WinRM), one entry per line the user submitted, including attempts a command policy blocked and the fact that they were blocked. Both native and in-browser sessions.
- Database queries from both native and in-browser database sessions.
- HTTP requests passing through the web proxy.
- File transfers - clipboard file copies and browser uploads.
- Pasted text from in-browser RDP, SSH and VNC sessions, at the level set
by
paste_capture. - Typed input in desktop sessions (RDP, VNC) - what was typed into the remote
desktop, one entry per line, governed by
keystroke_capture. - Typed input in in-browser SSH, as a second entry alongside the command when the two differ - the edits, aborts and control keys the final command text hides.
Each entry keeps the session, user, target and timestamp, and links back to the moment in the recording it came from - so a search result opens the replay at that point rather than at the beginning.
Only recorded sessions are indexed. A checkout that sets record_session: false
is not recorded and does not appear.
Desktop typing is indexed as keystroke entries, never as commands: nothing typed into a window was executed, and letting it land as a command would weaken the meaning of every command result.
What is not searchable
| Not indexed | Why |
|---|---|
| Mouse movement, clicks and window focus | Only typed input is reconstructed. What was clicked is a question for the replay. |
| Pastes in native sessions (any protocol) | A native client has no clipboard channel to the Bridge. A paste arrives as ordinary input, indistinguishable from typing, and is recorded as such. |
| Pastes in in-browser telnet and Kubernetes exec | Those sessions use a different relay from RDP/SSH/VNC and do not produce paste entries. Commands typed in them are still indexed. |
Desktop keystrokes
What someone typed inside a remote desktop is indexed and exported like any other activity, but it needs its own setting, because a desktop gives Bridge less to work with than a terminal does.
In a terminal, Bridge can tell a password from a command: a terminal only draws when it echoes, so input that produced no echo is a secret and is masked outright. A desktop draws constantly - the clock alone - so that signal means nothing there. What leaves the recording for a searchable index or a SIEM is therefore a deliberate setting rather than something inferred.
| Option | Type | Default | Description |
|---|---|---|---|
server.recording.keystroke_capture | string | redacted | redacted to index desktop typing with secret-shaped spans masked, or off to not index it at all. |
server:
recording:
keystroke_capture: "redacted" # the default; "off" to index none of itA checkout can override it for one grant with keystroke_capture.
This setting does not change the recording. Key events are captured either way, and remain visible in the player’s keystroke log - it governs only what becomes searchable and what is sent to a SIEM.
What the masking does and does not catch. It recognizes command-line secret
shapes - --password X, token=X, identified by X - so it catches a credential
typed into a console inside the desktop. It cannot catch a password typed into
a GUI field, such as a Windows logon box: from key events that looks like any
other word, and nothing on the wire identifies it.
If a desktop session might involve typing a password into a Windows dialog and
that must never reach the index or your SIEM, set keystroke_capture: off for
those checkouts. The session is still fully recorded and replayable.
There is no verbatim option. The reconstruction that turns key events into lines masks secrets for the player’s keystroke log and the command log as well, so a mode that bypassed it would weaken those too.
Searching
Open Activity Search from the floating search button in the web interface, beside the Admin button. Search by text, and narrow by event type, user, target, protocol or time range. Each result offers View session, which opens the replay at that event.
Activity Search is admin-only - the button appears for users with the admin role (or an active admin-role checkout), and the search API rejects anyone else. Auditors review through the sessions list and their audit scope, not through Activity Search.
Indexing settings
New sessions are indexed as they run, and that is not optional. What you can control is the one-time catch-up for recordings that were made before the index existed, which is paced so it never competes with live sessions for disk or database.
server:
audit:
backfill_enabled: true # import pre-existing recordings (default)
backfill_batch: 20 # sessions per cycle
backfill_interval_seconds: 5 # seconds between cycles| Option | Type | Default | Description |
|---|---|---|---|
server.audit.backfill_enabled | bool | true | Import events from recordings that predate the index. Set false to index only sessions started from now on. |
server.audit.backfill_batch | int | 20 | How many sessions one catch-up cycle processes. |
server.audit.backfill_interval_seconds | int | 5 | Seconds between catch-up cycles. Also the idle wait when nothing is pending. |
The Admin console’s Overview tab reports catch-up progress, so you can see whether the index is still filling in.
The index lives in the same PostgreSQL database Bridge already requires. Its table is created automatically on upgrade - there is nothing to run by hand.
Streaming to a SIEM
The same events can be forwarded as they are indexed. Off by default.
server:
audit:
export:
enabled: true
type: "webhook" # or "syslog"
endpoint: "https://siem.example.com/ingest"
token: "REPLACE_WITH_YOUR_TOKEN" # webhook only| Option | Type | Default | Description |
|---|---|---|---|
server.audit.export.enabled | bool | false | Turn on streaming. |
server.audit.export.type | string | - | webhook (an HTTPS POST carrying a batch of events as JSON) or syslog (one RFC 5424-style line per event). |
server.audit.export.endpoint | string | - | The webhook URL, or the syslog host:port. |
server.audit.export.network | string | udp | Syslog transport: udp or tcp. Ignored for webhook. |
server.audit.export.token | string | - | Webhook only. Sent as Authorization: Bearer <token>. |
Prefer tcp for syslog unless you have a reason not to - UDP silently drops
under load.
Sending is best-effort, and the console tells you so
Export never blocks or slows a session. If the destination is unreachable, events are dropped and counted, and the session carries on. That is the right trade-off for access, but it means a misconfigured destination can look like it is working.
So the Admin console’s View Configuration tab reports export twice: what the configuration asks for, and what actually got wired. If the first is on and the second is off, Bridge could not establish the destination - check the endpoint and the logs. Do not treat configured as delivered.
The bearer token is never shown back, only whether one is set.
Audit events describe activity: who connected to what, and the commands, queries
and requests they issued. Depending on your paste_capture setting they can also
include pasted text. Treat the destination as a system that receives sensitive
operational data, and prefer a webhook over HTTPS, or syslog over TCP on a trusted
network, rather than plain UDP across untrusted ground.