Skip to content

Specification

JSON policy formats, matching rules, and supported operations.

Policy Structure

A policy is a JSON object. Only mode is required; add operation sections as needed:

{
  "mode": "observe",
  "path": {
    "open": [
      "all|%workspace%"
    ]
  }
}

Omitted or empty sections and operations grant no permissions. A mode-only enforce policy treats every covered operation as a violation; hook capabilities determine enforcement.

Limits: 1,024 brace combinations per rule, 8,192 bytes per expanded expression register, and 262,144 bytes of authored policy content in Team Server.

Operation Index

Common Patterns

These patterns apply across operation formats.

The all Wildcard

The string "all" matches any value for that position in a rule:

"connect": ["all"]

Use all only where the broad match is intentional.

Pipe-Delimited Rules

Most rules use pipes (|) to separate components:

component1|component2|component3

Example:

/usr/bin/curl|api.example.com|443

The <anonymous> Value

The special value <anonymous> denotes a target that has no on-disk path. It appears across several operations, for example, fileless/memfd execution in path.execute and anonymous memory mappings in mmap.file. Authorize it only when your build legitimately performs such operations.

Brace Expansion

Use braces to match multiple values:

{value1,value2,value3}

Examples:

  • {80,443} matches port 80 or 443
  • {/bin,/usr/bin}/bash matches /bin/bash or /usr/bin/bash
  • {http,https}://example.com matches either protocol

Variables can be used inside braces:

  • {%workspace%,%home%}/bin matches the workspace or home bin subdirectory
  • {%home%/.local/bin,/usr/bin}/app matches the app binary in either location

Whitespace and Escaping

Whitespace inside a value is significant. /srv/My Project/build names a directory called My Project, and matches only that directory.

Whitespace is ignored only where the grammar already has a delimiter, so these are equivalent:

all|/usr/bin/bash
  all  |  /usr/bin/bash
/usr/{bin,local/bin}/node
/usr/{ bin , local/bin }/node

The characters \ { } , % | are structure. To use one literally, escape it with a backslash:

\\   a literal backslash
\{   a literal opening brace
\}   a literal closing brace
\,   a literal comma
\%   a literal percent sign
\|   a literal pipe, which does NOT separate components
\    a backslash followed by a space, keeping a space at the very
     start or end of a value that would otherwise be trimmed

Any other escape is rejected, so a mistyped path fails loudly instead of silently matching nothing.

JSON requires an additional level of escaping

A policy file is JSON, which has its own backslash escaping. One literal backslash in a path is written as four in the file: "all|/srv/back\\\\slash" is the rule for /srv/back\slash.

No component may be empty. all| and a||b are rejected, because an empty component would match everything rather than nothing.

Runtime Variables

Use %workspace%, %home%, %hostname%, %uid%, and %user% for job-specific values, for example %workspace%/build or %home%/.config. See runtime values and variable scopes.

Undefined Variables

Team Server expands custom variables from effective system/policy scope. It leaves the five runtime variables for the Sensor to bind at job start. Direct local policies support only those runtime variables.

Unresolved names reject the policy rather than expanding to empty paths:

unresolved variable 'cache' in '%cache%/files'

%workspace%, %hostname%, and %uid% always have values. If the caller’s verified UID has no host account, %home% and %user% use literal <undefined>.

Derived Policies

The Sensor omits empty rule lists and simplifies observed rules. It can replace transient paths, including package-manager staging paths, with stable parents; path.rename widens source/destination together only when observed pairs support both. Redundancy removal compares every component, including numeric network containment. Brace consolidation preserves observed relationships without adding unobserved combinations.

Directory Prefix Matching

Every file-path argument supports directory prefix matching: a rule specifying a directory path matches any path beneath it. For example, /opt/myapp/tmp matches /opt/myapp/tmp/script12345.

One identity-style field is matched exactly rather than as a directory prefix: the path.quota device name.

Mode

Required field.

{
  "mode": "observe"
}
ValueDescription
deriveMonitor all behavior and auto-generate policy rules. The Runtime Sensor outputs a derived policy when the job completes.
observeLog violations without blocking. Use for testing and refinement.
enforceDeny unauthorized operations through LSM hooks and, by default, terminate offending tasks on LSM and fallback paths. ENDURA_SENSOR_KILL_TASK=false disables termination while retaining direct denial.

Policies are deny-by-default in enforce mode. Follow the policy lifecycle before enabling enforcement.

Container Operations

container.run

Specifies which container images can be executed.

Format: image|tag

"container": {
  "run": [
    "registry.example.com/web/nginx|1.0.0",
    "gcr.io/myproject/myapp|v1.0",
    "quay.io/podman/hello|all"
  ]
}

