Skip to content

🐛 fix(context-url): add authorization, rate limiting, and input validation#4613

Merged
Ostico merged 1 commit into
developfrom
fix-context-url-api
Jun 7, 2026
Merged

🐛 fix(context-url): add authorization, rate limiting, and input validation#4613
Ostico merged 1 commit into
developfrom
fix-context-url-api

Conversation

@Ostico
Copy link
Copy Markdown
Contributor

@Ostico Ostico commented Jun 7, 2026

Summary

Fix critical IDOR vulnerability in Context URL API: any authenticated user could read/write context URLs for any project, file, or segment. Added full authorization chain, rate limiting, entity validation, and unified JSON schema validation.

Type

  • fix — bug fix

Changes

File Change
lib/Routes/api_v3_routes.php Add [:id_project]/[:password] to context-url route prefix
lib/Controller/API/App/ContextUrlController.php Add ProjectPasswordValidator + ProjectAccessValidator chain in afterConstruct, RateLimiterService (IP + email), entity existence and domain ownership checks, unified JSON body validation via schema, DI refactor for testability
inc/validation/schema/segment_context_url.json Unified schema: required context_url (format: uri), nullable id_segment and id_file
lib/Model/Segments/SegmentMetadataDao.php Parameterize getBySegmentIds() IN clause to prevent SQL injection
tests/unit/Core/Controllers/ContextUrlControllerTest.php 19 tests covering rate limiting, authorization, JSON schema validation, entity existence, domain ownership, and happy paths (84% line coverage)

Testing

  • vendor/bin/phpunit --exclude-group=ExternalServices --no-coverage passes
  • ./vendor/bin/phpstan passes (0 errors, with baseline)
  • New tests added for changed behavior
  • Regression tests added for bug fixes
PHPStan: [OK] No errors
PHPUnit: OK (19 tests, 32 assertions)
Coverage: Controller\API\App\ContextUrlController — Lines: 84.21% (96/114)

AI Disclosure

  • AI tools were used — name the agent/tool below

Claude Code (claude-opus-4-6)

Notes

  • Breaking API change: all context-url endpoints now require id_project and password in the route path (/api/v3/context-url/:id_project/:password/...) and JSON body instead of form params
  • Rate limit: 10 requests per minute-window per identifier (IP + email), with penalty TTL reset on breach

Copilot AI review requested due to automatic review settings June 7, 2026 09:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request hardens the /api/v3/context-url endpoints to address an IDOR risk by enforcing project/password scoping in routes, adding an authorization chain in the controller, introducing request body JSON-schema validation, and adding rate limiting plus entity ownership checks before writing context URLs.

Changes:

  • Updated v3 routes to include id_project and password in the context-url route prefix.
  • Refactored ContextUrlController to require validated project context, validate JSON body via a shared schema, rate-limit requests, and validate file/segment membership in the project.
  • Improved SegmentMetadataDao::getBySegmentIds() by parameterizing the IN (...) clause; added new unit tests covering the new controller behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/Routes/api_v3_routes.php Scopes context-url endpoints under /:id_project/:password to support project/password validation.
lib/Controller/API/App/ContextUrlController.php Adds validator chain, JSON body validation, rate limiting, and entity existence/ownership checks.
inc/validation/schema/segment_context_url.json Introduces a shared JSON schema for context-url payload validation.
lib/Model/Segments/SegmentMetadataDao.php Parameterizes IN queries for segment metadata lookups.
tests/unit/Core/Controllers/ContextUrlControllerTest.php Adds unit coverage for rate limiting, validation failures, authorization, existence checks, and happy paths.

Comment thread lib/Model/Segments/SegmentMetadataDao.php
@github-actions

This comment was marked as outdated.

@Ostico Ostico force-pushed the fix-context-url-api branch from cb425e5 to 5b74d84 Compare June 7, 2026 11:10
@Ostico Ostico changed the title Fix context url api 🐛 fix(context-url): add authorization, rate limiting, and input validation Jun 7, 2026
@github-actions

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor Author

@Ostico Ostico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both Copilot findings fixed in latest push (5298c59):

  1. Empty array guardgetBySegmentIds() returns [] immediately for empty $ids
  2. Cache key regression — explicit $keyMap (self::_keymap_get_by_segment_ids . $key) passed to _fetchObjectMap() to preserve cache eviction

Unit test added: SegmentMetadataDaoTest::getBySegmentIds_returns_empty_array_for_empty_ids

@github-actions

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings June 7, 2026 11:36
@Ostico Ostico force-pushed the fix-context-url-api branch from 5298c59 to 378bf4a Compare June 7, 2026 11:36
@Ostico Ostico force-pushed the fix-context-url-api branch from 378bf4a to 2319d49 Compare June 7, 2026 11:40
@github-actions

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment thread lib/Controller/API/App/ContextUrlController.php
Comment thread inc/validation/schema/segment_context_url.json
Comment thread lib/Routes/api_v3_routes.php Outdated
@github-actions

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings June 7, 2026 11:48
@Ostico Ostico force-pushed the fix-context-url-api branch from 2319d49 to c3d4b91 Compare June 7, 2026 11:48
Copy link
Copy Markdown
Contributor Author

