{"record":{"id":"414482bf7574ec15","repo":"HKUDS/Vibe-Trading","slug":"settings-access-requires-api-auth-key-or-a-local-l","errorCode":null,"errorMessage":"Settings access requires API_AUTH_KEY or a local loopback client","messagePattern":"Settings access requires API_AUTH_KEY or a local loopback client","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"warning","filePath":"agent/src/api/security.py","lineNumber":634,"sourceCode":"\n    if _is_local_client(request):\n        return\n    raise HTTPException(\n        status_code=status.HTTP_403_FORBIDDEN,\n        detail=\"API_AUTH_KEY is required for non-local API access\",\n    )\n\n\nasync def require_local_or_auth(\n    request: Request,\n    cred: Optional[HTTPAuthorizationCredentials] = Security(_security),\n) -> None:\n    \"\"\"Protect settings access when dev-mode auth is disabled.\"\"\"\n    if _configured_api_key():\n        await require_auth(request, cred)\n        return\n    if not _is_local_client(request):\n        raise HTTPException(\n            status_code=status.HTTP_403_FORBIDDEN,\n            detail=\"Settings access requires API_AUTH_KEY or a local loopback client\",\n        )\n\n\nasync def require_settings_write_auth(\n    request: Request,\n    cred: Optional[HTTPAuthorizationCredentials] = Security(_security),\n) -> None:\n    \"\"\"Require explicit authorization before changing credential-routing settings.\"\"\"\n    api_key = _configured_api_key()\n    if api_key:\n        token = _auth_credential_from_header_or_query(cred, None, allow_query=False)\n        if not token or not hmac.compare_digest(token, api_key):\n            raise HTTPException(status_code=401, detail=\"Invalid or missing API key\")\n        return\n\n    if not _is_local_client(request):","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/api/security.py#L616-L652","documentation":"require_local_or_auth protects settings endpoints when dev-mode auth is disabled: with no API_AUTH_KEY configured, settings may only be read from a loopback client; anything else gets 403. When a key IS configured it defers to require_auth instead, so this branch only fires in key-less mode.","triggerScenarios":"A GET on a settings route from a non-local address while API_AUTH_KEY is unset and dev-mode auth is disabled.","commonSituations":"Remote management UI or curl hitting /settings on a key-less dev instance; container orchestration probing the settings endpoint over the pod network; accessing via hostname that resolves to a non-loopback IP.","solutions":["Read settings from localhost (127.0.0.1) when running key-less","Configure API_AUTH_KEY if settings must be accessed remotely, then send the key","Restrict network exposure of the API port (firewall/bind to 127.0.0.1) in dev","If behind a proxy, make sure forwarded client IP handling is configured before relying on loopback detection"],"exampleFix":"# before (no API_AUTH_KEY set)\ncurl http://server.lan:8000/settings   # 403\n\n# after\ncurl http://127.0.0.1:8000/settings\n# or: set API_AUTH_KEY, then curl -H \"Authorization: Bearer $API_AUTH_KEY\" http://server.lan:8000/settings","handlingStrategy":"validation","validationCode":"import os\nif not os.environ.get(\"API_AUTH_KEY\"):\n    assert urlparse(BASE).hostname in (\"127.0.0.1\", \"localhost\", \"::1\"), \\\n        \"Settings reads from a remote host will 403 while no API_AUTH_KEY is set\"","typeGuard":null,"tryCatchPattern":"try:\n    r = client.get(\"/settings\"); r.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 403:\n        # key-less mode: only loopback may read settings\n        raise RuntimeError(\"Run locally or configure API_AUTH_KEY to read settings\") from e\n    raise","preventionTips":["Treat settings endpoints as privileged even in dev","Configure API_AUTH_KEY before building remote dashboards","Restrict API port exposure with firewall rules in key-less setups"],"tags":["settings","auth","http-403","loopback"],"backgroundTag":"api-key-required-non-local","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}