Security·Runtime Defense

MCP server eBPF security: syscall monitoring, LSM hooks, and runtime threat detection

eBPF lets you observe and enforce MCP server runtime behavior at the kernel level — without modifying application code or loading kernel modules. Here's how to use Falco, Tetragon, and eBPF LSM hooks to detect and block anomalous behavior in agent workloads.

Why eBPF matters for MCP server security

Static analysis and code review tell you what an MCP server is supposed to do. eBPF tells you what it actually does at runtime. That gap matters in MCP security because:

eBPF programs run in the Linux kernel and can observe every syscall, network connection, file operation, and process fork — with negligible performance overhead (<2% CPU for typical MCP server workloads).

Pattern 1: Syscall monitoring with Falco

Falco is the CNCF runtime security tool. It uses an eBPF probe to instrument kernel syscalls and fires alerts when behavior matches a rule. A baseline rule set for MCP servers:

- rule: MCP server unexpected shell spawn
  desc: An MCP server spawned a shell — likely command injection
  condition: >
    spawned_process
    and proc.name in (node, deno)
    and proc.pname in (bash, sh, zsh, dash)
  output: "Shell spawned by MCP server (proc=%proc.name cmd=%proc.cmdline)"
  priority: CRITICAL

- rule: MCP server unexpected outbound connection
  desc: MCP server connected to an address outside its expected range
  condition: >
    outbound
    and proc.name = "node"
    and not fd.sip in (allowed_mcp_upstream_ips)
    and not fd.sport in (443, 80)
  output: "Unexpected outbound connection (dest=%fd.rip:%fd.rport proc=%proc.cmdline)"
  priority: WARNING

- rule: MCP server read of /etc/passwd or /etc/shadow
  desc: Credential file read — possible SSRF or path traversal exploitation
  condition: >
    open_read
    and proc.name = "node"
    and fd.name in (/etc/passwd, /etc/shadow, /etc/hosts)
  output: "Sensitive file read by MCP process (file=%fd.name)"
  priority: CRITICAL

Deploy Falco as a DaemonSet on Kubernetes with the eBPF driver (preferred over the kernel module for GKE/EKS where module loading is restricted):

helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
  --set driver.kind=ebpf \
  --set falcosidekick.enabled=true \
  --set falcosidekick.config.slack.webhookurl="$SLACK_WEBHOOK"

Pattern 2: Tetragon process-level enforcement

Tetragon (Cilium project) goes beyond detection — it can enforce policies by killing processes or blocking syscalls in-kernel, before the action completes. A TracingPolicy for MCP server containment:

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: mcp-server-execve-policy
spec:
  kprobes:
  - call: "sys_execve"
    syscall: true
    args:
    - index: 0
      type: "string"
    selectors:
    - matchBinaries:
      - operator: "In"
        values:
        - "/usr/local/bin/node"
      matchActions:
      - action: Sigkill
        argFqdn:
          index: 0
          operator: "NotIn"
          values:
          - "/app/server.js"
          - "/app/node_modules/.bin/*"

This policy kills any execve call from the MCP server Node process that tries to spawn a binary not in the expected set — blocking command injection exploitation at the kernel level before any damage occurs.

Pattern 3: eBPF LSM hooks for file access control

Linux Security Module (LSM) hooks via eBPF allow you to write custom access control policies in BPF bytecode. This is more flexible than SELinux/AppArmor for MCP workloads with dynamic path patterns. A libbpf-based LSM program to restrict file reads:

SEC("lsm/file_open")
int BPF_PROG(restrict_file_open, struct file *file)
{
    char fname[256];
    bpf_d_path(&file->f_path, fname, sizeof(fname));

    /* Block reads of /proc/self/environ — credential exposure vector */
    if (bpf_strncmp(fname, 19, "/proc/self/environ") == 0)
        return -EPERM;

    /* Block reads outside /app and /tmp */
    if (bpf_strncmp(fname, 4, "/app") != 0 &&
        bpf_strncmp(fname, 4, "/tmp") != 0 &&
        bpf_strncmp(fname, 4, "/etc") != 0)
        return -EPERM;

    return 0;
}

Pattern 4: Network traffic analysis with Cilium

Cilium's eBPF-based NetworkPolicy enforcement can be combined with Layer 7 visibility to detect anomalous HTTP calls from an MCP server without TLS interception:

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: mcp-server-egress
spec:
  endpointSelector:
    matchLabels:
      app: mcp-server
  egress:
  - toFQDNs:
    - matchName: "api.anthropic.com"
    - matchName: "your-db.internal"
    toPorts:
    - ports:
      - port: "443"
        protocol: TCP
      rules:
        http:
        - method: "POST"
          path: "/v1/messages"

This policy enforces that the MCP server can only make POST requests to /v1/messages on Anthropic's API — any other outbound HTTP call (like to an SSRF target) is blocked at the eBPF level.

SkillAudit and eBPF

SkillAudit's static analysis phase flags the syscall patterns that eBPF monitoring is designed to catch: exec() calls with string concatenation, unbound fetch() without allowlists, and direct process environment reads. The eBPF controls described here form the defense-in-depth layer that catches exploitation of vulnerabilities SkillAudit grades as Medium or Low — ones that exist but are harder to exploit.

For teams running MCP servers in Kubernetes, combining a SkillAudit grade ≥ B with Falco + Cilium enforcement is the recommended production baseline. Run a free audit to get your server's current grade.

Related: MCP security review checklist · Kubernetes MCP security · Process isolation and sandboxing