Security

Rate Limiting

Rate limiting can be used to restrict how often someone can execute an operation in a defined time frame. For app framework controllers it is recommended to use rate limiting attributes.

Outside controllers, e.g. in DAV code, it’s also possible to guard operations by injecting \OCP\Security\RateLimiting\ILimiter and registering requests before the operation:

<?php

use OCP\Security\RateLimiting\ILimiter;

class MyDavPlugin {
    private ILimiter $limiter;

    public function __construct(ILimiter $limiter) {
        $this->limiter = $limiter;
    }

    public function calledAnonymously(): void {
        try {
            $this->limiter->registerAnonRequest(
                'my-dav-plugin-anon',
                5, // Allow five executions …
                60 * 60, // … per hour
            );
        } catch (IRateLimitExceededException $exception) {
            // Respond with a HTTP 429 error
        }

        // No rate limiting reached. Carry on.
    }

    public function calledByUser(IUser $user): void {
        try {
            $this->limiter->registerUserRequest(
                'my-dav-plugin-user',
                5, // Allow five executions …
                60 * 60, // … per hour
                $user
            );
        } catch (IRateLimitExceededException $exception) {
            // Respond with a HTTP 429 error
        }

        // No rate limiting reached. Carry on.
    }
}

Remote Host Validation

Nextcloud can help validating a remote host so that no internal infrastructure is contacted by user-provided host names or IPs. The validator \OCP\Security\IRemoteHostValidator can be injected into any app class:

<?php

use OCP\Security\IRemoteHostValidator;

class MyRemoteServerIntegration {
    private IRemoteHostValidator $hostValidator;

    public function __construct(IRemoteHostValidator $hostValidator) {
        $this->hostValidator = $hostValidator;
    }

    public function contactRemoteServer(string $hostname): void {
        if (!$this->hostValidator->isValid($hostname)) {
            // ABORT
        }

        // Contact the server
    }
}

Note

Nextcloud’s HTTP clients obtained from \OCP\Http\Client\IClientService have this validation built in so you don’t have to check hosts of HTTP requests as long as you use this provided abstraction.

Trusted domain

In some cases it might be required that an app checks that a user given link is one of the current instance. This is possible with the OCP\Security\ITrustedDomainHelper:

<?php

declare(strict_types=1);
use OCP\Security\ITrustedDomainHelper;

$helper = \OC::$server->get(ITrustedDomainHelper::class);

// Compare a full URL example given
$url = 'https://localhost/nextcloud/index.php/apps/files/';
$helper->isTrustedUrl($url);

// Compare a domain and port
$domain = 'example.tld:8443';
$helper->isTrustedDomain($domain);