Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Event types

An event type determines which runtime event a rule evaluates. Every event type can use process.

rule_sets:
  - ruleset_id: acme/process
    rules:
      - rule_id: network_tool_exec
        event_type: process_exec
        condition: |
          process.exec_path.endsWith("/curl") ||
          process.exec_path.endsWith("/wget")
        action: collect

process is the snapshot of the process that produced the event.

fieldTypeExample valueMeaning
process.exec_pathstring/usr/bin/curlExecutable path
process.argvlist(string)["curl", "-fsSL", "https://example.com/install.sh"]Process arguments
process.ancestorslist(object)[{exec_path: "/bin/bash", argv: ["bash", "-c", "npm install"]}]Snapshot of ancestor processes

process.ancestors is newest-first. The first element is the immediate parent, followed by the grandparent. Rule conditions should search ancestors with exists instead of index access. Each ancestor exposes exec_path, argv, and descendants. descendants contains only the processes forked below that ancestor on the path to the current process. It is ordered from that ancestor toward the current process: parent -> child. It does not include the current process itself.

condition: |
  process.ancestors.exists(parent,
    parent.exec_path.endsWith("/bash") &&
    parent.argv.exists(arg, arg == "-c")
  )

process_exec

Evaluates process execution.

fieldTypeExample valueMeaning
processobjectprocess.exec_path == "/usr/bin/curl"Executed process
is_memfdbooltrue / falseTrue for memfd-backed execution

Network tool execution:

rule_sets:
  - ruleset_id: acme/process
    rules:
      - rule_id: network_tool_exec
        event_type: process_exec
        condition: |
          process.exec_path.endsWith("/curl") ||
          process.exec_path.endsWith("/wget") ||
          process.exec_path.endsWith("/nc")
        action: collect

Shell started as a descendant of an installer or package manager:

rule_sets:
  - ruleset_id: acme/process
    rules:
      - rule_id: shell_from_package_manager
        event_type: process_exec
        condition: |
          (
            process.exec_path.endsWith("/sh") ||
            process.exec_path.endsWith("/bash")
          ) &&
          process.ancestors.exists(parent,
            parent.exec_path.endsWith("/npm") ||
            parent.exec_path.endsWith("/pip") ||
            parent.exec_path.endsWith("/bundle")
          )
        action: detect

memfd-backed execution:

condition: is_memfd

Example event value:

{
  "event_type": "process_exec",
  "process": {
    "exec_path": "/usr/bin/curl",
    "argv": ["curl", "-fsSL", "https://example.com/install.sh"],
    "ancestors": [
      {"exec_path": "/bin/bash", "argv": ["bash", "-c", "curl -fsSL https://example.com/install.sh"]}
    ]
  },
  "payload": {
    "is_memfd": false
  }
}

network_connect

Evaluates outbound network connections.

fieldTypeExample valueMeaning
remote_ipstring203.0.113.10, 2001:db8::1Destination IP address
remote_portint443, 53Destination port
protocolstringtcp, udpProtocol
familystringipv4, ipv6Destination address family
processobjectprocess.exec_path == "/usr/bin/curl"Process that created the connection

Outbound TCP connection from curl / wget:

rule_sets:
  - ruleset_id: acme/network
    rules:
      - rule_id: network_tool_outbound
        event_type: network_connect
        condition: |
          protocol == "tcp" &&
          remote_port == 443 &&
          (
            process.exec_path.endsWith("/curl") ||
            process.exec_path.endsWith("/wget")
          )
        action: collect

Connection to private networks:

condition: |
  family == "ipv4" &&
  (
    inIpRange(remote_ip, "10.0.0.0/8") ||
    inIpRange(remote_ip, "172.16.0.0/12") ||
    inIpRange(remote_ip, "192.168.0.0/16")
  )

Example event value:

{
  "event_type": "network_connect",
  "process": {
    "exec_path": "/usr/bin/curl",
    "argv": ["curl", "https://registry.npmjs.org/"]
  },
  "payload": {
    "remote_ip": "104.16.24.34",
    "remote_port": 443,
    "protocol": "tcp",
    "family": "ipv4"
  }
}

unix_socket_connect

Evaluates Unix domain socket connections.

fieldTypeExample valueMeaning
pathstring/run/docker.sock, @dbus-7Socket path. Abstract namespace sockets are represented as @....
socket_typestringstream, dgram, seqpacket, unknownSocket type
is_abstractbooltrue / falseTrue for abstract namespace sockets
processobjectprocess.exec_path == "/usr/bin/docker"Process that connected to the socket

Docker socket access:

rule_sets:
  - ruleset_id: acme/socket
    rules:
      - rule_id: docker_socket_access
        event_type: unix_socket_connect
        condition: |
          socket_type == "stream" &&
          !is_abstract &&
          (
            path == "/var/run/docker.sock" ||
            path == "/run/docker.sock"
          )
        action: detect

Example event value:

{
  "event_type": "unix_socket_connect",
  "process": {
    "exec_path": "/usr/bin/docker",
    "argv": ["docker", "ps"]
  },
  "payload": {
    "path": "/run/docker.sock",
    "socket_type": "stream",
    "is_abstract": false
  }
}

file_open

Evaluates file open events.

fieldTypeExample valueMeaning
pathstring/home/runner/.npmrc, /workspace/.envOpened file path
is_readbooltrue / falseTrue when read access is included
is_writebooltrue / falseTrue when write access is included
flagsint0, 66Open flags
processobjectprocess.exec_path == "/bin/cat"Process that opened the file

Credential file read:

rule_sets:
  - ruleset_id: acme/file
    rules:
      - rule_id: package_credential_read
        event_type: file_open
        condition: |
          is_read &&
          (
            path.endsWith("/.npmrc") ||
            path.endsWith("/.pypirc") ||
            path.endsWith("/.docker/config.json")
          )
        action: collect