container.socket

Controls privileged socket exposure to containers.

Format: image|tag

"container": {
  "socket": [
    "registry.example.com/build/docker|1.0.0",
    "gcr.io/myproject/builder|all",
    "all|production"
  ]
}

Container-runtime socket access grants host-level control; permit it only when required.

File System Operations

path.execute

Specifies which programs can be executed.

Format: grandparent_path|parent_path|target_path

The fields are the caller’s parent executable, the calling executable, and the target executable. For example, /bin/sudo|/bin/bash|/usr/bin/whoami describes sudo → bash → whoami. These are executable identities; use file-access rules for Makefiles and source inputs. Derive script/interpreter chains from actual runs.

"path": {
  "execute": [
    "/bin/sudo|/bin/bash|/usr/bin/whoami",
    "all|/bin/bash|%workspace%/scripts/build.sh",
    "{/bin,/usr/bin}/bash|all|{/bin,/usr/bin}/{ls,cat,grep}"
  ]
}

The special value <anonymous> matches fileless execution via memfd_create.

path.create

Controls file and directory creation.

Format: process_path|target_path

"path": {
  "create": [
    "/bin/touch|/var/log/app.log",
    "/usr/bin/mkdir|%workspace%/build",
    "all|/tmp"
  ]
}

This operation covers creation of ordinary files, directories, cron entries, rc scripts, and service files.

path.delete

Controls file and directory deletion.

Format: process_path|target_path

"path": {
  "delete": [
    "/bin/rm|%workspace%/build",
    "/usr/bin/make|%workspace%/obj",
    "all|/tmp"
  ]
}

path.link

Controls hard link creation.

Format: process_path|source_path|destination_path

"path": {
  "link": [
    "/bin/ln|%workspace%|%workspace%",
    "/usr/bin/cp|%workspace%|%workspace%",
    "all|all|/tmp"
  ]
}

Hard links create additional directory entries that point to the same inode.

Hard links can create alternate paths to protected files; restrict them when controls depend on one location.

path.mount

Controls filesystem mount operations.

Format: process_path|source|mount_point

"path": {
  "mount": [
    "/bin/mount|/dev/sda1|/mnt",
    "/bin/mount|/tmp/overlay|/tmp/merged",
    "/usr/bin/runc|all|all"
  ]
}

Mounts can replace visible content. Permit only required sources and mount points.

path.open

Controls file opens, including opens for reading or writing. This operation does not filter by the requested access mode. Receiving a file descriptor through a Unix socket can also trigger this check.

Format: process_path|file_path

"path": {
  "open": [
    "/bin/cat|/etc/passwd",
    "/usr/bin/app|/var/lib/app/config.yaml",
    "all|%workspace%"
  ]
}

Use narrow process and path values for sensitive files such as /etc/shadow, SSH keys, and credentials.

path.overwrite

Controls writable O_TRUNC opens of existing, nonempty files. Empty files do not trigger it; path.write covers appends and in-place changes.

Format: process_path|file_path

"path": {
  "overwrite": [
    "/usr/bin/gcc|%workspace%/build/output.o",
    "/usr/bin/cp|%workspace%",
    "all|/tmp"
  ]
}

path.write

Controls file modification.

Format: process_path|file_path

"path": {
  "write": [
    "/usr/bin/gcc|%workspace%/build/output.o",
    "/usr/bin/npm|%workspace%/node_modules",
    "all|/tmp"
  ]
}

Restrict writes to system files, configuration, and binaries to the processes that require them.

path.quota

Controls disk quota operations.

Format: process_path|device|quota_command

"path": {
  "quota": [
    "/usr/bin/quota|sda1|getquota",
    "all|sda1|setquota"
  ]
}

Supported quota commands are sync, quotaon, quotaoff, getfmt, getinfo, setinfo, getquota, setquota, and getnextquota.

Quota changes can exhaust storage; restrict them to filesystem administrators.

path.rename

Controls file and directory renaming.

Format: process_path|old_path|new_path

"path": {
  "rename": [
    "/bin/mv|%workspace%|%workspace%",
    "/usr/bin/install|all|/usr/local/bin",
    "all|%workspace%|%workspace%"
  ]
}

Rename operations can replace a target path atomically.

Authorize rename separately when replacing a target with a completed file.

path.symlink

Controls symbolic link creation.

Format: process_path|link_path

"path": {
  "symlink": [
    "/bin/ln|%workspace%",
    "/usr/bin/npm|%workspace%/node_modules",
    "all|/tmp"
  ]
}

