Data
Get every firewall decision out of the container and into your SIEM.
Every package download the firewall checks produces a decision event: allowed, warned, monitored, or blocked. You can ship those events three ways.
| Output | Configure | Use when | Page |
|---|---|---|---|
| Splunk HEC | Container env vars | You use Splunk | Splunk config |
| Webhook | Container env vars | Anything else: Sentinel, Defender XDR, Elastic, a ticketing workflow | Webhook config |
| Container logs | One .env line | You already ship container stdout | Below |
Two different webhooksThese pages cover the firewall's webhook, set by environment variables on the container. The webhook under Dashboard → Settings → Webhooks is separate and only carries scan and alert events, not install decisions.
What an event contains
Each event is JSON with event_type: firewall_package_encountered and these fields:
| Field | Meaning |
|---|---|
timestamp | Epoch seconds, with a fraction (for example 1793310476.523) |
client_ip | Who requested the package |
registryFqdn | The firewall hostname the request arrived on, not the upstream registry |
repo | Which route served it |
purl / artifact_purl | The package. For npm this includes the version. For PyPI it carries the file instead, as ?artifact_filename=... |
action, decision | What the firewall did |
block_reason / warn_reason | Why, for blocks and warnings |
blocked_alerts | The alerts that caused a block |
request_id | Matches the ID a developer sees in a blocked install |
cached | Whether the verdict came from the firewall's cache |
Container logs (one setting)
Decisions are written to stdout as [SOCKET_DECISION] lines followed by JSON, but each kind is logged at its own level, and clean allows are hidden by default:
| Decision | Default log level | Shown by default |
|---|---|---|
| Block | error | Yes |
| Allowed with a warn alert | warn | Yes |
| Allowed with a monitor alert | notice | Yes |
| Clean allow (ignore) | debug | No |
To log every decision, add this to .env and recreate the container. Block installs with Firewall already includes it.
SOCKET_IGNORE_LOG_LEVEL=warndocker compose up -d --force-recreate
docker compose logs socket-firewall | grep SOCKET_DECISION
Long events are splitOn some firewall versions, events too long for one log line are split across lines tagged
[SOCKET_DECISION 1/2],[SOCKET_DECISION 2/2]. If you see these, reassemble them before parsing, orjqwill fail on the fragments. Filter on the[SOCKET_DECISIONprefix rather than on log level.
Things that apply to every output
- Events fire on downloads only, unless metadata filtering is on. Without metadata filtering, package metadata requests don't produce events. With it, each listing logs one
event_category: "proactive"event per version checked (up tomax_versions). Excludeproactiveevents when counting install blocks. PyPI is the exception in practice: pip downloads the.whl.metadatafile and then the wheel, so each package logs two events with the samepurland differentsource_path. Dedupe onpurlplusclient_ip. - Count on
decision, notaction. Some allowed downloads carryaction: error, for example a recently published version in an ecosystem listed inrecently_published_enabled_ecosystems(Cooldown).decisionis what the client actually got. - Client-side caches skip the firewall. A package already in a developer's npm cache or a warm
.m2directory never reaches the firewall, so there's no event. - Behind a load balancer,
client_ipis the balancer's address until you setclient_ip.headerandclient_ip.trusted_proxiesinsocket.yml. See Client IP Detection.
Updated 8 days ago