Back to Intelligence

datasette-llm 0.1a11 Adds OpenAI-Compatible Endpoints — Security Hardening Guide for Local LLM Deployments

SA
Security Arsenal Team
November 14, 2026
15 min read

The release of datasette-llm 0.1a11 represents a significant shift in how organizations can integrate Large Language Models (LLMs) into their data exploration workflows. By adding support for OpenAI-compatible endpoints, this Datasette plugin now allows security teams to configure local LLM deployments using LM Studio, Ollama, or llama.cpp (which recently reached v1.0.0) alongside traditional cloud-based OpenAI services.

While this flexibility eliminates reliance on external API providers and reduces per-token costs, it introduces critical security considerations that defenders must address immediately. When organizations deploy local LLM endpoints—particularly in SOC environments, threat hunting platforms, or sensitive data analysis workflows—they create new attack surfaces that can expose proprietary data, enable prompt injection attacks, and bypass traditional DLP controls.

This analysis provides actionable guidance for securing datasette-llm deployments in production environments, with specific focus on network segmentation, authentication hardening, and detection strategies for anomalous LLM usage patterns.

Technical Analysis

Affected Products and Scope

  • Primary Component: datasette-llm 0.1a11 (Datasette plugin)
  • Integration Points:
    • LM Studio (local LLM server)
    • Ollama (local LLM runtime)
    • llama.cpp v1.0.0 (LLM inference engine)
    • Any OpenAI-compatible API endpoint

Architectural Risk Profile

The OpenAI-compatible endpoint feature allows datasette-llm to communicate with LLM services over HTTP/HTTPS using the standardized OpenAI API schema. This creates several security boundaries that require explicit hardening:

  1. Data Egress Risk: Datasette instances configured with external OpenAI-compatible endpoints can transmit sensitive query data, database schemas, and result sets to third-party servers. Unlike traditional database connections, these requests contain natural language descriptions of data structures that may reveal sensitive business logic or compliance-regulated information.

  2. Local LLM Attack Surface: When using LM Studio or Ollama, the LLM server typically binds to localhost by default. However, misconfigurations can expose these services to network access, creating unauthenticated inference endpoints that attackers can abuse for resource exhaustion, model extraction, or lateral movement.

  3. Prompt Injection Vectors: Datasette plugins that pass user-controlled input to LLM endpoints are vulnerable to prompt injection attacks. An attacker with access to Datasette's query interface could craft malicious prompts that cause the LLM to reveal system prompts, internal configurations, or bypass intended access controls.

Exploitation Status

This release is a feature addition, not a vulnerability patch. No CVEs are associated with datasette-llm 0.1a11, and there is no confirmed active exploitation. However, the architectural changes warrant immediate defensive review because:

  • New Network Dependencies: The plugin introduces HTTP client functionality that may bypass existing proxy controls or DLP inspection points
  • Credential Management: OpenAI-compatible endpoints typically require API keys, creating new secrets management requirements
  • Default Configuration Risk: Many local LLM servers ship with permissive CORS policies and no authentication, creating opportunities for cross-origin attacks

Detection & Response

Executive Takeaways

Given that this is a feature release rather than a technical vulnerability, the following defensive recommendations apply to organizations deploying datasette-llm 0.1a11:

  1. Network Segmentation for LLM Endpoints: Isolate local LLM servers (LM Studio, Ollama, llama.cpp) in dedicated network segments with strict ingress/egress filtering. These services should never be directly accessible from user workstations or external networks.

  2. API Key Rotation and Vaulting: If using external OpenAI-compatible endpoints, store API keys in enterprise vault solutions (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) rather than environment variables or configuration files. Implement automatic rotation policies.

  3. Data Classification Enforcement: Deploy DLP rules specifically tuned for LLM traffic patterns. Monitor for high-volume requests to OpenAI-compatible endpoints that may indicate bulk data exfiltration through prompt engineering.

  4. Prompt Injection Testing: Before deploying datasette-llm in production, conduct adversarial testing to identify prompt injection vulnerabilities. Test whether users can manipulate the LLM into revealing system prompts, ignoring instructions, or accessing unauthorized data.

  5. Audit Logging for LLM Interactions: Enable comprehensive logging for all datasette-llm requests, including the full prompt text, model responses, and user identity. These logs are critical for forensic investigations involving data leakage or compliance violations.

  6. Rate Limiting and Resource Controls: Implement strict rate limiting on LLM endpoints to prevent resource exhaustion attacks. Local LLM servers are particularly vulnerable to denial-of-service through computationally expensive prompts.