@Ostico Ostico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 3 new Copilot findings addressed in c3d4b91:

  1. XSS via dangerous URI schemes — JSON schema now uses "pattern": "^https?://" + "minLength": 1 instead of "format": "uri". Rejects javascript:, data:, and all non-http(s) schemes. Tests added for both.
  2. Route type safety — Changed [:id_project] to [i:id_project] (Klein integer matcher). Non-integer paths rejected at routing level before reaching controller.
  3. Empty bodygetValidatedBody() already throws InvalidArgumentException for null body before JSON parsing.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Comment thread tests/unit/Core/Controllers/ContextUrlControllerTest.php Outdated
Comment thread tests/unit/Core/Controllers/ContextUrlControllerTest.php Outdated
Comment thread tests/unit/Core/Controllers/ContextUrlControllerTest.php Outdated
Comment thread inc/validation/schema/segment_context_url.json
@github-actions

This comment was marked as outdated.

…ation

IDOR vulnerability: any authenticated user could modify context URLs for
any project/file/segment. Added ProjectPasswordValidator + ProjectAccessValidator
chain, RateLimiterService (IP + email), entity existence and domain checks,
unified JSON schema validation across all endpoints, and parameterized SQL
in SegmentMetadataDao to prevent injection.
Copy link
Copy Markdown
Contributor Author

@Ostico Ostico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 4 findings from this review addressed in 8295ef6:

  1. Rate-limit test false positive (3 comments) — fixed. The same $responseMock is now returned by the RateLimiterService stub, so expects(never())->method("json") asserts on the actual response object the controller uses after replacement.
  2. Schema: add format: "uri" — added alongside pattern: "^https?://". Both constraints apply: format validates URI structure, pattern restricts to http(s) schemes.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 7, 2026

🧪 Test-Guard Report

❌ FAIL — Some changed source files lack adequate test coverage.

Coverage Analysis: ❌ FAIL

Changed lines: 87.0% covered (threshold: 80%)

📋 4 files: 1 ❌ fail, 3 ✅ pass
File Verdict Reason
lib/Controller/API/App/ContextUrlController.php ✅ pass 87% diff coverage ≥ 80% threshold
lib/Controller/Abstracts/KleinController.php ✅ pass 100% diff coverage ≥ 80% threshold
lib/Model/Segments/SegmentMetadataDao.php ✅ pass 100% diff coverage ≥ 80% threshold
lib/Routes/api_v3_routes.php ❌ fail 0% diff coverage < 80% threshold

Test File Matching: ❌ FAIL

File matching: 2 pass, 1 warning, 1 fail

📋 4 files: 1 ❌ fail, 1 ⚠️ warning, 2 ✅ pass
File Verdict Reason
lib/Controller/API/App/ContextUrlController.php ✅ pass Test file modified in PR: tests/unit/Core/Controllers/ContextUrlControllerTest.php
lib/Controller/Abstracts/KleinController.php ⚠️ warning Test file exists (tests/unit/Core/Controllers/Abstracts/KleinControllerTest.php) but was not modified in this PR
lib/Model/Segments/SegmentMetadataDao.php ✅ pass Test file modified in PR: tests/unit/Core/Model/Segments/SegmentMetadataDaoTest.php
lib/Routes/api_v3_routes.php ❌ fail No matching test file found

Per-File Evaluation: ❌ FAIL

Evaluated 4 files: 1 via AI (1 batch), 3 via shortcuts.

📋 4 files: 1 ❌ fail, 3 ✅ pass
File Verdict Reason
lib/Controller/API/App/ContextUrlController.php ✅ pass shortcut → coverage 87% ≥ 80%
lib/Controller/Abstracts/KleinController.php ✅ pass shortcut → coverage 100% ≥ 80%
lib/Model/Segments/SegmentMetadataDao.php ✅ pass shortcut → coverage 100% ≥ 80%
lib/Routes/api_v3_routes.php ❌ fail No tests cover the new route parameter changes in the routing configuration.

Result: ❌ FAIL


Why this FAIL?

  • Coverage Analysis: lib/Routes/api_v3_routes.php has 0% diff coverage, meaning none of the changed lines in this routing configuration file are exercised by tests → add tests that exercise the new or changed route parameters.
  • Test File Matching: No matching test file found for lib/Routes/api_v3_routes.php → create or modify a test file to cover this routing configuration.
  • Per-File Evaluation: AI evaluation confirms no tests cover the new route parameter changes in lib/Routes/api_v3_routes.php → add targeted tests for the routing changes.
  • Test File Matching: Warning for lib/Controller/Abstracts/KleinController.php as its test file exists but was not modified → no action needed unless the changes require test updates.

To resolve: add or update tests to cover the new or changed route parameters in lib/Routes/api_v3_routes.php.

@Ostico Ostico merged commit f1d2b4e into develop Jun 7, 2026
15 of 17 checks passed
@Ostico Ostico deleted the fix-context-url-api branch June 7, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants