{"record":{"id":"174ac9721808b5a3","repo":"BerriAI/litellm","slug":"plugin-claim-audience-mismatch","errorCode":null,"errorMessage":"Plugin claim audience mismatch","messagePattern":"Plugin claim audience mismatch","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/plugin_routes.py","lineNumber":171,"sourceCode":"        \"exp\": int(time.time()) + _CLAIM_TTL_SECONDS,\n    }\n    return _plugin_fernet(plugin_name).encrypt(json.dumps(claim).encode()).decode()\n\n\ndef verify_plugin_session_claim(plugin_name: str, ciphertext: str) -> dict:\n    \"\"\"Verify and decode a plugin session claim.\n\n    Raises ValueError if the HMAC is invalid, the audience is wrong, or\n    the claim is expired.  Returns the decoded claim dict on success.\n    \"\"\"\n    try:\n        raw: Final = _plugin_fernet(plugin_name).decrypt(ciphertext.encode(), ttl=_CLAIM_TTL_SECONDS)\n        claim: Final = json.loads(raw)\n    except (InvalidToken, Exception) as exc:\n        raise ValueError(\"Invalid, tampered, or expired plugin session claim\") from exc\n\n    if claim.get(\"plugin\") != plugin_name:\n        raise ValueError(\"Plugin claim audience mismatch\")\n    if int(claim.get(\"exp\", 0)) < int(time.time()):\n        raise ValueError(\"Plugin session claim expired\")\n    return claim\n\n\n# ---------------------------------------------------------------------------\n# Config\n# ---------------------------------------------------------------------------\ndef register_plugins_from_config(general_settings: dict[str, object]) -> None:\n    \"\"\"Replace the plugin registry from general_settings.\n\n    Replaces (not merges) so plugins removed from config are immediately\n    unreachable without requiring a process restart.\n    \"\"\"\n    raw: Final = general_settings.get(\"plugins\")\n    entries: Final[list[object]] = raw if isinstance(raw, list) else []\n    new_registry: Final = {p.name: p for p in (PluginConfig.model_validate(entry) for entry in entries)}\n    _plugin_registry.clear()","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/plugin_routes.py#L153-L189","documentation":"Plugin session-claim verification: the Fernet token decrypted and decoded successfully, but the claim's audience does not match the plugin making the request, so a token minted for one plugin is being replayed against another; verification raises ValueError.","triggerScenarios":"Thrown at litellm/proxy/plugin_routes.py:171 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Load the plugin through its registered UI route so the claim audience matches; do not reuse claims across plugins."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}