Sigma Rules

The following Sigma rules detect suspicious behaviors associated with datasette-llm deployments and local LLM server abuse.

YAML
---
title: Datasette LLM Plugin Network Connection to Non-Standard Endpoint
id: 8f3a2b1c-4e5d-4c6a-9b8d-7e6f5a4b3c2d
status: experimental
description: Detects when Datasette process establishes network connections to LLM endpoints outside approved domains or IP ranges.
references:
  - https://attack.mitre.org/techniques/T1071/
  - https://simonwillison.net/2026/Nov/14/datasette-llm/
author: Security Arsenal
date: 2026/11/14
tags:
  - attack.command_and_control
  - attack.t1071.001
logsource:
  category: network_connection
  product: windows
detection:
  selection:
    Image|endswith:
      - '\datasette.exe'
      - '\python.exe'
    CommandLine|contains:
      - 'datasette-llm'
      - 'datasette serve'
  filter_approved_endpoints:
    DestinationHostname|endswith:
      - '.openai.com'
      - '.azure.com'
      - 'localhost'
      - '127.0.0.1'
  condition: selection and not filter_approved_endpoints
falsepositives:
  - Legitimate connections to approved third-party LLM providers
  - Development environments using local LLM servers
level: medium
---
title: Local LLM Server Exposed to Network
id: 9d4c3b2a-5f6e-4d7c-8b9a-6e5f4a3b2c1d
status: experimental
description: Detects when LM Studio, Ollama, or llama.cpp server binds to non-localhost interface, potentially exposing unauthenticated LLM endpoint.
references:
  - https://attack.mitre.org/techniques/T1021/
  - https://lmstudio.ai
  - https://ollama.com
author: Security Arsenal
date: 2026/11/14
tags:
  - attack.lateral_movement
  - attack.t1021
logsource:
  category: network_connection
  product: linux
detection:
  selection:
    Image|endswith:
      - '/lm-studio'
      - '/ollama'
      - '/llama.cpp'
      - '/server'
    DestinationIp|startswith:
      - '0.0.0.0'
      - '::'
  filter_localhost:
    DestinationIp:
      - '127.0.0.1'
      - '::1'
      - 'localhost'
  condition: selection and not filter_localhost
falsepositives:
  - Intentional internal LLM server deployments with proper network controls
level: high
---
title: High-Volume LLM API Requests from Single Source
id: 7b2c1d0e-3f4a-4b5c-6d7e-5f4a3b2c1d0e
status: experimental
description: Detects abnormally high request volume to LLM endpoints, potentially indicating data exfiltration, model extraction, or resource exhaustion attacks.
references:
  - https://attack.mitre.org/techniques/T1048/
  - https://attack.mitre.org/techniques/T1499/
author: Security Arsenal
date: 2026/11/14
tags:
  - attack.exfiltration
  - attack.t1048
  - attack.impact
  - attack.t1499
logsource:
  category: proxy
  product: zeek
detection:
  selection:
    uri_path|contains:
      - '/v1/chat/completions'
      - '/v1/completions'
      - '/v1/embeddings'
  timeframe: 5m
  condition: selection | count() by src_ip > 100
falsepositives:
  - Legitimate batch processing jobs
  - Development/testing environments with automated testing
level: medium

KQL (Microsoft Sentinel / Defender)

