Hardening Ollama: Blue Team Defense Guide

Hardening Ollama: Blue Team Defense Guide

Overview & Defensive Context#

In our morning research breakdown, we dissected the mechanics of CVE-2024-37032 (dubbed "Probllama")—a critical vulnerability in the open-source Ollama AI model runner carrying a CVSS score of 9.8 (CWE-22 / CWE-73). We analyzed how threat actors abuse Ollama's unauthenticated HTTP API on TCP port 11434 by dispatching rogue model pull requests (POST /api/pull). By leveraging unvalidated layer digests containing path traversal sequences (such as sha256-../../../../../../etc/ld.so.preload), an external attacker can stream arbitrary binary blobs directly into sensitive system paths, resulting in pre-authentication remote code execution (RCE) and complete host takeover.

For AI platform engineers, DevSecOps teams, and enterprise security architects, Probllama highlights systemic architectural weaknesses common to first-generation AI infrastructure:

  • Zero Authentication by Design: Ollama's API was conceived as a local developer tool. It natively lacks authentication, user accounts, API key validation, or role-based access control (RBAC). When deployed in cloud environments or container clusters, instances are routinely bound to 0.0.0.0:11434 without an authentication gateway, exposing administrative primitives directly to untrusted networks.
  • Asymmetric Network Trust & Unrestricted Egress: Standard firewall perimeters monitor inbound traffic but permit unrestricted outbound egress for inference nodes to pull multi-gigabyte model weights. When an unauthenticated POST /api/pull is received, Ollama initiates an outbound HTTP/HTTPS connection to the attacker's registry, bypassing inbound inspection and pulling malicious payloads through trusted outbound channels.
  • High-Privilege Execution in AI Containers: Many standard Docker containers and quick-start deployment guides run the Ollama daemon as root inside the container. When combined with shared host volumes or permissive container configurations, writing to /etc/ld.so.preload immediately compromises the container and provides a high-leverage beachhead for container breakout and cluster-wide pivoting.

[!WARNING] Because Ollama can download arbitrary model definitions and write files to disk, exposing port 11434 to the internet or untrusted internal subnets provides attackers with an unauthenticated, zero-click remote code execution vector against your AI compute nodes.

This guide provides a comprehensive blue team defense architecture: network-level reverse proxy gates with mTLS, AppArmor and container sandboxing profiles, production-grade Sigma rules, eBPF file-write auditing probes, and an incident response playbook to verify and harden Ollama deployments against supply chain and traversal exploits.


Architecture Hardening#

Securing Ollama and local LLM inference engines requires dismantling the assumption that the inference API is safe to expose directly. A robust defense implements three concentric rings: API Gateway Isolation & Ingress Filtering, Operating System & Container Confinement (AppArmor / Non-Root), and Strict Digest Allowlisting.

Defense Architecture Flowchart#

flowchart TD
    classDef external fill:#1e293b,stroke:#ef4444,stroke-width:2px,color:#f8fafc
    classDef gateway fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#93c5fd
    classDef daemon fill:#064e3b,stroke:#10b981,stroke-width:2px,color:#6ee7b7
    classDef lsm fill:#4c1d95,stroke:#8b5cf6,stroke-width:2px,color:#ddd6fe
    classDef drop fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#fca5a5
    classDef success fill:#065f46,stroke:#34d399,stroke-width:2px,color:#a7f3d0

    Client[Incoming Client Request]:::external --> Gateway{Ring 1: Reverse Proxy Gateway}:::gateway
    
    Gateway -- Missing mTLS or Invalid Bearer Token --> Drop1[Action: Terminate with HTTP 401]:::drop
    Gateway -- Request to Administrative Endpoint /api/pull --> RouteCheck{Authorized Admin IP Subnet?}:::gateway
    
    RouteCheck -- External or Untrusted IP --> Drop2[Action: Deny Administrative Route HTTP 403]:::drop
    RouteCheck -- Whitelisted Management Network --> Daemon[Ring 2: Ollama Loopback Listener 127.0.0.1:11434]:::daemon
    
    Gateway -- Legitimate Inference Request /api/generate --> Daemon
    
    Daemon --> LSM{Ring 3: AppArmor and Container LSM Confinement}:::lsm
    
    LSM -- File Write Outside ~/.ollama/models --> Drop3[Action: SIGKILL and Kernel Audit Alert]:::drop
    LSM -- File Write to Confined Model Storage --> WriteSuccess[Layer Written to Verified Blobs Directory]:::success