Unlike hard links, symbolic links can cross filesystem boundaries and point to targets that do not yet exist.

Symbolic links redirect path-based operations; restrict permitted link paths.

path.pivot

Controls pivot_root operations that change the filesystem root.

Format: process_path|old_root_path|new_root_path

"path": {
  "pivot": [
    "/usr/bin/runc|/tmp/old|/tmp/new",
    "/usr/bin/containerd|all|all"
  ]
}

Permit pivot_root only for processes that intentionally replace their filesystem root.

path.chroot

Controls chroot operations.

Format: process_path|chroot_path

"path": {
  "chroot": [
    "/usr/sbin/sshd|/var/chroot/ssh",
    "/usr/bin/app|all"
  ]
}

IP Networking

Control TCP/IP socket operations for both IPv4 and IPv6. Numeric ports range from 0 through 65535, inclusive. For ip.bind, port 0 asks the kernel to select an available ephemeral port.

ip.bind

Specifies which processes can listen for inbound connections.

Format: executable_path|ip_address/CIDR|port

"ip": {
  "bind": [
    "/usr/bin/nginx|0.0.0.0/0|{80,443}",
    "/usr/bin/node|{127.0.0.1/32,::1/128}|3000",
    "/usr/bin/node|::/128|0",
    "all|::/0|8080"
  ]
}

ip.connect

Specifies which outbound connections are permitted.

Format: executable_path|ip_address_or_hostname/CIDR|port

"ip": {
  "connect": [
    "/usr/bin/curl|{api.example.com,140.82.112.0/20,github-api-ip4}|443",
    "all|140.82.112.0/20|443",
    "/usr/bin/apt-get|archive.ubuntu.com|{80,443}"
  ]
}

Hostnames and Provider Selectors

Brace members can be CIDRs, hostnames, provider selectors, or all; each is validated independently. all makes narrower alternatives redundant.

At each job start, ordinary hostnames resolve to exact IPv4/IPv6 addresses as absolute DNS names, without search domains. Use fully qualified names. Lookup failure does not reject the policy: ip.connect can learn addresses later; ip.bind remains unresolved until reload.

Live ip.connect learning preserves executable/port restrictions within the current job. It never expands ip.bind after load:

SourceCoverage and limits
Packet DNSCorrelated UDP port 53 A/AAAA queries and answers; unambiguous CNAME chains up to eight aliases; up to 64 answer records per response. TCP, TLS, and HTTPS DNS packets are excluded.
Host resolver hooksSuccessful host-glibc getaddrinfo results expand rules before the application resumes. Includes hosts files, resolve NSS, nscd/SSSD caches, and encrypted-DNS results returned through that function.

Resolver hooks use PID 1’s glibc through configured host procfs. Private container libc, musl, static resolvers, gethostbyname*, and direct NSS calls are excluded. Restart the Sensor after replacing host glibc.

Each resolver call examines up to 32 result nodes, captures up to eight unique addresses, and considers the first eight stored hostname templates matching exact executables or all. Storage order need not match policy order. Keep each hostname within eight templates for reliable resolver expansion; directory-prefix and additional templates depend on packet DNS.

A hostname permits at most 16 live executable/port templates; a job permits 4,096 total. Exceeding these rejects loading with domain <domain> exceeds 16 live ip.connect templates or policy exceeds 4096 live ip.connect templates.

Provider selectors use startup CIDR feeds for AWS, Azure, GCP, GitHub, and Linode, never hostname lookup. Ranges remain fixed until restart; failed feeds leave empty selectors. Derivation retains observed DNS names and adds provider aliases only for downloaded ranges. Otherwise it uses an observed or reverse-DNS name, or exact /32//128 address.

See feed access and trust. Use explicit CIDRs when coverage must not depend on DNS or feeds.

Unix Domain Sockets

unix.bind

Specifies which processes can create Unix sockets.

Format: process_path|socket_path

"unix": {
  "bind": [
    "/usr/bin/app|/tmp/app.sock",
    "/usr/bin/postgres|/var/run/postgresql/.s.PGSQL.5432"
  ]
}

unix.connect

Specifies which processes can connect to Unix sockets.

Format: process_path|socket_path

"unix": {
  "connect": [
    "/usr/bin/docker|/var/run/docker.sock",
    "/usr/bin/psql|/var/run/postgresql/.s.PGSQL.5432"
  ]
}

Advanced Socket Operations

Control raw sockets, packet manipulation, and process I/O backed by an AF_INET or AF_INET6 socket, features commonly used by network tools and potentially by attack tools.

socket.packet

Controls packet-level network access at the data link layer.

Format: process_path

