{"record":{"id":"eb51e56932915053","repo":"infiniflow/ragflow","slug":"anonymous-webhook-access-requires-allow-anonymous","errorCode":null,"errorMessage":"Anonymous webhook access requires allow_anonymous to be true","messagePattern":"Anonymous webhook access requires allow_anonymous to be true","errorType":"exception","errorClass":"Exception","httpStatus":400,"severity":"error","filePath":"api/apps/restful_apis/agent_api.py","lineNumber":1913,"sourceCode":"        await _validate_max_body_size(security_cfg)\n\n        # 2. Validate IP whitelist\n        _validate_ip_whitelist(security_cfg)\n\n        # # 3. Validate rate limiting\n        _validate_rate_limit(security_cfg)\n\n        # 4. Validate authentication\n        auth_type = security_cfg.get(\"auth_type\", \"none\")\n\n        if auth_type == \"none\":\n            if not _allow_anonymous_webhook(security_cfg):\n                logging.warning(\n                    \"Webhook denied: anonymous access missing explicit opt-in agent_id=%s method=%s\",\n                    agent_id,\n                    request.method,\n                )\n                raise Exception(\"Anonymous webhook access requires allow_anonymous to be true\")\n            return\n\n        if auth_type == \"token\":\n            _validate_token_auth(security_cfg)\n\n        elif auth_type == \"basic\":\n            _validate_basic_auth(security_cfg)\n\n        elif auth_type == \"jwt\":\n            _validate_jwt_auth(security_cfg)\n\n        else:\n            raise Exception(f\"Unsupported auth_type: {auth_type}\")\n\n    async def _validate_max_body_size(security_cfg):\n        \"\"\"Check request size does not exceed max_body_size.\"\"\"\n        max_size = security_cfg.get(\"max_body_size\")\n        if not max_size:","sourceCodeStart":1895,"sourceCodeEnd":1931,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/apps/restful_apis/agent_api.py#L1895-L1931","documentation":"When a webhook's security config has auth_type 'none' (or omits it), validate_webhook_security checks _allow_anonymous_webhook(security_cfg); unless allow_anonymous is explicitly true it raises Exception('Anonymous webhook access requires allow_anonymous to be true') (agent_api.py:1913). Anonymous is opt-in only - unauthenticated requests are rejected even though a security block exists.","triggerScenarios":"security config contains {\"auth_type\": \"none\"} without allow_anonymous: true; auth_type omitted (defaults to 'none') and allow_anonymous not set; a client calls the webhook without credentials expecting it to be open.","commonSituations":"Users set a security block just to configure rate limits or IP whitelist but leave authentication off, forgetting the separate anonymous opt-in; trial webhooks intended for public testing.","solutions":["If the webhook must be public, set \"allow_anonymous\": true in the security config (accepting anyone can invoke it - pair with IP whitelist/rate limits).","Otherwise pick a real auth_type: 'token', 'basic', or 'jwt' and configure its fields.","Re-publish/restart the agent so the updated security config takes effect.","Send the matching credentials from the caller once auth is enabled (Bearer token, Basic header, or JWT)."],"exampleFix":"// before\n\"security\": {\"auth_type\": \"none\", \"max_body_size\": \"1MB\"}\n\n// after (public, with mitigation)\n\"security\": {\"auth_type\": \"none\", \"allow_anonymous\": true, \"max_body_size\": \"1MB\", \"rate_limit\": \"10/min\"}","handlingStrategy":"validation","validationCode":"sec = agent_config.get(\"webhook\", {}).get(\"security\", {})\nif sec.get(\"auth_type\", \"none\") == \"none\" and sec.get(\"allow_anonymous\") is not True:\n    raise ValueError(\"Anonymous webhook requires allow_anonymous=true, or pick token/basic/jwt auth\")","typeGuard":"def is_valid_webhook_anonymous(sec: dict) -> bool:\n    return sec.get(\"auth_type\", \"none\") != \"none\" or sec.get(\"allow_anonymous\") is True","tryCatchPattern":"try:\n    resp = await invoke_webhook(session, url, payload)\nexcept WebhookRejected as e:\n    if \"allow_anonymous\" in str(e):\n        raise ConfigError(\"Webhook is not open: either enable allow_anonymous or send credentials\") from e\n    raise","preventionTips":["If you intend public access, set allow_anonymous=true deliberately and add rate limiting plus IP whitelist.","Otherwise configure a real auth_type and never assume 'none' means open - it means opt-in required.","Automate a pre-publish check for the auth_type/allow_anonymous pairing."],"tags":["webhook","agent","security","authentication","api"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}