Layer 1: Network Ingress Control & Reverse Proxy Gateway#

Ollama must never listen directly on public or untrusted network interfaces (0.0.0.0). Configure the daemon to bind strictly to localhost (127.0.0.1):

BASH
# Set environment variables for Ollama systemd service
sudo mkdir -p /etc/systemd/system/ollama.service.d/
cat << 'CONFIG_EOF' | sudo tee /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"
Environment="OLLAMA_ORIGINS=https://app.company.internal"
CONFIG_EOF

## Reload and restart service
sudo systemctl daemon-reload
sudo systemctl restart ollama

To expose inference capabilities to legitimate corporate applications, place an enterprise reverse proxy (such as NGINX or Envoy) in front of Ollama. The reverse proxy must enforce mutual TLS (mTLS) or Bearer token authorization and block administrative endpoints:

NGINX
# /etc/nginx/conf.d/ollama_proxy.conf
server {
    listen 443 ssl http2;
    server_name ollama.internal.corp;

    ssl_certificate /etc/ssl/certs/ollama_server.crt;
    ssl_certificate_key /etc/ssl/private/ollama_server.key;
    ssl_client_certificate /etc/ssl/certs/corp_ca.crt;
    ssl_verify_client on;

    # Restrict administrative supply chain endpoints strictly to Admin VPN
    location ~ ^/api/(pull|push|delete|create) {
        allow 10.100.0.0/16; # Corp Management Subnet
        deny all;

        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Publicly accessible inference routes (Token Authenticated)
    location /api/ {
        auth_request /auth_validate;
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Layer 2: Operating System & Container Confinement (AppArmor & Least Privilege)#

Even if an administrative endpoint is reached, host-level mandatory access control (MAC) policies must prevent the process from writing outside its assigned directory:

  1. Enforce Non-Root Execution: Run the Ollama daemon under a dedicated service account (ollama:ollama) without sudo privileges:
BASH
# Create system user without interactive shell
sudo useradd -r -s /bin/false -m -d /usr/share/ollama ollama
sudo chown -R ollama:ollama /usr/share/ollama
  1. AppArmor Profile Confinement: Apply an AppArmor profile to restrict file write operations exclusively to the model storage directory, denying access to /etc/, /tmp/, and user configuration files:
BASH
# /etc/apparmor.d/usr.bin.ollama
#include <tunables/global>

/usr/bin/ollama {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  # Allow read access to libraries and system files
  /usr/bin/ollama mr,
  /lib/** mr,
  /usr/lib/** mr,

  # Deny writes to critical linker and system configurations
  deny /etc/ld.so.preload w,
  deny /etc/** w,
  deny /root/** rwklx,
  deny /home/** rwklx,
  deny /tmp/** w,
  deny /var/tmp/** w,

  # Restrict write capabilities strictly to Ollama's data directory
  /usr/share/ollama/.ollama/** rw,
  /var/lib/ollama/** rw,

  # Network permissions
  network inet stream,
  network inet6 stream,
}

Load and enforce the profile:

BASH
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.ollama
sudo aa-enforce /usr/bin/ollama
  1. Hardened Docker Run Configuration: When containerizing Ollama, drop all Linux capabilities and enforce a read-only root filesystem:
BASH
docker run -d \
  --name ollama \
  --read-only \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  --tmpfs /tmp:rw,noexec,nosuid,size=512m \
  -v /opt/ollama/models:/root/.ollama/models:rw \
  -p 127.0.0.1:11434:11434 \
  ollama/ollama:0.1.34

Production Detection Queries#

Blue teams must deploy multi-layered detection covering network proxy logs, host audit daemons, and kernel-level file integrity monitoring.

Production Sigma Rule: Suspicious Model Pull and Shell Execution from Ollama#

The following Sigma rule detects unauthorized /api/pull requests originating from untrusted networks and subsequent anomalous child processes spawned by Ollama:

YAML
title: Suspicious Ollama Model Pull and Anomalous Process Execution (CVE-2024-37032)
id: c91a28bf-4091-4cf1-831d-876a3e1dfb02
status: production
description: |
  Detects potential exploitation of Ollama CVE-2024-37032 (Probllama) including unauthenticated /api/pull
  requests from external IPs, attempts to pull models containing path traversal sequences, or unexpected
  child shells spawned directly by the ollama daemon.
references:
  - https://www.oligo.security/blog/more-models-more-probs-ollama-rce
  - https://nvd.nist.gov/vuln/detail/CVE-2024-37032

tags:
  - attack.initial_access
  - attack.t1190
  - attack.persistence
  - attack.t1574.006
  - attack.execution
  - attack.t1059.004
  - cve.2024.37032
logsource:
  category: webserver
  product: linux
detection:
  selection_web:
    cs-method: 'POST'
    cs-uri-stem|contains: '/api/pull'
  filter_internal_admin:
    c-ip|cidr:
      - '127.0.0.1/32'
      - '10.100.0.0/16'
  selection_traversal:
    cs-uri-query|contains:
      - '..'
      - 'ld.so.preload'
      - '%2e%2e'
  selection_process:
    ParentImage|endswith:
      - '/ollama'
    Image|endswith:
      - '/bin/sh'
      - '/bin/bash'
      - '/bin/dash'
      - '/usr/bin/python'
      - '/usr/bin/python3'
      - '/usr/bin/curl'
      - '/usr/bin/wget'
      - '/usr/bin/socat'
  condition: (selection_web and not filter_internal_admin) or selection_traversal or selection_process
fields:
  - c-ip
  - cs-method
  - cs-uri-stem
  - Image
  - ParentImage
  - CommandLine
falsepositives:
  - Authorized internal CI/CD pipelines pulling verified models from corporate registries.
level: critical

Host-Level Auditd Rules for Linker Preload and Model Storage#

Deploy auditd rules to immediately alert on attempts to write to /etc/ld.so.preload or modify dynamic linker configurations:

BASH
# Monitor critical shared object preloading files
-w /etc/ld.so.preload -p wa -k preload_tamper
-w /etc/ld.so.conf -p wa -k linker_config_tamper
-w /etc/ld.so.conf.d/ -p wa -k linker_config_tamper

## Monitor unexpected execution of binaries in temporary folders
-w /tmp/ -p wxa -k tmp_execution_anomaly
-w /var/tmp/ -p wxa -k tmp_execution_anomaly

## Monitor Ollama process execution
-w /usr/bin/ollama -p xwa -k ollama_binary_tamper

## Lock auditd configuration
-e 2

eBPF Runtime Kernel Probe: Detecting Directory Traversal in openat#

Below is an eBPF tracepoint probe written in C (ollama_traversal_monitor.bpf.c) that hooks sys_enter_openat. It inspects open requests initiated by the ollama process, generating a security event if the path contains traversal sequences (..) or targets /etc/ld.so.preload:

C
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

struct event_t {
    __u32 pid;
    char comm[16];
    char filename[256];
};

struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 1 << 24);
} events SEC(".maps");

SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat_enter(struct trace_event_raw_sys_enter *ctx) {
    char comm[16];
    bpf_get_current_comm(&comm, sizeof(comm));

    // Monitor only the Ollama service daemon
    if (comm[0] != 'o' || comm[1] != 'l' || comm[2] != 'l' || comm[3] != 'a') {
        return 0;
    }

    struct event_t *event = bpf_ringbuf_reserve(&events, sizeof(struct event_t), 0);
    if (!event) {
        return 0;
    }

    event->pid = bpf_get_current_pid_tgid() >> 32;
    __builtin_memcpy(event->comm, comm, sizeof(event->comm));

    // Read filename argument passed to openat(dfd, filename, flags, mode)
    const char *filename_ptr = (const char *)ctx->args[1];
    bpf_probe_read_user_str(event->filename, sizeof(event->filename), filename_ptr);

    // Alert if filename targets ld.so.preload or contains traversal patterns
    if (event->filename[0] == '/' && event->filename[1] == 'e' && event->filename[2] == 't' && event->filename[3] == 'c') {
        bpf_ringbuf_submit(event, 0);
        return 0;
    }

    bpf_ringbuf_discard(event, 0);
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

YARA Rule: Detecting Traversal Signatures in OCI Manifests#

Deploy this YARA rule to inspect inbound web traffic, proxy caches, and model manifest files on disk:

YAML
rule Detect_Rogue_Ollama_Manifest_Traversal {
    meta:
        description = "Detects directory traversal sequences embedded within OCI / Ollama model manifest digests"
        author = "Md Redwan Ahmed (Fast Cyber Defense)"
        date = "2026-09-21"
        reference = "CVE-2024-37032"
    strings:
        $schema = "application/vnd.docker.distribution.manifest.v2+json" ascii
        $ollama_media = "application/vnd.ollama.image" ascii
        
        // Traversal patterns inside digest strings
        $trav1 = "sha256-.." ascii
        $trav2 = "sha256-../" ascii
        $trav3 = "../etc/ld.so.preload" ascii
        $trav4 = "..%2f" ascii
        $trav5 = "..%2F" ascii
        $trav6 = "sha256-....//" ascii
    condition:
        ($schema or $ollama_media) and 1 of ($trav*)
}

Enterprise Mitigation Matrix#

When evaluating defenses for local and cloud LLM inference clusters, security architects must weigh implementation velocity against architectural durability:

Remediation Strategy Implementation Effort Blast Radius & Operational Risk Detection & Prevention Efficacy Performance Overhead Architectural Longevity
Workaround: Localhost Binding & Gateway mTLS 15 - 30 Minutes
(Environment variable update + NGINX proxy)
Low
Requires updating application connection strings to point to reverse proxy.
High (95%)
Blocks unauthenticated network callers from reaching port 11434.
Negligible
(Under 1% proxy latency overhead).
Permanent Best Practice
Enforces zero-trust access control regardless of application flaws.
Hotfix: Official Patch (Ollama >= 0.1.34) 10 - 20 Minutes
(Package upgrade or container image pull)
Low
Direct drop-in replacement; zero API changes or backward-incompatibility.
Absolute for CVE-2024-37032
Enforces strict regex validation on layer digests.
Zero
Native Go execution speed maintained.
Mandatory Milestone
Eliminates the specific path traversal code path.
Architecture Fix: AppArmor Sandbox + Egress Filtering 1 - 2 Business Days
(Policy tuning and testing against model libraries)
Moderate
Misconfigured policies may prevent legitimate model caching.
Comprehensive (100%)
Prevents file write escapes and blocks rogue registry egress.
Negligible
(Kernel LSM check under 0.2% CPU).
Permanent State
Immunizes host against future arbitrary file write zero-days.

[!IMPORTANT] Upgrading Ollama to >= 0.1.34 is essential, but must be paired with reverse proxy authentication. Exposing unauthenticated inference engines directly to untrusted networks violates fundamental defense-in-depth principles.


Incident Response & Verification Playbook#

If your organization operated an internet-accessible or untrusted-network Ollama instance prior to applying patches, execute the following forensic verification playbook immediately:

flowchart TD
    classDef check fill:#1e293b,stroke:#f59e0b,stroke-width:2px,color:#fef3c7
    classDef alert fill:#450a0a,stroke:#dc2626,stroke-width:2px,color:#fca5a5
    classDef clean fill:#064e3b,stroke:#10b981,stroke-width:2px,color:#6ee7b7
    classDef triage fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#93c5fd

    Start[Step 1: Audit Service Version and Network Binding]:::triage --> Check1{Version < 0.1.34 and Bound to 0.0.0.0?}:::check
    Check1 -- Yes --> AlertExposure[Declare Exposure: Host Triage Initiated]:::alert
    Check1 -- No --> CheckPreload[Step 2: Inspect ld.so.preload and Staging Dirs]:::triage
    
    AlertExposure --> CheckPreload
    CheckPreload --> CheckHook{Unexpected Entries in ld.so.preload?}:::check
    
    CheckHook -- Yes --> DeclareCompromise[Declare Severity 1 Incident: Host Compromised]:::alert
    CheckHook -- No --> Step3[Step 3: Audit Model Manifest Cache Directory]:::triage
    
    DeclareCompromise --> IsolateNode[Isolate Host and Sever Network Interfaces]:::alert
    IsolateNode --> RotateSecrets[Rotate Cloud API Keys and Vector DB Credentials]:::alert
    
    Step3 --> CheckManifest{Rogue Registries or Traversal Strings in Manifests?}:::check
    CheckManifest -- Yes --> DeclareCompromise
    CheckManifest -- No --> Step4[Step 4: Upgrade Ollama and Enforce Localhost Binding]:::clean

Phase 1: Live Exposure & Network Audit#

  1. Verify Interface Bindings: Inspect active listening sockets to confirm if port 11434 is exposed to external interfaces:
BASH
# Audit listening ports for Ollama
sudo ss -tulpn | grep 11434

## Expected secure output: 127.0.0.1:11434 (NOT 0.0.0.0:11434)
  1. Check Running Version and User Context:
BASH
# Check binary version
ollama --version

## Verify process ownership
ps aux | grep ollama | grep -v grep

Phase 2: Filesystem & Dynamic Linker Integrity Verification#

  1. Inspect /etc/ld.so.preload: The primary exploitation vector targets the system-wide dynamic linker preload configuration:
BASH
# Check if ld.so.preload exists and inspect contents
if [ -f /etc/ld.so.preload ]; then
    echo "[!] WARNING: /etc/ld.so.preload detected. Inspecting contents:"
    cat /etc/ld.so.preload
else
    echo "[+] Clean: /etc/ld.so.preload does not exist."
fi
  1. Audit Temporary Directories for Suspicious Shared Libraries: Search for unmanaged .so files created in temporary directories (/tmp, /var/tmp):
BASH
# Search for recently created ELF shared objects in /tmp
sudo find /tmp /var/tmp -name "*.so" -type f -exec ls -la {} +
  1. Audit Local Model Manifest Cache: Review all downloaded manifests for unexpected foreign registries or directory traversal strings:
BASH
# Check manifests directory for foreign registry URLs or dot-dot patterns
MANIFEST_DIR="${HOME}/.ollama/models/manifests"
if [ -d "$MANIFEST_DIR" ]; then
    grep -rn "sha256-.." "$MANIFEST_DIR"
    find "$MANIFEST_DIR" -type f -exec head -n 20 {} +
fi

Phase 3: Containment & Eradication#

If any unauthorized entries or rogue models are detected:

  1. Isolate the Inference Host: Sever external network interfaces and detach cloud IAM security groups immediately.
  2. Remove Preload Artifacts: Delete /etc/ld.so.preload and any associated malicious shared objects in /tmp/.
  3. Purge Model Storage: Clear the existing model cache (rm -rf ~/.ollama/models/*) to eliminate poisoned weights or manifests.
  4. Credential Rotation: Assume all secrets stored in memory or on the filesystem—including Hugging Face tokens, OpenAI API keys, database connection strings, and vector database credentials—have been exfiltrated. Rotate all credentials immediately.

Phase 4: Post-Remediation Hardening Verification#

  1. Verify Binary Upgrade: Confirm that the installed Ollama binary is version 0.1.34 or newer:
BASH
ollama --version
## Output must be >= 0.1.34
  1. Test Traversal Rejection: Attempt to pull a test model with traversal characters to confirm the fix is operational:
BASH
curl -s -X POST http://127.0.0.1:11434/api/pull -d '{"name":"test/../../traversal:latest"}'
## Expected response: {"error":"invalid model name"}
  1. Validate Reverse Proxy & AppArmor Profiles: Confirm that AppArmor profile status is active and enforcing:
BASH
sudo aa-status | grep ollama
## Expected output: /usr/bin/ollama (enforce)

Authoritative References#

  1. Oligo Security Threat Research: Probllama: Ollama Remote Code Execution Vulnerability (CVE-2024-37032) — Oligo Security Labs
  2. National Vulnerability Database (NVD): CVE-2024-37032 Detail - Improper Limitation of a Pathname to a Restricted Directory in Ollama — NIST NVD
  3. Ollama GitHub Repository: Release v0.1.34 - Security Fix for Model Pull Path Traversal Validation — GitHub Ollama Releases
  4. CISA / NSA / FBI Cybersecurity Advisory: Deploying and Securing Artificial Intelligence Systems in Enterprise Environments — CISA AI Security

Comments