README.md
Rendering markdown...
"""
Dummy backend for the CVE-2026-48020 PoC.
It is a tiny HTTP server that echoes the exact request path it receives and
returns a canned secret for the protected paths. This lets us observe what
Traefik forwarded after routing + StripPrefix + normalisation.
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
# Each path is guarded by the `protected` router in dynamic.yml and must
# only ever be reachable after the basicAuth middleware succeeds.
PROTECTED = {
"/admin": {"secret": "ADMIN_SECRET_REACHED", "role": "administrator"},
"/internal/config": {"secret": "TRAEFIK_LAB_INTERNAL_CONFIG", "scope": "internal"},
"/admin/exec": {"secret": "EXEC_ENDPOINT_REACHED", "note": "conditional RCE primitive"},
}
class Handler(BaseHTTPRequestHandler):
def log_message(self, fmt, *args):
# Keep stdout clean; the PoC client prints the interesting part.
return
def _json(self, status, obj):
body = json.dumps(obj).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
# The backend faithfully reflects the (possibly normalised) path
# Traefik handed to it. Any "secret" here means an unauthenticated
# caller reached a protected resource.
if self.path in PROTECTED:
payload = dict(PROTECTED[self.path])
payload["seen_path"] = self.path
payload["bypassed_auth"] = True
self._json(200, payload)
else:
self._json(404, {"seen_path": self.path, "secret": None})
if __name__ == "__main__":
HTTPServer(("0.0.0.0", 9000), Handler).serve_forever()