The following KQL queries hunt for anomalous LLM usage patterns and potential security violations in datasette-llm deployments.

KQL — Microsoft Sentinel / Defender
// Hunt for Datasette processes making external LLM API calls
// Focus on non-standard ports and unapproved destinations
let approved_llm_endpoints = dynamic(["api.openai.com", "*.openai.azure.com", "localhost", "127.0.0.1"]);
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where InitiatingProcessFileName =~ "python.exe" or InitiatingProcessFileName =~ "datasette.exe"
| where InitiatingProcessCommandLine has_any ("datasette-llm", "datasette serve")
| where RemotePort in (11434, 1234, 8080, 5000, 3000) // Common local LLM ports
| extend IsApprovedEndpoint = iff(RemoteUrl has_any (approved_llm_endpoints) or RemoteIP in (approved_llm_endpoints), "Approved", "Unapproved")
| where IsApprovedEndpoint == "Unapproved"
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, 
          RemoteUrl, RemoteIP, RemotePort, IsApprovedEndpoint
| order by TimeGenerated desc;

// Detect potential prompt injection attempts in web server logs
// Look for common prompt injection patterns in HTTP requests to Datasette
CommonSecurityLog
| where TimeGenerated > ago(24h)
| where ApplicationProtocol == "HTTP"
| where RequestURL has_any ("/llm", "/chat", "/query")
| where RequestMethod == "POST"
| extend RequestBody = tostring(AdditionalExtensions)
| where RequestBody has_any (
    "ignore previous instructions",
    "disregard all prior",
    "system prompt",
    "you are now",
    "new instructions:",
    "override",
    "bypass"
)
| project TimeGenerated, SourceIP, DestinationHostName, RequestURL, RequestMethod, RequestBody
| order by TimeGenerated desc;

// Identify high-volume LLM API usage that may indicate abuse
// Aggregate requests by source IP and endpoint over time
let time_threshold = 5m;
let request_threshold = 50;
Syslog
| where TimeGenerated > ago(1h)
| where SyslogMessage has_any ("/v1/chat/completions", "/v1/completions", "/v1/embeddings")
| parse SyslogMessage with * "client_ip=" ClientIP " " *
| summarize RequestCount = count() by ClientIP, bin(TimeGenerated, time_threshold)
| where RequestCount > request_threshold
| order by RequestCount desc;

Velociraptor VQL

The following Velociraptor artifacts hunt for datasette-llm configurations and local LLM server exposures.

VQL — Velociraptor
-- Hunt for datasette-llm configuration files that may contain API keys or endpoint configurations
-- Focus on common configuration directories and file patterns
SELECT 
    FullPath,
    Size,
    Mtime,
    Ctime,
    Mode
FROM glob(
    globs=[
        'C:\\Users\\*\\.datasette\\**',
        'C:\\Users\\*\\AppData\\Local\\datasette\\**',
        '/home/*/.datasette/**',
        '/root/.datasette/**',
        '/etc/datasette/**',
        'C:\\ProgramData\\datasette\\**'
    ],
    accessor='file'
)
WHERE FullPath =~ '(config|settings|metadata)\\.(json|yaml|yml|toml)$'
   OR FullPath =~ 'llm.*\\.(json|yaml|yml|toml)$'
ORDER BY Mtime DESC
LIMIT 100

-- Identify running LLM server processes and their network bindings
-- Focus on LM Studio, Ollama, and llama.cpp
SELECT 
    Pid,
    Name,
    CommandLine,
    Exe,
    Username,
    CreateTime
FROM pslist()
WHERE 
    Name =~ '(lm-studio|ollama|llama|server)'
    OR CommandLine =~ '(lm-studio|ollama serve|llama.cpp|--port 11434|--port 1234)'
ORDER BY CreateTime DESC

-- Enumerate network listeners on common LLM ports
-- Detect if LLM servers are bound to non-localhost interfaces
SELECT 
    Pid,
    Name,
    LocalAddress,
    LocalPort,
    RemoteAddress,
    RemotePort,
    State
