-
Notifications
You must be signed in to change notification settings - Fork 615
[BUG][API]: admin_test_gateway crashes with ValueError on decode_auth of masked auth_value #3539
Description
Bug Description
The admin_test_gateway endpoint (POST /admin/gateways/test) crashes with a 500 Internal Server Error for all gateways — both those with authentication and those without.
Root Cause
mcpgateway/admin.py:12992 unconditionally calls decode_auth() on a masked GatewayRead object:
else:
headers: dict = decode_auth(gateway.auth_value if gateway else None)Problem 1: Masked value passed to decryption
get_first_gateway_by_url() (line 12945) returns a GatewayRead.masked() object where auth_value is the literal string "*****". decode_auth("*****") base64-decodes this to a 3-byte payload, then tries to extract a 12-byte nonce — producing:
ValueError: Nonce must be between 8 and 128 bytes
Problem 2: No auth_type guard
The else branch at line 12991 runs for ALL non-OAuth gateways — including those with auth_type=None. For gateways without auth, decode_auth(None) returns {} (harmless), but for gateways with auth, the masked value crashes.
Problem 3: ORM mutation from _prepare_gateway_for_read
get_first_gateway_by_url() calls the deprecated _prepare_gateway_for_read() which:
- Mutates the attached ORM object's
auth_valuefrom dict → encoded string - Returns a
.masked()GatewayReadwhereauth_value = "*****"
So the raw auth_value is never available to the caller.
Reproduction Steps
- Register any gateway (with or without auth)
- Open Admin UI → MCP Servers → click "Test" on any gateway
- Click "Test" in the connectivity dialog
- Observe 500 Internal Server Error
curl -X POST http://localhost:8080/admin/gateways/test \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"baseUrl": "http://fast_time_server:8080/sse", "method": "GET", "path": "/health", "headers": {}, "body": ""}'
# Returns: Internal Server ErrorStack Trace
File "/app/mcpgateway/admin.py", line 12992, in admin_test_gateway
headers: dict = decode_auth(gateway.auth_value if gateway else None)
File "/app/mcpgateway/utils/services_auth.py", line 234, in decode_auth
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
ValueError: Nonce must be between 8 and 128 bytes
Suggested Fix
Option A — query raw DB object instead of masked GatewayRead:
# Use raw DB query instead of get_first_gateway_by_url (which masks)
raw_gateway = db.execute(select(DbGateway).where(DbGateway.url == validated_base_url)).scalars().first()
if raw_gateway and raw_gateway.auth_type in ("basic", "bearer", "authheaders"):
if isinstance(raw_gateway.auth_value, dict):
headers.update(raw_gateway.auth_value)
elif isinstance(raw_gateway.auth_value, str):
headers.update(decode_auth(raw_gateway.auth_value))Option B — guard with auth_type check and handle masked sentinel:
if gateway and gateway.auth_type and gateway.auth_type != "oauth" and gateway.auth_value and gateway.auth_value != settings.masked_auth_value:
headers.update(decode_auth(gateway.auth_value))Impact
- Severity: Medium — admin UI feature is completely broken for all gateways
- Scope: Only the admin "Test Gateway Connectivity" button is affected
- Security: No data exposure, but the 500 response leaks the error type in server logs