{"record":{"id":"15610e69f68af70f","repo":"BerriAI/litellm","slug":"couldn-t-get-cato-networks-api-key-either-set-the","errorCode":null,"errorMessage":"Couldn't get Cato Networks api key, either set the `CATO_API_KEY` in the environment or pass it as a parameter to the guardrail in the config file","messagePattern":"Couldn't get Cato Networks api key, either set the `CATO_API_KEY` in the environment or pass it as a parameter to the guardrail in the config file","errorType":"validation","errorClass":"CatoNetworksGuardrailMissingSecrets","httpStatus":null,"severity":"critical","filePath":"litellm/proxy/guardrails/guardrail_hooks/cato_networks/cato_networks.py","lineNumber":115,"sourceCode":"            GuardrailEventHooks.pre_call,\n            GuardrailEventHooks.during_call,\n            GuardrailEventHooks.post_call,\n        ]\n\n    def __init__(self, api_key: str | None = None, api_base: str | None = None, **kwargs):\n        kwargs.setdefault(\"supported_event_hooks\", list(self.get_supported_event_hooks()))\n        ssl_verify: Final = kwargs.pop(\"ssl_verify\", None)\n        self.async_handler = get_async_httpx_client(\n            llm_provider=httpxSpecialProvider.GuardrailCallback,\n            params={\"ssl_verify\": ssl_verify} if ssl_verify is not None else None,\n        )\n        self.api_key = api_key or os.environ.get(\"CATO_API_KEY\")\n        if not self.api_key:\n            msg: Final = (\n                \"Couldn't get Cato Networks api key, either set the `CATO_API_KEY` in the environment or \"\n                \"pass it as a parameter to the guardrail in the config file\"\n            )\n            raise CatoNetworksGuardrailMissingSecrets(msg)\n        self.api_base = api_base or os.environ.get(\"CATO_API_BASE\") or \"https://api.aisec.catonetworks.com\"\n        self.api_base = self.api_base.rstrip(\"/\")\n        self.ws_api_base = self.api_base.replace(\"http://\", \"ws://\").replace(\"https://\", \"wss://\")\n        self._ws_connect_ssl_kwargs = self._build_ws_ssl_kwargs(ssl_verify, self.ws_api_base)\n        super().__init__(**kwargs)\n\n    @staticmethod\n    def _build_ws_ssl_kwargs(ssl_verify: bool | str | None, ws_api_base: str) -> _WsSslKwargs:\n        \"\"\"Resolve the ``ssl`` argument for ``websockets.connect``. Mirrors the\n        ``ssl_verify`` handling applied to the HTTP handler so a custom Cato instance\n        behind TLS honours the same verification settings for streaming.\"\"\"\n        if ssl_verify is None or not ws_api_base.startswith(\"wss://\"):\n            return {}\n        ssl_config = get_ssl_configuration(ssl_verify)\n        if ssl_config is False:\n            ssl_config = ssl.create_default_context()\n            ssl_config.check_hostname = False\n            ssl_config.verify_mode = ssl.CERT_NONE","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/cato_networks/cato_networks.py#L97-L133","documentation":"CatoNetworksGuardrailMissingSecrets is raised from the Cato Networks guardrail constructor when neither the api_key parameter nor the CATO_API_KEY environment variable yields a key. It is a fail-fast startup error: the guardrail cannot authenticate to the Cato AI Security API (api.aisec.catonetworks.com by default), so initialization aborts rather than silently allowing unscanned traffic.","triggerScenarios":"Adding a cato_networks guardrail to config.yaml without api_key in litellm_params while the proxy process environment lacks CATO_API_KEY; deploying via Docker/systemd where the env var is set in a shell but not in the service unit; secrets referenced with the wrong secret manager path so get_secret resolves to None.","commonSituations":"Env var set in an interactive shell but the proxy runs under a different user/service; typos in the variable name (CATO_APIKEY, CATO_TOKEN); key stored in litellm's secret_manager but the guardrail only reads the literal env var and the api_key param.","solutions":["Set CATO_API_KEY in the environment the proxy actually runs in (systemd Environment=, docker env, .env loaded by the proxy).","Or pass api_key directly (or via <secret_manager> reference) in the guardrail's litellm_params.","Verify with a quick check before startup: printenv CATO_API_KEY or litellm's secret resolution test.","Restart/reload the proxy after the env change — the check runs at guardrail init, not per request."],"exampleFix":"# before\nguardrails:\n  - guardrail_name: cato\n    litellm_params:\n      guardrail: cato_networks\n\n# after — explicit key via environment\n#   export CATO_API_KEY=xxxx  (in the service env)\nguardrails:\n  - guardrail_name: cato\n    litellm_params:\n      guardrail: cato_networks\n      api_key: os.environ/CATO_API_KEY","handlingStrategy":"validation","validationCode":"import os\nfrom litellm import get_secret_str\nkey = get_secret_str(\"CATO_API_KEY\") or os.environ.get(\"CATO_API_KEY\")\nif not key:\n    raise SystemExit(\"Set CATO_API_KEY before starting the litellm proxy\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Put secret preflight checks (all guardrail env keys) into the container entrypoint so the process fails before accepting traffic.","Use docker compose env_file / systemd EnvironmentFile consistently for the proxy service.","Prefer litellm secret-manager references over raw env vars in config to centralize key management."],"tags":["litellm","guardrails","cato-networks","api-key","configuration","startup"],"backgroundTag":"missing-api-key","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}