mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
fix: require explicit anonymous webhook access (#14890)
### What problem does this PR solve? Fixes #14882 Agent webhook execution currently fails open when the saved webhook `security` block is missing/empty, or when `auth_type` is set to `none`. This allows unauthenticated webhook invocation without an explicit operator opt-in. This PR makes anonymous webhook access explicit: - Rejects missing or empty webhook security config. - Requires `allow_anonymous: true` when `auth_type` is `none`. - Preserves explicit anonymous webhooks by having the frontend serialize `allow_anonymous: true` when the user selects `None` auth. - Updates webhook unit tests to cover both denied implicit-anonymous configs and allowed explicit-anonymous configs. ### Type of change - [x] Bug Fix - [x] Security hardening - [x] Test ### Tests - [x] `ZHIPU_AI_API_KEY=dummy uv run python -m pytest --confcutdir=test/testcases/test_web_api/test_agent_app test/testcases/test_web_api/test_agent_app/test_agents_webhook_unit.py` - [x] `uv run ruff check api/apps/restful_apis/agent_api.py test/testcases/test_web_api/test_agent_app/test_agents_webhook_unit.py` - [x] `npm exec eslint src/pages/agent/utils.ts src/pages/agent/form/begin-form/schema.ts` --------- Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
This commit is contained in:
@@ -2881,6 +2881,9 @@ Important structured information may include: names, dates, locations, events, k
|
||||
'Accepted Response: The system returns an acknowledgment immediately after the request is validated, while the workflow continues to execute asynchronously in the background. /Final Response: The system returns a response only after the workflow execution is completed.',
|
||||
authMethods: 'Authentication methods',
|
||||
authType: 'Authentication type',
|
||||
allowAnonymous: 'Allow anonymous access',
|
||||
allowAnonymousTip:
|
||||
'Anyone with this webhook URL can trigger the agent when this is enabled.',
|
||||
limit: 'Request frequency limit',
|
||||
per: 'Time period',
|
||||
maxBodySize: 'Maximum body size',
|
||||
|
||||
@@ -29,6 +29,7 @@ export const BeginFormSchema = z.object({
|
||||
per: z.string().optional(),
|
||||
}),
|
||||
max_body_size: z.string(),
|
||||
allow_anonymous: z.boolean().optional(),
|
||||
jwt: z
|
||||
.object({
|
||||
algorithm: z.string().default(WebhookJWTAlgorithmList[0]).optional(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { WebhookJWTAlgorithmList } from '@/constants/agent';
|
||||
import { WebhookSecurityAuthType } from '@/pages/agent/constant';
|
||||
import { buildOptions } from '@/utils/form';
|
||||
@@ -100,7 +101,21 @@ export function Auth() {
|
||||
[WebhookSecurityAuthType.Token]: renderTokenAuth,
|
||||
[WebhookSecurityAuthType.Basic]: renderBasicAuth,
|
||||
[WebhookSecurityAuthType.Jwt]: renderJwtAuth,
|
||||
[WebhookSecurityAuthType.None]: () => null,
|
||||
[WebhookSecurityAuthType.None]: () => (
|
||||
<RAGFlowFormItem
|
||||
name="security.allow_anonymous"
|
||||
label={t('flow.webhook.allowAnonymous')}
|
||||
tooltip={t('flow.webhook.allowAnonymousTip')}
|
||||
horizontal
|
||||
>
|
||||
{(field) => (
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -456,6 +456,14 @@ function transformBeginParams(params: BeginFormSchemaType) {
|
||||
required_claims: security?.jwt?.required_claims.map((x) => x.value),
|
||||
};
|
||||
}
|
||||
if (
|
||||
params.security?.auth_type === WebhookSecurityAuthType.None &&
|
||||
params.security?.allow_anonymous
|
||||
) {
|
||||
nextSecurity.allow_anonymous = true;
|
||||
} else {
|
||||
delete nextSecurity.allow_anonymous;
|
||||
}
|
||||
return {
|
||||
...params,
|
||||
schema: transformRequestSchemaToJsonschema(params.schema),
|
||||
|
||||
Reference in New Issue
Block a user