Security Overview & Timeline
Bromure's protections all run on the host, inside the proxy and the virtual network switch: the credential swap, the egress firewall, Guardrails, the supply-chain checks, prompt-injection detection and PII Protection. Every time one of them makes a decision — swaps a credential, blocks a connection, checks a package, withholds a message — it records it. The Security Timeline window shows those decisions: an Overview of the last 24 hours, and a Timeline of every event.
It answers a different question from tracing. A trace records the traffic itself — "what did the agent send?" — and only when you turn tracing on. The Security Timeline records what the security engines decided about that traffic, and it is always on: every machine, enrolled or not, private mode or not, with nothing to configure.
Opening the window
Choose Window → Security Timeline…, or press ⌘K and pick Security Timeline. The window opens on the Overview tab; the segmented control at the top left switches between Overview and Timeline. There is one window for the whole app; choosing the menu item again brings it forward.
The Overview tab
The Overview is headed Last 24 hours — "What Bromure's security engines decided for your agents." It has three parts.
Tiles
Five tiles count the last 24 hours of events:
| Tile | Counts |
|---|---|
| Blocked | Every event whose decision was a block (red in the Timeline), from any engine. |
| Allowed | Every event whose decision was to let something through (green in the Timeline), from any engine. |
| Credentials brokered | Credential brokering events: credential swaps, blocked exfiltration attempts, and hosts you allowed from the compromise alert. |
| Packages checked | Supply chain events: every package fetch the proxy saw. |
| PII swapped | The number of personal-data values PII Protection swapped for stand-ins — values, not requests. |
Click a tile to jump to the Timeline tab. Credentials brokered, Packages checked and PII swapped open it filtered on their engine; Blocked and Allowed open it on all engines, filtered on that outcome.
Protections
The Protections table lists each machine on this Mac, with its colour, and shows which protections it has on — a green check for on, a grey dash for off:
| Column | Checked when |
|---|---|
| Firewall | The machine has outbound-connection rules in its Guardrails pane, or denies unmatched traffic. |
| Supply chain | At least one supply-chain layer is on (the age gate, OSV, socket.dev, script stripping or the lockfile prompt). |
| Guardrails | Guardrails actually restrict something: a service with a write policy other than Off, a database guardrail, an outbound-connection rule, or any credential set to Ask before use. The per-request insecure bypass (X-bromure-insecure) doesn't count, since it relaxes rather than restricts. |
| Prompt injection | At least one prompt-injection detector is on. |
| PII protection | PII Protection's master switch is on with at least one category. |
| Credential brokering | Always: the credential swap can't be turned off. |
Use it to spot a machine that runs with fewer protections than the others. To change one, open that machine's settings (see Settings Reference).
Latest blocks
Latest blocks lists the most recent blocks of the last 24 hours, newest first, up to eight: what was blocked, the engine and decision, and how long ago. The list is hidden when nothing was blocked.
The Timeline tab
The Timeline is one table of every event, newest first:
| Column | Shows |
|---|---|
| Time | Date and time of the decision. |
| Workspace | The machine it happened on. When you mirror remote Macs, it reads Mac · machine. |
| Engine | Which engine decided, with its icon. |
| Condition | What the engine saw: the host, package, snippet, key… Hover for the full text; the text can be selected and copied. |
| Decision | What it decided, colour-coded. |
| (last column) | For firewall rows, a quick-action button: Allow…, Block… or Rule… — see Firewall quick actions. For a package OSV or socket.dev blocked, Allow… → Always Allow … in This Workspace adds it to the workspace's trusted packages (Allowed now once it is) — see Trusting a blocked package. |
Colours read the same way everywhere in the window:
- Green — allowed: let through, passed, signed.
- Red — blocked: denied, refused, withheld.
- Blue — informational: a transformation that is neither a pass nor a block, such as a credential swap, an age-gated version list or stripped install scripts.
The toolbar above the table filters it:
- Filter events… matches text in the engine, condition, decision, machine and Mac names.
- The engine pop-up (All engines by default) lists the engines that have events.
- The outcome pop-up (All outcomes by default) narrows the table to Blocked or Allowed events.
- When you mirror at least one remote Mac, a machine pop-up appears: All machines, This Mac, or one remote Mac.
- The event count ("8 events") reflects the filters.
Clear empties the window. It only hides events: they stay on disk, but cleared events don't come back when the app restarts. Export… is described below.
The engines
| Engine | What its rows record | Example decisions |
|---|---|---|
| Credential brokering | Credential swaps on the wire (Credentials), exfiltration attempts, and hosts allowed from the compromise alert. | "swapped in sk-a…9f" (blue); "blocked — exfiltration attempt, VM paused" (red), or "blocked — exfiltration attempt (alerts off, VM not paused)" when the machine has exfiltration alerts turned off; "allowed by user for this session" (green) |
| Credential used | SSH signatures and AWS SigV4 signings the host performed for the agent. | "signed" (green) |
| Firewall | Egress-firewall verdicts, per host, port and protocol, with the rule that decided — or "default policy" when no rule matched — for direct connections and for those made through the proxy settings alike. The host is the name the program asked for (www.wikipedia.org), not the CDN name it resolves to. A destination is reported again only once a minute has passed since its last report, or at once after the rules change; allowed connections are listed only when the machine logs them, and their repeats fold into one row with a count. An open connection cut because the rules changed gets its own row. | "allow — allow tcp github.com:443" (green); "deny — default policy" (red); "connection closed — “allow tcp github.com:443” no longer allows it" (red); "deny" (red) for connections dropped regardless of rules (IPv6, QUIC, IP fragments) |
| Guardrails | Write-policy blocks (Guardrails), with the method and path. | "blocked — …" (red) |
| Supply chain | Every package fetch, including apt .deb downloads (Supply-Chain Protection). | "checked", "downloaded" (green); "checked — versions newer than the cooldown hidden", "install scripts stripped" (blue); "blocked — …" (red) |
| Prompt injection | Detector hits, with the detector, the source and a short snippet (Prompt-Injection Detection). | "log", "allowed" (green); "blocked" (red) |
| PII protection | Requests in which personal data was swapped, with counts by kind and the host — never the values (PII Protection) — and requests whose scan ran out of model budget. | "swapped for stand-ins" (blue); "partial — model budget reached; pattern rules only" (blue) |
| Agent delegation | Each message one agent sent another through delegation. | "relayed" (blue); "withheld — prompt injection" (red) |
| Upstream TLS | Upstream certificates the host refused to trust, and uses of the per-request insecure bypass. | "blocked — …" (red); "allowed — certificate validation skipped (X-bromure-insecure); no credentials injected" (green) |
Firewall quick actions
Firewall rows can change the machine's outbound-connection rules on the spot. Use the button in the row's last column, or right-click the row. The change is saved to the machine and applies to it immediately if it's running — no restart.
- A blocked connection — Allow host:port adds an allow rule for exactly that host, protocol and port, placed first so it wins over the rule that blocked it. When the host is a subdomain, Allow all of domain:port is offered too (for example
github.comforapi.github.com), which covers every subdomain — except under CDN and shared-hosting domains (cloudflare.net,cloudfront.net,amazonaws.com,github.io,herokuapp.com…), where "all of" would mean every customer of that provider. The other names the host resolved through (its CDN aliases) are offered as exact hosts after it. Each offers Always, For 15 minutes, For 1 hour or Until the workspace stops; a timed rule switches itself off when the time is up. If the same rule already exists, the menu first says how it stands (switched off, or on until when), so re-allowing never silently shortens it. If a deny rule blocked it, that rule can also be switched off or removed. - A connection allowed by a rule — Switch off rule keeps the rule but stops it matching (tick it again in the editor to bring it back); Remove rule deletes it. Connections the change now denies are cut.
- A connection allowed because no rule matched — Block host (or Block all of domain) adds a deny rule for every protocol and port to it.
Rules made here use the name the program asked for, the same name the proxy checks, so they hold however the program connects.
When the rules have changed since the row was recorded — a blocked host allowed since, or the reverse — the button reads Allowed now or Blocked now and its menu names the rule (or default policy) that decides now, instead of offering the same change again.
Quick actions appear only for rows that a rule change can affect: not for IPv6, QUIC or fragment drops, and not for HTTP-method blocks from web rules. On a remote Mac's rows the button is greyed out: change that machine's rules in its settings on the Mac that runs it.
Note: If the machine's settings are open, the rule table picks up the change. Unsaved edits are kept: the change is merged into them rule by rule, and a note above the table says so. If your edits can't be merged (a rule that doesn't parse yet), the note offers Reload (take the saved rules) or Keep my edits.
The Timeline records security decisions only. File reads, commands, tool calls and model usage are not in it; they belong to tracing.
Exporting events
Export… (in the toolbar on both tabs) saves events as a CSV file, named bromure-security-<date>.csv by default. From the Timeline tab it saves exactly what the table shows, with the filters applied; from the Overview tab it saves every event in the window. Rows are oldest first, with the columns time (ISO 8601), machine ("This Mac" or the remote Mac's name), workspace, engine, condition, decision and outcome (allowed, blocked or info).
Storage and retention
- Every event is appended to a daily file in
~/Library/Application Support/BromureAC/security-timeline/, one JSON line per event, named<yyyy-MM-dd>.jsonl(UTC dates). - Files older than 90 days are deleted.
- At launch the window reloads the most recent 5,000 events, and holds at most 5,000 in memory; older events stay in the files.
- Events hold previews only: token previews like
sk-a…f9q3, snippet previews, PII counts. No secret or personal value is written.
Remote Macs
The engines run on the Mac that hosts the machines. When a remote client mirrors another Mac, it receives that Mac's most recent events and shows them in its own Security Timeline window, alongside its local ones. Each mirrored Mac's events are kept apart from this Mac's, so the machine pop-up can separate them and the Workspace column names the Mac.
Relation to enterprise telemetry
On a Mac enrolled with bromure.io, the same engine events are also sent to the organization as cloud events (credential.token_swap, egress.firewall, supply_chain.fetch, prompt_injection.detection, privacy.pii_swap and others), unless the machine is in Private mode. The local Security Timeline is independent of that: it records every event whether or not the Mac is enrolled and whether or not private mode is on. See Tracing & Audit and Enterprise.