Security Policies

Security Policies

Overview

Security policies define the runtime behavior permitted for your CI/CD pipelines and deployments. The Runtime Sensor enforces these policies at the kernel level using eBPF technology, intercepting and validating security-relevant operations before they execute.

What Are Security Policies?

A security policy is a JSON document that specifies:

  • Allowed operations: Which processes can execute, what files can be accessed, which network connections are permitted
  • Enforcement mode: Whether to observe, enforce, or derive policy rules
  • Security boundaries: Constraints on containers, kernel operations, memory access, and inter-process communication

Policies follow a deny-by-default model—operations not explicitly permitted are blocked when enforcement is enabled.

Key Concepts

Policy Domains

Security policies cover multiple security domains:

DomainDescriptionExamples
File SystemFile and directory operationsProcess execution, file reads/writes/overwrites, path creation/deletion, renaming, linking, mounting
NetworkingTCP/IP, Unix sockets, raw socketsOutbound connections, listening ports, packet sniffing
ContainersContainer runtime operationsImage execution, socket access
MemoryMemory-related operationsMemory mapping, W+X protection
ProcessProcess managementProcess termination, resource limits, scheduling
KernelKernel-level operationseBPF programs, kernel modules, direct memory access
IPCInter-process communicationUnix sockets, System V shared memory, message queues

Enforcement Modes

Policies operate in one of three modes:

ModeBehaviorUse Case
deriveMonitor all behavior and generate policy rulesInitial setup—run your pipeline to capture baseline behavior
observeLog violations without blocking operationsTesting and refinement—validate policy before enforcement
enforceBlock unauthorized operations and fail buildsProduction—active protection against policy violations

Rule Format

Most policy rules follow a pipe-delimited format that specifies actors and targets:

actor|target
actor|target|additional_context

For example, an IP connection rule:

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

This permits the curl binary to connect to api.example.com on port 443.

Wildcards and Patterns

Policies support several pattern matching features:

PatternDescriptionExample
allMatches any value"all" permits all values for that field
{a,b,c}Brace expansion{80,443} matches port 80 or 443; {%workspace%,%tmpdir%}/bin matches either path
%home%Home directory of the user running the pipeline%home%/.config/myapp
%hostname%Hostname of the machine running the Sensor%hostname%
%tmpdir%Temporary directory ($TMP, $TMPDIR, $TEMP, or $TEMPDIR)%tmpdir%/build-cache
%uid%UID of the user running the pipeline%uid%
%user%Username of the user running the pipeline%user%
%workspace%Job workspace directory%workspace%/build/output

Policy Lifecycle

The recommended workflow for creating and deploying security policies:

1. Derive

Start with a policy in derive mode and run your pipeline:

{
    "mode": "derive"
}

After the build completes, the Runtime Sensor outputs a derived policy containing rules for all observed behavior. The Sensor automatically consolidates path-based rules by removing entries that are subpaths of other entries in the same rule group, reducing policy size before output.

2. Refine

Review the derived policy and refine it before moving to observe or enforce mode. The derive output captures exact behavior from your pipeline run, which often needs to be generalized to account for dynamic values or broader valid ranges.

Consolidate dynamic file paths

Build processes frequently generate files with dynamic, unpredictable names. The derived policy captures each specific filename observed during the run, but those names will differ on every execution. Replace them with their parent directory.

Note: Directory-prefix path matching is supported for most, but not all, path positions. Consult the Specification for the specific operation to confirm which arguments support this technique.

For example, derive may produce:

"/usr/bin/bash|/opt/myapp/tmp/custom_script12345",
"/usr/bin/bash|/opt/myapp/tmp/custom_script67890"

These represent the same program (/usr/bin/bash) operating in the same temporary directory—only the filename suffix differs. Refine this to:

"/usr/bin/bash|/opt/myapp/tmp"

At runtime, any file under /opt/myapp/tmp (including dynamically named scripts) satisfies this rule. The policy remains precise about where the operation is permitted while accommodating filenames that cannot be known in advance.

Review and broaden IP address ranges

The Runtime Sensor operates at the kernel level and works exclusively with IP addresses. When derive captures an outbound connection, it records the specific IP with a /32 mask (IPv4) or /128 mask (IPv6). Domain name resolution is best-effort and may not always succeed, so the derived policy often contains raw IPs.

A derived policy might look like:

"ip": {
  "connect": [
    "all|127.0.0.1/32|53",
    "all|127.0.0.53/32|53",
    "all|::1/128|53",
    "/usr/bin/python3.6|192.168.1.100/32|443",
    "/usr/bin/python3.6|192.168.1.101/32|443",
    "/usr/bin/python3.6|192.168.1.102/32|443",
    "/usr/bin/python3.6|192.168.1.103/32|53"
  ]
}

When refining, consider:

  • DNS traffic (port 53) — entries like all|127.0.0.1/32|53 and all|127.0.0.53/32|53 represent local DNS resolvers. These are typically safe to leave as-is or consolidate into a subnet.
  • Application connections — the /32 entries for 192.168.1.100192.168.1.103 may represent a load-balanced service or CDN. If those IPs belong to a known address range, replace the individual entries with the appropriate CIDR block (e.g., 192.168.1.0/24).
  • Completeness — the derive run captures only the IPs contacted during that specific run. Verify that the full set of valid IPs for each service is represented, especially for services that rotate addresses.

Other refinement techniques

  • Brace expansion — consolidate rules with a common prefix using {a,b,c} notation: "/usr/bin/node|/app/{src,dist,node_modules}"
  • Remove one-time entries — derived policies may include paths from install steps or first-run initialization that won’t recur. Remove entries that don’t apply to steady-state pipeline execution.

Policy too large to load

If a derived policy is applied without sufficient refinement, the Sensor may emit the following error:

Argument list too long (os error 7)

This means the policy has too many rules to load. Return to the derive output and apply the techniques above—particularly collapsing dynamic paths into parent directories and consolidating IP ranges into CIDR blocks—until the policy is compact enough to load successfully.

3. Observe

Deploy the refined policy in observe mode:

{
    "mode": "observe"
}

Run several builds and review any violations in Team Server. Adjust the policy as needed.

4. Enforce

Once builds run cleanly in observe mode, switch to enforce:

{
    "mode": "enforce"
}

The Runtime Sensor now actively blocks unauthorized operations.

Policy Management

Security policies are managed through Team Server:

  • Create policies: Define policies using the built-in editor with JSON schema validation
  • Assign policies: Link policies to pipelines for enforcement
  • Monitor violations: View and investigate policy violations
  • Version history: Track policy changes with audit logging

To create a policy in Team Server:

  1. Navigate to Policies in the main menu
  2. Click Create
  3. Enter a Name, Description, and Version
  4. Write or paste your policy JSON
  5. Click Create

To assign a policy to a pipeline:

  1. Navigate to Policies
  2. Click the Assign Policy (link icon) for your policy
  3. Search and select the pipeline(s) to protect
  4. Click Assign

Next Steps