"socket": {
  "packet": [
    "/usr/bin/tcpdump",
    "/usr/bin/wireshark"
  ]
}

Provides raw Ethernet frame access. Used by packet capture tools.

socket.raw

Controls raw IP socket creation.

Format: process_path

"socket": {
  "raw": [
    "/usr/bin/ping",
    "/usr/bin/traceroute"
  ]
}

Used for ICMP tools, port scanning, and custom protocols. Bypasses the TCP/UDP layer.

socket.inject

Controls packet injection capabilities.

Format: process_path

"socket": {
  "inject": [
    "/usr/bin/hping3",
    "/usr/bin/nmap"
  ]
}

Enables IP header modification, broadcast, and TX ring operations.

socket.sniff

Controls promiscuous mode (network sniffing).

Format: process_path

"socket": {
  "sniff": [
    "/usr/bin/tcpdump",
    "/usr/bin/tshark"
  ]
}

Promiscuous mode exposes other processes’ traffic; restrict it to approved diagnostics.

socket.stdio

Controls execution with stdin, stdout, or stderr backed by an AF_INET or AF_INET6 socket.

Format: process_path|target_path

process_path performs execution; target_path is the executed program.

"socket": {
  "stdio": [
    "/usr/sbin/xinetd|/usr/sbin/in.telnetd",
    "/usr/lib/systemd/systemd|/usr/libexec/myservice",
    "all|/usr/sbin/sshd"
  ]
}

This covers reverse shells (bash -i >& /dev/tcp/..., nc -e, socat) and legitimate socket-activated services (inetd/xinetd, Accept=yes systemd units, sshd children). Permit required pairs explicitly. Unix domain socket-backed streams are excluded.

Review network-backed streams and permit only required service/session pairs.

Netlink Sockets

Control kernel-userspace communication for network configuration.

netlink.bind

Specifies which processes can create netlink sockets.

Format: process_path

"netlink": {
  "bind": [
    "/usr/bin/ip",
    "/usr/bin/ss",
    "/usr/sbin/NetworkManager"
  ]
}

Used by network tools like ip, ss, and network managers for kernel communication.

Virtual Sockets (vsock)

Control VM-to-host and VM-to-VM communication.

vsock.bind

Specifies which processes can bind vsock ports.

Format: process_path|port

"vsock": {
  "bind": [
    "/usr/bin/app|1234",
    "/usr/bin/app|all"
  ]
}

vsock.connect

Specifies which processes can connect via vsock.

Format: process_path|port

"vsock": {
  "connect": [
    "/usr/bin/app|1234"
  ]
}

Used in VMware, KVM, and Firecracker for VM-host communication.

Process Hooks and Debugging

Control debugging tools and code injection mechanisms, commonly abused in attacks.

hook.ptrace

Controls process tracing operations.

Format: tracer_path|target_path

"hook": {
  "ptrace": [
    "/usr/bin/strace|all",
    "/usr/bin/gdb|/usr/bin/myapp"
  ]
}

This operation covers debugger attachment by tools such as gdb, strace, and ltrace.

hook.traceme

Controls anti-debugging via PTRACE_TRACEME. Detects processes that request their parent trace them, a technique used by malware to prevent debuggers and security tools from attaching.

Format: process_path

"hook": {
  "traceme": [
    "/usr/bin/myapp",
    "%workspace%/build/output"
  ]
}

hook.ptrace covers PTRACE_ATTACH/PTRACE_SEIZE; hook.traceme covers PTRACE_TRACEME. Authorize independently.

hook.wx

Controls writable and executable memory (W+X).

Format: process_path

"hook": {
  "wx": [
    "/usr/bin/java",
    "/usr/bin/node",
    "/usr/bin/python3"
  ]
}

Writable/executable memory permits dynamic code execution; allow only required JIT runtimes or programs.

hook.preload

Controls execution pairs where the target is invoked with LD_PRELOAD set.

Format: current_path|target_path

"hook": {
  "preload": [
    "/usr/bin/bash|/usr/bin/myapp",
    "all|/usr/bin/node",
    "/usr/bin/make|{/usr/bin/gcc,/usr/bin/g++}"
  ]
}

LD_PRELOAD can replace target functions; allow only required execution pairs.

Memory Operations

mmap.file

Controls mappings requested with both PROT_WRITE and PROT_EXEC; other mappings are excluded. Use hook.wx for W+X transitions through mprotect.

Format: process_path|mapped_file_path

"mmap": {
  "file": [
    "/usr/bin/app|/lib/x86_64-linux-gnu/libc.so.6",
    "/usr/bin/app|<anonymous>"
  ]
}