FROM netstat()
WHERE 
    LocalPort in (11434, 1234, 8080, 5000, 3000, 8000)
    AND State == 'LISTEN'
    AND NOT LocalAddress =~ '^(127\\.|::1|localhost)'
ORDER BY LocalPort

Remediation Script

The following script audits datasette-llm deployments for security misconfigurations and enforces hardening controls.

Bash / Shell
#!/bin/bash
# datasette-llm Security Hardening Script
# Version: 1.0
# Date: 2026-11-14
# Purpose: Audit and harden datasette-llm deployments with OpenAI-compatible endpoints

set -euo pipefail

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Logging function
log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}

warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check if running as root
if [[ $EUID -eq 0 ]]; then
   error "This script should not be run as root. Run as the datasette service account."
   exit 1
fi

log "Starting datasette-llm security audit..."

# 1. Check for datasette-llm installation
if ! command -v datasette &> /dev/null; then
    error "Datasette not found in PATH. Please install datasette first."
    exit 1
fi

DATASETTE_VERSION=$(datasette --version | grep -oP '\d+\.\d+\.\d+' || echo "unknown")
log "Detected Datasette version: $DATASETTE_VERSION"

# 2. Check for datasette-llm plugin
if datasette plugins | grep -q "datasette-llm"; then
    log "datasette-llm plugin detected"
    LLM_VERSION=$(datasette plugins | grep "datasette-llm" | grep -oP '\d+\.\d+[a-z0-9]*' || echo "unknown")
    log "datasette-llm version: $LLM_VERSION"
else
    warn "datasette-llm plugin not found. This script is specific to LLM deployments."
    exit 0
fi

# 3. Audit Datasette configuration for LLM endpoints
CONFIG_DIRS=(
    "$HOME/.datasette"
    "$HOME/.config/datasette"
    "/etc/datasette"
)

for dir in "${CONFIG_DIRS[@]}"; do
    if [[ -d "$dir" ]]; then
        log "Auditing configuration directory: $dir"
        
        # Check for API keys in configuration files
        if find "$dir" -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.toml" \) -exec grep -l "api_key\|apikey\|openai_api_key" {} \; | grep -q .; then
            error "API keys detected in plaintext configuration files in $dir"
            warn "RECOMMENDATION: Move API keys to environment variables or secrets management system"
            find "$dir" -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.toml" \) -exec grep -l "api_key\|apikey\|openai_api_key" {} \;
        else
            log "No plaintext API keys found in $dir"
        fi
        
        # Check for overly permissive file permissions
        find "$dir" -type f -perm /o+r | while read -r file; do
            warn "World-readable file detected: $file"
            warn "RECOMMENDATION: Run 'chmod 600 $file' to restrict access"
        done
    fi
done

# 4. Check for local LLM server exposures
log "Checking for local LLM server network bindings..."

LLM_PORTS=(11434 1234 8080 5000 3000 8000)
EXPOSED_SERVERS=()

for port in "${LLM_PORTS[@]}"; do
    if netstat -tuln 2>/dev/null | grep -q ":$port "; then
        BIND_ADDR=$(netstat -tuln 2>/dev/null | grep ":$port " | awk '{print $4}' | head -1)
        if [[ "$BIND_ADDR" != "127.0.0.1:$port" && "$BIND_ADDR" != "[::1]:$port" ]]; then
            error "LLM server on port $port is exposed to network: $BIND_ADDR"
            EXPOSED_SERVERS+=("$port:$BIND_ADDR")
        else
            log "LLM server on port $port is properly bound to localhost"
        fi
    fi
done

