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.

OutputConfigureUse whenPage
Splunk HECContainer env varsYou use SplunkSplunk config
WebhookContainer env varsAnything else: Sentinel, Defender XDR, Elastic, a ticketing workflowWebhook config
Container logsOne .env lineYou already ship container stdoutBelow
🚧

Two different webhooks

These 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:

FieldMeaning
timestampEpoch seconds, with a fraction (for example 1793310476.523)
client_ipWho requested the package
registryFqdnThe firewall hostname the request arrived on, not the upstream registry
repoWhich route served it
purl / artifact_purlThe package. For npm this includes the version. For PyPI it carries the file instead, as ?artifact_filename=...
action, decisionWhat the firewall did
block_reason / warn_reasonWhy, for blocks and warnings
blocked_alertsThe alerts that caused a block
request_idMatches the ID a developer sees in a blocked install
cachedWhether 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:

DecisionDefault log levelShown by default
BlockerrorYes
Allowed with a warn alertwarnYes
Allowed with a monitor alertnoticeYes
Clean allow (ignore)debugNo

To log every decision, add this to .env and recreate the container. Block installs with Firewall already includes it.

SOCKET_IGNORE_LOG_LEVEL=warn
docker compose up -d --force-recreate
docker compose logs socket-firewall | grep SOCKET_DECISION
📘

Long events are split

On 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, or jq will fail on the fragments. Filter on the [SOCKET_DECISION prefix 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 to max_versions). Exclude proactive events when counting install blocks. PyPI is the exception in practice: pip downloads the .whl.metadata file and then the wheel, so each package logs two events with the same purl and different source_path. Dedupe on purl plus client_ip.
  • Count on decision, not action. Some allowed downloads carry action: error, for example a recently published version in an ecosystem listed in recently_published_enabled_ecosystems (Cooldown). decision is what the client actually got.
  • Client-side caches skip the firewall. A package already in a developer's npm cache or a warm .m2 directory never reaches the firewall, so there's no event.
  • Behind a load balancer, client_ip is the balancer's address until you set client_ip.header and client_ip.trusted_proxies in socket.yml. See Client IP Detection.

Did this page help you?