bug: Null byte (\x00) in POST body to /oidc/token causes HTTP 500 instead of 400
bug
### Describe the bug
When a null byte (`\x00`) is present in an `application/x-www-form-urlencoded` POST body sent to the `/oidc/token` endpoint, the server returns an HTTP 500 Internal Server Error with `{"message":"Internal server error."}` instead of the expected HTTP 400 Bad Request.
Root cause: In `packages/core/src/oidc/init.ts:462`, the request body is parsed via `querystring.parse(body)`, which passes null bytes through unchanged. The downstream `oidc-provider` library then throws an unhandled generic `Error` (not an `OIDCProviderError` that would be caught properly), causing the Koa generic error handler to return a 500.
### Expected behavior
The server should return HTTP 400 Bad Request (or an OAuth error response such as `invalid_request`), since null bytes are not valid in `application/x-www-form-urlencoded` values. The request should be cleanly rejected at the input parsing layer rather than propagating as an unhandled exception.
### How to reproduce?
Prerequisites: Any running Logto instance (default OIDC port 3001).
Step 1 — Normal request: Send a well-formed token endpoint request and observe the expected error (e.g., `invalid_client` or `invalid_request`):
```html
curl -v -X POST http://127.0.0.1:3001/oidc/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&client_id=test&code=test"
```
Step 2 — Null byte injection: Inject a null byte into the POST body:
```html
printf 'grant_type=authorization_code\x00&client_id=test&code=test' | \
curl -v -X POST http://127.0.0.1:3001/oidc/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-binary @-
Observed: HTTP 500 with {"message":"Internal server error."}
```
Step 3 — Alternative Python reproduction:
```html
import requests
url = "http://127.0.0.1:3001/oidc/token"
body = "grant_type=authorization_code\x00&client_id=test&code=test"
resp = requests.post(url, data=body, headers={"Content-Type": "application/x-www-form-urlencoded"})
print(f"Status: {resp.status_code}") # 500 (expected: 400)
print(f"Body: {resp.text}") # {"message":"Internal server error."}
```
Environment:
- Logto Docker image: svhd/logto:latest
- OIDC port: 3001
- Endpoint: /oidc/token
### Environment
Self-hosted (Docker image)
### Screenshots
_No response_
关闭于 2026-06-11 0 条评论