Why we reject GDPR consent tokens at the proxy layer: a sovereign AI's data minimization pattern

by
Why we reject GDPR consent tokens at the proxy layer: a sovereign AI's data minimization pattern

Why we reject GDPR consent tokens at the proxy layer: a sovereign AI's data minimization pattern

When you self-host an LLM behind a reverse proxy, every request carries baggage. GDPR consent tokens, analytics cookies, tracking pixels — they all arrive at your inference endpoint as if they belong there. They don't.

Most teams pipe requests straight into vLLM or llama.cpp and let the model parse whatever comes in. That's a mistake. Consent tokens are not just noise; they are data minimization violations waiting to happen. If your model logs the raw request — even for debugging — you've just ingested personal data you never needed.

We solve this at the proxy layer. Our sovereign AI stack runs behind a hardened nginx instance that strips all known consent tokens before the request reaches the inference engine. No exceptions. Here's why and how.

GDPR consent tokens are typically opaque strings passed via headers (e.g., X-Consent-Token) or cookies (gdpr_consent). They encode user choices about data processing, but they also encode a user identifier, a timestamp, and sometimes a hash of the user's IP. That's personal data.

When you run a self-hosted LLM, you don't need any of that. The model only needs the prompt text. The consent token is irrelevant to the generation task. Yet if your proxy forwards it, the inference engine receives it, and if you log the request body or headers for auditing, you've just stored personal data without a clear purpose.

Why it violates data minimization

Article 5(1)(c) of the GDPR states that personal data shall be "adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed." A consent token is not necessary for generating text. It's metadata that belongs to the application layer, not the inference layer.

By forwarding it, you create a copy of personal data in a system (the LLM server) that has no business processing it. Even if you never look at it, the risk exists: a breach of the inference server exposes consent tokens alongside model outputs. That's a data spill waiting to happen.

The EU AI Act adds another layer

The EU AI Act requires high-risk AI systems to maintain technical documentation and logs. If your inference logs include consent tokens, those logs become subject to stricter requirements. Stripping tokens at the proxy simplifies compliance: your logs contain only prompts and responses — no personal data — so you avoid the "processing of special categories" overhead.

Implementation: proxy-level filtering

We use nginx's lua module to inspect and filter headers on every request. Here's the core logic:

server {
    listen 443 ssl;
    server_name ai.example.com;

    # Block known consent headers before they reach the app
    set $consent_headers "X-Consent-Token gdpr_consent consent-token";

    access_by_lua_block {
        local headers = ngx.req.get_headers()
        for _, h in ipairs(ngx.split(ngx.var.consent_headers, " ")) do
            if headers[h] then
                ngx.log(ngx.WARN, "Stripping consent header: " .. h)
                ngx.req.clear_header(h)
            end
        end
        -- Also strip any cookie that starts with 'gdpr_'
        local cookie = ngx.var.http_cookie or ""
        local new_cookie = cookie:gsub(";?\s*gdpr_[^;]+", "")
        if new_cookie ~= cookie then
            ngx.req.set_header("Cookie", new_cookie)
        end
    }

    location /v1/chat/completions {
        proxy_pass http://vllm:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        # Do NOT forward consent tokens
    }
}

This runs before any Lua code touches the request body. We also log the stripping event to a separate audit stream (syslog) so we can prove we never processed the token.

You might think: "But I need the consent token to prove the user agreed to processing." That logic is backwards. The consent token proves consent for your application, not for the inference engine. If you need to associate a response with a user, use a session ID that you generate yourself — not a GDPR consent token. Session IDs are not personal data if they're random and not linked to an identity.

We generate a X-Session-Id header at the application layer (before the proxy) and strip all upstream consent tokens. The inference engine only sees the session ID and the prompt. That's enough for usage metering and debugging.

Data minimization in practice

Stripping consent tokens is one pattern. Apply the same logic to:

  • IP addresses: Don't log the client IP in inference logs. Use X-Forwarded-For only for rate limiting, then discard.
  • User-agent strings: Strip them unless you need them for browser-specific behavior (you don't, for an API).
  • Referrers: Never needed.

We run a custom nginx module that drops all headers not in an allowlist: Content-Type, Authorization, X-Session-Id, and X-Request-Id. Everything else gets deleted. That's true minimization.

The trade-off

This makes debugging harder. When a request fails, you don't have the original headers. We mitigate by logging the stripped headers to a separate, short-lived buffer that auto-expires after 24 hours. The buffer is encrypted and not accessible from the inference server. If you need to replay a request, you can retrieve the original headers from the buffer using the X-Request-Id — but only with a special admin token.

This is more work than just forwarding everything. But it's the only way to run a sovereign AI stack that respects data minimization by default.

Audit trail

We log all stripping actions to a dedicated syslog facility (local5). Example:

2025-03-28T10:15:00Z proxy consent-strip: session=abc123 header=X-Consent-Token

This log is immutable (written to a append-only database) and forms part of our GDPR compliance documentation. It proves we never forwarded the token to the inference engine.

Conclusion

Consent tokens are a liability in an inference pipeline. They carry personal data that the model doesn't need, and they complicate compliance with GDPR and the EU AI Act. By stripping them at the proxy layer, you enforce data minimization at the network boundary — before the data even reaches your AI stack.

This is not paranoia. It's engineering discipline. Your LLM should only see the prompt. Everything else is someone else's problem.

#audit#compliance#data-minimization#eu-ai-act#self-hosted-ai
Share — X / Twitter · LinkedIn · HN · Email
Damir Radulić
Founder of RiNET. On the Croatian internet since 1996 (Kvarner Net). In Amsterdam now, building autonomous AI infrastructure that runs on Monday morning when nobody's watching — sovereign stacks, agent swarms, LoRA fine-tuning, civic-intelligence platforms.

Related