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
  }
}

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"
  }
}