Skip to content
< ./SECURITY_PROFILE

> ./OMNISIGHT

A self-hosted endpoint network visibility and SIEM-oriented product: an endpoint agent, a local server, an operator console, installers, and a cloud control plane for licensing and updates. The interesting part is not its size. It is the boundaries I committed to before writing the first line, and what holding them cost.

Role: sole designer and engineerGo · Python · React · LinuxStatus: in development

What it does

Agents on managed endpoints report connection metadata, software inventory and system metrics to a server the customer runs on their own hardware. The server stores it, runs detection against it, matches installed software to public vulnerability data, and drives an operator console for search, alert triage and reporting.

Four-stage pipeline: endpoint agents collect metadata, inventory and metrics; the customer's own OmniSight server stores and detects; the operator console queries it; reports and alerts go out to email and to the customer's own webhook.
> Collect, store and detect, investigate, notify. Solid paths are always on. Dashed paths exist only when the operator configures them.

Endpoint agent

Go. Network metadata, inventory, heartbeat, aggregate metrics.

Local server

Python API, relational store, RBAC, audit, detection, reporting.

Operator console

React. Dashboard, event search, alert triage, vulnerabilities.

Control plane

Licensing, update delivery, rollout state, aggregate report relay.

Vulnerability service

CVE feed sync and version-aware matching against inventory.

Installers and packaging

macOS and Linux install, update, and uninstall flows.

The three boundaries

A monitoring product is, by construction, the thing with the most access on the network. That makes it a liability as much as a tool, and the design questions worth answering are about what it deliberately refuses to do.

01

Metadata only, as a contract

No packet payloads, request bodies, headers, cookies, decrypted TLS, command lines, endpoint files, or credentials. This is written into the product's terms, not just the docs — so widening it later is a contractual change with a correction sequence, not a feature flag.

02

Outbound only

The cloud never opens a connection into a customer network. The customer's server initiates every exchange: licence checks, update polls, relay sends. A compromise of my infrastructure gives an attacker no path inward.

03

Fail closed, everywhere

The email relay rejects any recipient absent from its allowlist rather than queueing it. Vulnerability matching declines to guess when it cannot resolve a version. Runtime gates refuse to start rather than starting degraded.

The customer's own infrastructure — endpoint agents, their OmniSight server and the operator console — sits inside one boundary. Managed OmniSight services sit outside it, reached only by outbound dashed connections carrying licence, update and software-version requests.
> Every arrow crossing the boundary points outward. There is no inbound path from my infrastructure into a customer network.

Where the data actually goes

Telemetry stays on the customer's server. What crosses to my infrastructure is a short, deliberate list, and every item on it is there because the feature is impossible without it — software names and versions to match vulnerabilities, aggregate summaries to deliver a report, licence and update requests. The asymmetry between the two lists is the design.

What stays on your OmniSight server and what leavesNetwork events, alerts and verdicts, system metrics and endpoint inventory, and anything identifying your internal hosts or users all stay on your own server. Only software names and versions for vulnerability matching, aggregate report summaries for email delivery, and licence and update requests leave, and only when you configure them.Your data does not cross this lineStays on your serverYour OmniSight ServerNetwork events and connection metadataAlerts, verdicts, and investigation notesSystem metrics and endpoint inventory detailAnything identifying your internal hosts or usersLeaves only whenyou configure itOmniSight CloudVulnerability IntelligenceSoftware names and versions, forvulnerability matchingAggregate report summaries, foremail deliveryLicence and update requests
> Left: everything that never leaves. Right: everything that can, and only on configuration.

Two decisions worth defending

Durable data goes over REST, never the socket

The console updates live, which usually means pushing data over a WebSocket. I push notifications that carry no payload at all — a signal that something changed, after which the browser re-fetches over the authenticated REST path. It is more work and one extra round trip. It also means the socket never becomes a second, less-audited way to read data, and that authorization is enforced in exactly one place.

The lab outage I wrote up separately is the counterweight to that decision: because the socket and REST do not share a failure domain, the socket kept reporting healthy while REST ingest was entirely blocked. Splitting them bought me a cleaner authorization story and cost me a monitoring blind spot. Both are true.

I withdrew my own release

During a security review of my own installer I found a flaw serious enough that shipping past it was not defensible. I pulled the published artifact rather than patching forward quietly, fixed the cause at the source, and left it unpublished until it could be rebuilt and reviewed properly. Publishing a new version to cover an old one leaves the old one installed on machines; withdrawing it does not.

What I would do differently

I let the documentation grow without a structure. The always-loaded set eventually reached tens of thousands of tokens because three separate documents each accumulated their own copy of the same release history, and it became genuinely unusable — for collaborators and for me. Fixing it meant separating documents that describe the present from a changelog that describes the past, and enforcing that split with a check rather than a convention.

The general lesson is the one I keep relearning: a rule nobody measures is a rule that has already been broken. Every boundary on this page has something that fails when it is crossed — a gate, a test, a script — because the ones that only existed as intentions did not hold.

root@omnisight:~

> Design the refusals first. The features will follow the shape they leave.

Deciding early what the product would never collect made most later decisions easy, because anything that needed content was simply not on the table.