The special value <anonymous> matches anonymous mappings requested with both write and execute permissions.

Kernel Operations

kernel.ebpf

Specifies which processes can load eBPF programs.

Format: process_path

"kernel": {
  "ebpf": [
    "/usr/bin/bpftrace",
    "/usr/bin/bpftool"
  ]
}

Used for kernel tracing, packet filtering, and security monitoring.

kernel.module

Controls kernel requests to load a module by name, such as an operation that triggers automatic loading of a network module. It does not describe every explicit module-loading syscall.

Format: process_path|module_name

"kernel": {
  "module": [
    "/sbin/modprobe|nfs",
    "/usr/sbin/ip|dummy",
    "all|overlay"
  ]
}

Kernel modules have unrestricted system access; permit only required processes and module names.

kernel.read

Controls which module files the kernel may read during module loading.

Format: process_path|module_path

"kernel": {
  "read": [
    "/sbin/insmod|/lib/modules/6.1/kernel/drivers/net/dummy.ko",
    "/usr/bin/kmod|%workspace%/mymodule.ko",
    "all|/lib/modules"
  ]
}

kernel.read evaluates the module file read during loading. kernel.module evaluates a kernel request for a module name. These are separate checks; do not assume that permitting one covers the other or that every loading path triggers both.

IOCTL Operations

ioctl.cmd

Specifies permitted IOCTL commands.

Format: process_path|device_path|command_number

"ioctl": {
  "cmd": [
    "/usr/bin/app|/dev/tty|all",
    "all|/dev/null|{21523,21584}",
    "/usr/bin/app|all|12345"
  ]
}

Use decimal command numbers. Hexadecimal strings such as 0x5401 are invalid.

Privilege Escalation

Control selected Linux capability checks.

privilege.escalate

Controls supported capability checks. It evaluates use, grants no capability bits, and cannot override operating-system denial.

Format: executable_path|{capabilities}

"privilege": {
  "escalate": [
    "/usr/bin/sudo|{setuid,setgid}",
    "/usr/bin/chown|chown",
    "/usr/bin/ip|netadmin"
  ]
}

Supported capability names are lowercase and do not use the CAP_ prefix or underscores:

CapabilityDescription
chownChange file ownership
dacoverrideBypass discretionary file-access checks
fownerBypass checks that require matching the file owner
setgidChange process group identities
setuidChange process user identities
netadminPerform network administration
sysadminPerform broad system-administration operations

Task/Process Management

task.kill

Specifies which processes can terminate others.

Format: killer_path|target_path

"task": {
  "kill": [
    "/usr/bin/kill|all",
    "/usr/bin/systemctl|all",
    "/usr/bin/app|/usr/bin/app"
  ]
}

Monitors attempts to kill security tools and critical processes.

task.rlimit

Controls resource limit modifications.

Format: current_path|target_path|resource_type

"task": {
  "rlimit": [
    "/usr/bin/systemd|all|nofile",
    "/usr/bin/app|all|{nofile,nproc}"
  ]
}

Resource types:

ResourceDescription
cpuCPU time limit
fsizeMaximum file size
dataProcess data-segment size
stackStack size limit
coreCore-dump size
rssResident set size
nprocNumber of processes
nofileNumber of open file descriptors
memlockLocked memory
asAddress-space size
locksFile locks
sigpendingPending signals
msgqueuePOSIX message-queue bytes
niceProcess nice value
rtprioReal-time priority
rttimeReal-time CPU time
nlimitsKernel resource-limit count

task.schedule

Controls scheduling priority modifications.

Format: current_path|target_path

"task": {
  "schedule": [
    "/usr/bin/chrt|all",
    "/usr/bin/app|all"
  ]
}

task.nice

Controls nice value (CPU priority) modifications.

Format: current_path|target_path

"task": {
  "nice": [
    "/usr/bin/nice|all",
    "/usr/bin/renice|all"
  ]
}

Nice values range from -20 (highest priority) to +19 (lowest priority).

task.pgroup

Controls process group modifications.

Format: current_path|target_path

"task": {
  "pgroup": [
    "/bin/bash|all",
    "/usr/bin/app|/usr/bin/app"
  ]
}

System V IPC

sysv.shmem

Controls shared memory operations.

Format: process_path|memory_key

"sysv": {
  "shmem": [
    "/usr/bin/postgres|5432",
    "/usr/bin/app|123456",
    "all|789012"
  ]
}

sysv.msgqueue

Controls message queue operations.

Format: process_path|message_key

"sysv": {
  "msgqueue": [
    "/usr/bin/app|123456",
    "/usr/bin/worker|all",
    "all|789012"
  ]
}