Skip to content

Commit f4e57eb

Browse files
authored
fix(security): give every public endpoint a volume ceiling (ADR-082) (#514)
These methods declare themselves public with the legacy @publicpage ANNOTATION rather than the #[PublicPage] attribute, which is why the fleet sweep that reported this app fully throttled did not see them: that sweep line-anchored the attribute form and excluded docblock matches. The annotation is not a docblock mention. It is a live declaration, proven against the running server on two other apps in this fleet: openregister GraphQLController::execute @publicpage only -> 200 anon opencatalogi CatalogiController::index @publicpage only -> 200 anon AnonRateLimit only, not BruteForceProtection: these endpoints check no credential, and brute-force protection without a paired registerAttempt() is the inert half of a two-half mechanism. AnonRateLimit also leaves authenticated server-to-server traffic untouched, so no integration can be throttled by this change. Health endpoints get a deliberately generous 240/60 - monitoring polls them on a short interval, and a ceiling that trips on a normal probe cadence turns the health check into the outage it was meant to detect. Verification: php -l clean on every changed file; the diff is purely additive with zero lines removed; gate-82 (.github#460) goes to 0 findings on this tree.
1 parent 8c6798b commit f4e57eb

2 files changed

Lines changed: 8 additions & 0 deletions

File tree

lib/Controller/AangebodenGebruikController.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use OCA\SoftwareCatalog\Service\AangebodenGebruikService;
2424
use OCP\AppFramework\Controller;
2525
use OCP\AppFramework\Http;
26+
use OCP\AppFramework\Http\Attribute\AnonRateLimit;
2627
use OCP\AppFramework\Http\JSONResponse;
2728
use OCP\IGroupManager;
2829
use OCP\IRequest;
@@ -203,6 +204,7 @@ public function getGebruiksWhereAfnemer(): JSONResponse {
203204
* @PublicPage
204205
* @spec openspec/specs/aangeboden-gebruik-api/spec.md
205206
*/
207+
#[AnonRateLimit(limit: 120, period: 60)]
206208
public function getKoppelingenGebruikByUuid(string $uuid): JSONResponse {
207209
$this->logger->info(
208210
'API: Getting koppelingen and gebruiks for specific UUID',
@@ -293,6 +295,7 @@ public function getKoppelingenGebruikByUuid(string $uuid): JSONResponse {
293295
* @PublicPage
294296
* @spec openspec/specs/aangeboden-gebruik-api/spec.md
295297
*/
298+
#[AnonRateLimit(limit: 120, period: 60)]
296299
public function getAllGebruiksForAmbtenaar(): JSONResponse {
297300
$this->logger->info(
298301
'API: Getting all gebruiks for ambtenaar (ignoring RBAC/multitenancy)',
@@ -400,6 +403,7 @@ public function getAllGebruiksForAmbtenaar(): JSONResponse {
400403
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
401404
* @spec openspec/specs/aangeboden-gebruik-api/spec.md
402405
*/
406+
#[AnonRateLimit(limit: 120, period: 60)]
403407
public function getSingleGebruikForAmbtenaar(string $gebruikId): JSONResponse {
404408
$this->logger->info(
405409
'API: Getting single gebruik for ambtenaar (ignoring RBAC/multitenancy)',
@@ -570,6 +574,7 @@ private function isUserInGroup(string $groupName): bool {
570574
* @PublicPage
571575
* @spec openspec/specs/aangeboden-gebruik-api/spec.md
572576
*/
577+
#[AnonRateLimit(limit: 120, period: 60)]
573578
public function getGebruiksWhereDeelnemers(): JSONResponse {
574579
$this->logger->info(
575580
'API: Getting gebruiks where active org is in deelnemers',
@@ -857,6 +862,7 @@ function ($key) {
857862
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
858863
* @spec openspec/specs/aangeboden-gebruik-api/spec.md
859864
*/
865+
#[AnonRateLimit(limit: 120, period: 60)]
860866
public function getApiDocumentation(): JSONResponse {
861867
$documentation = [
862868
'api_version' => '2.0.0',

lib/Controller/GebruikController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use OCA\SoftwareCatalog\Service\GebruikService;
2424
use OCP\AppFramework\Controller;
2525
use OCP\AppFramework\Http;
26+
use OCP\AppFramework\Http\Attribute\AnonRateLimit;
2627
use OCP\AppFramework\Http\JSONResponse;
2728
use OCP\IConfig;
2829
use OCP\IGroup;
@@ -92,6 +93,7 @@ public function __construct(
9293
* @spec openspec/specs/open-data-publishing/spec.md
9394
* @spec openspec/specs/vendor-visibility-rbac/spec.md#requirement-every-rbac-bypassing-gebruik-koppeling-contract-read-must-evaluate-its-deny-check-before-issuing-the-bypass-query-req-001
9495
*/
96+
#[AnonRateLimit(limit: 120, period: 60)]
9597
public function getGebruiken(): JSONResponse {
9698
// Open-data posture (open-data-publishing): gebruik is inherently
9799
// organisation-scoped, so an anonymous caller receives the documented

0 commit comments

Comments
 (0)