XX-net/XX-Net · warning

decode auth fail:%r

Error message

decode auth fail:%r

What it means

With webui_auth enabled, the Basic auth header's base64 payload failed to decode or split into user:password; the client gets a 401 with WWW-Authenticate after this warning.

Source

Thrown at code/default/launcher/web_control.py:222

        # check for '..', which will leak file
        if re.search(r'(\.{2})', self.path) is not None:
            self.wfile.write(b'HTTP/1.1 404\r\n\r\n')
            xlog.warn('%s %s %s haking', self.address_string(), self.command, self.path)
            return

        if config.webui_auth:
            auth = self.headers.get("Authorization")
            if not auth or not auth.startswith("Basic "):
                return self.send_response(content="", headers={
                    "WWW-Authenticate": 'Basic realm="Access to admin"'
                }, status=401)

            try:
                user_pass = base64.b64decode(auth[6:])
                user_pass = utils.to_str(user_pass)
                user, password = user_pass.split(":")[0:2]
            except Exception as e:
                xlog.warn("decode auth fail:%r", e)
                return self.send_response(content="", headers={
                    "WWW-Authenticate": 'Basic realm="Access to admin"'
                }, status=401)

            if config.webui_auth.get(user) != password:
                return self.send_response(content="", headers={
                    "WWW-Authenticate": 'Basic realm="Access to admin"'
                }, status=401)

        url_path = urlparse(self.path).path
        if url_path == '/':
            return self.req_index_handler()

        url_path_list = self.path.split('/')
        if len(url_path_list) >= 3 and url_path_list[1] == "module":
            module = url_path_list[2]
            if len(url_path_list) >= 4 and url_path_list[3] == "control":
                if module not in module_init.proc_handler:

View on GitHub (pinned to cfa5bc17b6)

Solutions

  1. Send a proper Basic header: 'Authorization: Basic ' + base64(user:password).
  2. Ensure the password contains a colon-free format and UTF-8 encoding.
  3. Check no proxy strips Authorization; bypass proxy for localhost.

Example fix

// before
curl -H 'Authorization: Basic abc' http://127.0.0.1:8085/
// after
curl -u user:pass http://127.0.0.1:8085/
Defensive patterns

Strategy: try-catch

Validate before calling

import base64
def parse_basic(auth):
    if not auth or not auth.startswith('Basic '): return None
    try:
        s = base64.b64decode(auth[6:]).decode('utf-8')
        u, p = s.split(':', 1)
        return u, p
    except Exception:
        return None

Try / catch

try:
    user, pw = parse_basic(self.headers.get('Authorization'))
except ValueError:
    return send_401()

Prevention

When it happens

Trigger: Malformed Authorization header (not valid base64, or no ':' separator) — hand-crafted requests, broken proxies stripping/rewriting the header, or browser sending credentials in an unexpected format.

Common situations: Typos in scripted curl requests; an intermediary mangling the header; very old browsers with non-Latin credentials.

Related errors


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/e4c6040d83137952. Report an issue: GitHub.