CVE: CVE-2026-23742
Alias: Skipper inline Lua filter vulnerability
CVSS v3.1 Score: 8.8 (High)
Severity: High
Exploitability:
- Attack Vector: Network
- Privileges Required: Low (ability to define filters)
- User Interaction: None
- Exploit Status: Conceptually simple to abuse; no widely distributed exploit code in major feeds at this moment
What the Vulnerability Is
Skipper is a widely used HTTP router and reverse proxy that helps route traffic inside cloud environments — especially Kubernetes.
Some Skipper deployments allow Lua scripts embedded directly (“inline”) in route definitions or Ingress objects. Prior to version 0.23.0, the default setting included -lua-sources=inline,file, meaning Skipper would accept Lua code from more places than just trusted files.
Here’s the crux of the problem:
- If an attacker (or low-privileged user) can create or update a route or Ingress definition that Skipper reads, they can include their own Lua script.
- That Lua code runs inside Skipper’s process with whatever privileges Skipper has.
- A malicious script can open arbitrary files Skipper has access to — including configuration, service tokens, or secrets mounted into the container.
- If the attacker can also read Skipper’s logs (which many environments allow), the script can dump file contents into logs, exposing credentials or sensitive data.
This turns a flexible runtime scripting feature into a local file access / secret disclosure vulnerability by design.
How Exploitation Works
Typical Exploitation Path
- Access control gap: An attacker has rights to define or edit certain Skipper route objects (e.g., Kubernetes Ingress annotations).
- Inline Lua injection: Attacker writes a Lua filter that uses basic file I/O functions (
io.open, etc.) to read sensitive files. - Triggering execution: The malicious filter is deployed; Skipper loads and runs it.
- Data exfiltration: The script prints file contents to stdout or stderr — often captured in logs — or reflects it back in an HTTP response if possible.
- Harvesting secrets: The attacker fetches logs or crafted responses to collect file contents.
This is a two-stage exploitation: ability to define filters and ability to read Skipper logs or responses. The more privileged the attacker is in the configuration system, the easier this abuse becomes.
How to Detect Exploitation
Detecting misuse of this vulnerability involves monitoring two main areas:
- Unauthorized filter creation / modification
- Suspicious behavior in logs / traffic that indicates file reads or exfiltration
Below are detection strategies and Splunk rules tailored for operational teams.
Log Sources You Need
| Log Source | Why It Matters |
|---|---|
| Skipper runtime logs | Shows filter loading, errors, and script execution output |
| Kubernetes audit logs | Shows who created or modified route/Ingress objects |
| API server logs | Trusted source of object mutations and identities |
| Application access logs | Can show exfiltration payloads in responses |
| Container logs | Useful if Skipper writes to stdout/stderr |
Splunk Detection Rules
1) Detect Ingress/Route Definitions with Inline Lua
index=kube_audit_logs
(resource="ingresses" OR resource="routes")
(requestBody="*lua*" OR requestBody="*filter*")
| stats count by user, namespace, resource, name, requestBody
| where count > 0
This rule catches any Kubernetes object creation or update that contains lua in its definition.
2) Skipper Logs — Inline Lua Filter Execution
index=skipper_logs
("inline lua" OR "lua filter" OR "loading lua")
| stats count by host, message
This surfaces instances where Skipper acknowledges loading or running Lua code.
3) Anomalous Log Output (Possible File Dumping)
index=skipper_logs
| rex field=_raw "(\/etc\/|\/var\/run\/|token)"
| search token OR passwd OR shadow
| stats count by host, _raw
This identifies log entries containing paths or sensitive tokens — common indicators of file access.
4) Unusual HTTP Responses (Potential Secret Exfil)
index=access_logs status=200
| regex _raw="([A-Za-z0-9+/]{50,}=*)"
| stats count by client_ip, uri
Long base64-like strings in responses can signal exfiltrated file contents.
Indicators of Exploitation
These are patterns worth alerting on or investigating:
- Creation/modification of routes containing inline Lua code where such behavior isn’t normal.
- Skipper logging unusual errors or messages referencing filesystem paths.
- Unexpected HTTP responses with long encoded blobs (base64 or similar).
- New or unusual access to secret file paths in logs (
/var/run/secrets/...,/etc/passwd, etc.). - Config changes by identities that don’t normally manage routing.
Mitigation & Hardening
Even before upgrading, you can significantly reduce risk:
Immediate
- Disable inline Lua filters: Configure Skipper with restricted Lua sources (e.g., only file-based scripts).
- Limit who can create filters: Tighten RBAC for Kubernetes Ingress/route resources.
- Run Skipper with least privilege: Don’t grant it access to secret paths unnecessarily.
- Audit recent Ingress configurations for suspicious
luaentries.
Long Term
- Upgrade Skipper to v0.23.0 or later — this release changes defaults to prevent untrusted inline Lua code execution.
👉 https://github.com/zalando/skipper/releases/tag/v0.23.0 - Implement consistent logging and alerting around config changes and runtime behavior.
- Regularly rotate secrets to reduce exposure risk if a secret could have been read.
Proof-of-Concept / Payload Patterns (For Educational Use Only)
Here’s a conceptual example of what an attacker might try — shared strictly for defenders to test detection coverage:
- Inline Lua payload snippet (illustrative only; do not run in production):
function request(ctx, params)
local f = io.open('/etc/passwd', 'r')
if f then
local content = f:read('*all')
f:close()
ngx.log(ngx.ERR, "[PWNED] " .. content)
end
end
This simply reads a file and writes its contents to error logs where a monitoring solution might catch it.
Final Takeaway
At its core, CVE-2026-23742 is about giving too much power to inline scripting in a critical network component. Where scripting should be controlled and trusted, the old defaults allowed less-trusted actors to run code inside Skipper — and read anything that Skipper itself had access to.
That’s serious because:
- It can expose secrets.
- It doesn’t require complex exploit tools.
- It happens inside the routing layer, often overlooked.
Detection focuses on:
- Watch for unauthorized filter changes.
- Monitor Skipper logs for script execution and file dumps.
- Alert on suspicious response behavior.
Fix it by upgrading to v0.23.0 and tightening access around who can define filters.