if [[ ${#EXPOSED_SERVERS[@]} -gt 0 ]]; then
    error "CRITICAL: ${#EXPOSED_SERVERS[@]} LLM server(s) exposed to network"
    for server in "${EXPOSED_SERVERS[@]}"; do
        error "  - $server"
    done
    warn "RECOMMENDATION: Configure LLM servers to bind only to localhost (127.0.0.1)"
    warn "  - For Ollama: Set OLLAMA_HOST=127.0.0.1:11434"
    warn "  - For LM Studio: Configure network settings to localhost only"
    warn "  - For llama.cpp: Use --host 127.0.0.1 flag"
fi

# 5. Check for running LLM processes
log "Checking for running LLM server processes..."

LLM_PROCESSES=$(ps aux | grep -E '(lm-studio|ollama|llama.cpp)' | grep -v grep || true)

if [[ -n "$LLM_PROCESSES" ]]; then
    log "Detected LLM server processes:"
    echo "$LLM_PROCESSES"
    
    # Check if processes are running with excessive privileges
    echo "$LLM_PROCESSES" | awk '{print $1}' | sort -u | while read -r user; do
        if [[ "$user" == "root" ]]; then
            error "LLM server running as root - CRITICAL SECURITY RISK"
            warn "RECOMMENDATION: Run LLM servers as unprivileged service account"
        fi
    done
else
    log "No LLM server processes detected"
fi

# 6. Network segmentation validation
log "Validating network segmentation for LLM endpoints..."

# Check if host can reach external LLM endpoints
EXTERNAL_ENDPOINTS=("api.openai.com" "api.anthropic.com")
for endpoint in "${EXTERNAL_ENDPOINTS[@]}"; do
    if timeout 5 curl -s -o /dev/null -w "%{http_code}" "https://$endpoint" 2>/dev/null | grep -q "200\|401\|403"; then
        warn "Host can reach external LLM endpoint: $endpoint"
        warn "RECOMMENDATION: If using only local LLMs, block egress to external LLM APIs via firewall"
    fi
done

# 7. Audit Datasette metadata for LLM configuration
if [[ -f "$HOME/.datasette/metadata.json" ]]; then
    log "Auditing Datasette metadata.json for LLM configuration..."
    
    if grep -q "llm" "$HOME/.datasette/metadata.json"; then
        log "LLM configuration found in metadata.json"
        
        # Check for insecure endpoint configurations
        if grep -q "http://" "$HOME/.datasette/metadata.json"; then
            error "Insecure HTTP endpoint detected in LLM configuration"
            warn "RECOMMENDATION: Use HTTPS for all external LLM endpoints"
        fi
    fi
fi

# 8. Generate hardening recommendations
log "\n=== SECURITY HARDENING RECOMMENDATIONS ==="

echo "1. API Key Management:"
echo "   - Store API keys in environment variables, not configuration files"
echo "   - Use secrets management: export OPENAI_API_KEY=\$(vault read -field=key secret/llm/openai)"
echo ""

echo "2. Network Controls:"
echo "   - Bind local LLM servers to 127.0.0.1 only"
echo "   - Implement egress filtering to block unauthorized LLM API calls"
echo "   - Use firewall rules to restrict Datasette host outbound connections"
echo ""

echo "3. Access Controls:"
echo "   - Enable Datasette authentication: datasette serve --root -h 127.0.0.1"
echo "   - Implement role-based access control for LLM features"
echo "   - Audit user permissions regularly"
echo ""

echo "4. Monitoring & Logging:"
echo "   - Enable verbose logging for datasette-llm plugin"
echo "   - Monitor for high-volume LLM API requests"
echo "   - Alert on connections to unapproved LLM endpoints"
echo ""

echo "5. Prompt Injection Defenses:"
echo "   - Sanitize user inputs before passing to LLM"
echo "   - Implement output validation for LLM responses"
echo "   - Use separate LLM contexts for untrusted user queries"
echo ""

# 9. Check for updates
log "Checking for datasette-llm updates..."
CURRENT_VERSION=$(datasette plugins | grep "datasette-llm" | grep -oP '\d+\.\d+[a-z0-9]*' || echo "0.0.0")
log "Current version: $CURRENT_VERSION"
log "Latest version: Check https://github.com/datasette/datasette-llm/releases"

log "Security audit complete. Review warnings and errors above."

# Exit with error code if critical issues found
if [[ ${#EXPOSED_SERVERS[@]} -gt 0 ]]; then
    exit 1
fi

exit 0

Remediation

Immediate Actions (Within 24 Hours)

  1. Audit Existing Deployments: Run the provided hardening script against all Datasette instances to identify exposed LLM servers, plaintext API keys, and insecure configurations.

  2. Network Segmentation: Ensure local LLM servers (LM Studio, Ollama, llama.cpp) bind only to localhost (127.0.0.1). For Ollama, set OLLAMA_HOST=127.0.0.1:11434 in the service environment. For llama.cpp, use the --host 127.0.0.1 flag.

  3. API Key Vaulting: Migrate all API keys from configuration files to environment variables or enterprise secrets management systems. Never commit API keys to version control.

Short-Term Hardening (Within 1 Week)

  1. Egress Filtering: Implement firewall rules to restrict outbound connections from Datasette hosts to approved LLM endpoints only. Block all other destinations on ports 443 and 80.

  2. Authentication Enforcement: Enable Datasette's built-in authentication mechanisms or deploy behind a reverse proxy with SSO integration. Never expose Datasette with LLM plugins to unauthenticated users.

  3. Logging Configuration: Enable comprehensive audit logging for all datasette-llm interactions. Forward logs to your SIEM for correlation and alerting.

Long-Term Security Controls (Within 1 Month)

  1. Prompt Injection Testing: Conduct adversarial testing to identify prompt injection vulnerabilities. Test scenarios include:

    • Attempts to reveal system prompts
    • Instructions to ignore previous directives
    • Requests to bypass access controls
    • Social engineering through crafted prompts
  2. Data Loss Prevention: Deploy DLP rules specifically tuned for LLM traffic patterns. Monitor for:

    • High-volume requests to LLM endpoints
    • Sensitive data patterns in prompts (PII, credentials, proprietary information)
    • Unusual query patterns that may indicate data exfiltration
  3. Incident Response Planning: Update IR playbooks to include LLM-specific scenarios:

    • Data leakage through prompt engineering
    • Model extraction attacks
    • Resource exhaustion via computationally expensive prompts
    • Unauthorized access to LLM endpoints

Vendor Resources

Configuration Examples

Secure Ollama Configuration:

Bash / Shell
# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"
Environment="OLLAMA_NUM_PARALLEL=2"
Environment="OLLAMA_MAX_LOADED_MODELS=1"

Datasette Metadata with LLM Endpoint:

JSON
{
  "plugins": {
    "datasette-llm": {
      "default_model": "local-llama",
      "models": {
        "local-llama": {
          "type": "openai_compatible",
          "api_base": "http://127.0.0.1:11434/v1",
          "model_name": "llama3.1:8b",
          "api_key_env": "OLLAMA_API_KEY"
        }
      }
    }
  }
}

Firewall Rules for LLM Egress Control:

Bash / Shell
# Allow only approved LLM endpoints
iptables -A OUTPUT -p tcp -d api.openai.com --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d 127.0.0.1 --dport 11434 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j DROP
iptables -A OUTPUT -p tcp --dport 80 -j DROP

Conclusion

The datasette-llm 0.1a11 release provides powerful capabilities for integrating local LLMs into data analysis workflows, but it also introduces new security boundaries that require explicit hardening. By implementing the network segmentation, authentication controls, and monitoring strategies outlined in this guide, organizations can safely leverage local LLM capabilities while maintaining robust security postures.

Security teams should treat LLM endpoints as high-value targets requiring the same level of protection as database servers or authentication systems. The combination of sensitive data access, natural language processing capabilities, and network connectivity creates unique attack vectors that traditional security controls may not adequately address.

Regular security assessments, prompt injection testing, and continuous monitoring are essential for maintaining the security of datasette-llm deployments in production environments.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.