Credential file read by a descendant of a shell:

condition: |
  is_read &&
  path.endsWith("/.npmrc") &&
  process.ancestors.exists(parent,
    parent.exec_path.endsWith("/sh") ||
    parent.exec_path.endsWith("/bash")
  )

Example event value:

{
  "event_type": "file_open",
  "process": {
    "exec_path": "/bin/cat",
    "argv": ["cat", "/home/runner/.npmrc"]
  },
  "payload": {
    "path": "/home/runner/.npmrc",
    "is_read": true,
    "is_write": false,
    "flags": 0
  }
}

file_remove

Evaluates file or directory removal.

fieldTypeExample valueMeaning
pathstring/workspace/.env, /var/log/journalRemoved path
is_folderbooltrue / falseTrue for directory removal
processobjectprocess.exec_path == "/bin/rm"Process that removed the path

Secret file removal:

condition: |
  !is_folder &&
  (
    path.endsWith("/.npmrc") ||
    path.endsWith("/.pypirc")
  )

Use !is_folder when you want to exclude directory removals and match only file unlink events.

Example event value:

{
  "event_type": "file_remove",
  "process": {
    "exec_path": "/bin/rm",
    "argv": ["rm", "/workspace/.env"]
  },
  "payload": {
    "path": "/workspace/.env",
    "is_folder": false
  }
}

file_move

Evaluates rename / move events.

fieldTypeExample valueMeaning
from_pathstring/tmp/payload.binOriginal path
to_pathstring/usr/local/bin/curlNew path
processobjectprocess.exec_path == "/bin/mv"Process that renamed / moved the path

Move from a temporary path to an executable path:

condition: |
  from_path.startsWith("/tmp/") &&
  (
    to_path.startsWith("/usr/local/bin/") ||
    to_path.startsWith("/usr/bin/")
  )

Example event value:

{
  "event_type": "file_move",
  "process": {
    "exec_path": "/bin/mv",
    "argv": ["mv", "/tmp/payload.bin", "/usr/local/bin/curl"]
  },
  "payload": {
    "from_path": "/tmp/payload.bin",
    "to_path": "/usr/local/bin/curl"
  }
}

Evaluates hardlink / symlink creation.

fieldTypeExample valueMeaning
created_pathstring/tmp/copy, /usr/local/bin/curlNewly created link / symlink path
existing_pathstring/etc/shadow, /tmp/wrapperExisting target path
is_hardlinkbooltrue / falseTrue for hardlinks
is_symlinkbooltrue / falseTrue for symlinks
processobjectprocess.exec_path == "/bin/ln"Process that created the link

Hardlink to /etc/shadow:

condition: is_hardlink && existing_path == "/etc/shadow"

Symlink from a temporary path to an executable path:

condition: |
  is_symlink &&
  created_path.startsWith("/usr/local/bin/") &&
  existing_path.startsWith("/tmp/")

Example event value:

{
  "event_type": "file_link",
  "process": {
    "exec_path": "/bin/ln",
    "argv": ["ln", "-s", "/tmp/wrapper", "/usr/local/bin/curl"]
  },
  "payload": {
    "created_path": "/usr/local/bin/curl",
    "existing_path": "/tmp/wrapper",
    "is_hardlink": false,
    "is_symlink": true
  }
}

mount

Evaluates mount attempts that may expose or relocate a mount tree through another path. The event records classic bind and move requests and new-API move_mount requests from tracked jobs. It does not represent every filesystem mount, and the recorded attempt is not guaranteed to have succeeded.

fieldTypeExample valueMeaning
source_pathstring/tmp/sourceMount source. For classic mount(2), this is the raw source string
target_pathstring/mnt/targetMount target path
processobjectprocess.exec_path == "/bin/mount"Process that attempted the mount

Because a classic source_path may be relative, symlinked, or otherwise non-canonical, source matching is a best-effort signal rather than a strict security boundary.

Protected path exposed through another location:

condition: source_path.startsWith("/protected/") && !target_path.startsWith("/protected/")

Example event value:

{
  "event_type": "mount",
  "process": {
    "exec_path": "/bin/mount",
    "argv": ["mount", "--bind", "/tmp/source", "/mnt/target"]
  },
  "payload": {
    "source_path": "/tmp/source",
    "target_path": "/mnt/target"
  }
}

The paths describe the mount operation, not a canonical identity for later file writes. The classic mount source is the raw source string supplied to the mount operation. Target paths and new-API move paths use a filesystem-rooted dentry walk and can expose node-side backing paths for Kubernetes volumes. A move_mount event can represent a detached mount attachment, a mount tree relocation, or another operation routed through the same kernel hook; rules should rely on path and process context rather than infer that distinction.

domain

Evaluates domain access.

fieldTypeExample valueMeaning
domainstringregistry.npmjs.org, example.comQuery domain. Lowercase, with trailing dot removed.
sourcestringdnsObservation source. Currently mainly dns.
processobjectprocess.exec_path == "/usr/bin/npm"Process that caused the domain access

Access outside known internal domains:

condition: |
  source == "dns" &&
  !domain.endsWith(".corp.example.com")

Suspicious domain access from a package-manager descendant:

condition: |
  source == "dns" &&
  process.ancestors.exists(parent,
    parent.exec_path.endsWith("/npm") ||
    parent.exec_path.endsWith("/pip")
  )

Example event value:

{
  "event_type": "domain",
  "process": {
    "exec_path": "/usr/bin/npm",
    "argv": ["npm", "install"]
  },
  "payload": {
    "domain": "registry.npmjs.org",
    "source": "dns"
  }
}