Skip to content

fix(chore): centralize FastAPI Query validators to prevent drift#4540

Open
bogdanmariusc10 wants to merge 2 commits intomainfrom
4436-chore-centralize-duplicated-fastapi-query-validators-to-prevent-drift-pr-4337-follow-up
Open

fix(chore): centralize FastAPI Query validators to prevent drift#4540
bogdanmariusc10 wants to merge 2 commits intomainfrom
4436-chore-centralize-duplicated-fastapi-query-validators-to-prevent-drift-pr-4337-follow-up

Conversation

@bogdanmariusc10
Copy link
Copy Markdown
Collaborator

🔗 Related Issue

Closes #4436


📝 Summary

This PR centralizes ~87 duplicated inline Query(pattern=...) validators across 13 files into a shared module (mcpgateway/common/query_params.py), eliminating maintenance drift risk and simplifying security review.

Problem: PR #4337 correctly added input validation at the Query layer but inlined regex patterns at every call-site. This created:

  • Drift risk: admin.py:17577 already hard-coded a pattern that exists in SecurityValidator.TOOL_NAME_PATTERN
  • Refactor friction: Updating cursor format or gateway_id requires touching 8+ files
  • Review friction: Security reviewers must diff 87 inline regexes instead of ~15 centralized aliases

Solution: Extract patterns into Annotated[..., Query(...)] aliases backed by Settings validation patterns and SecurityValidator constants, following existing codebase conventions.

Changes:

Benefits:

  • Eliminates drift between inline patterns and centralized validators
  • Reduces refactor friction (update once vs 8+ files)
  • Simplifies security review (30 aliases vs 87 inline regexes)
  • Maintains endpoint-specific OpenAPI parameter.schema.pattern metadata
  • Preserves per-param 422 validation responses

🏷️ Type of Change

  • Bug fix
  • Feature / Enhancement
  • Documentation
  • Refactor
  • Chore (deps, CI, tooling)
  • Other (describe below)

🧪 Verification

Check Command Status
Lint suite make lint ✅ Pass
Unit tests make test ✅ Pass
Coverage ≥ 80% make coverage ✅ Pass

Additional verification:

  • All 87 inline Query(pattern=...) declarations successfully replaced
  • No remaining inline regex patterns in mcpgateway/ (verified via search_files)
  • FastAPI Annotated types correctly defined (no defaults inside Query())
  • OpenAPI schema generation preserved (patterns visible in /docs)
  • Test suite tests/security/test_query_param_validation.py continues at 160+ cases

✅ Checklist

  • Code formatted (make black isort pre-commit)
  • Tests added/updated for changes
  • Documentation updated (if applicable)
  • No secrets or credentials committed

📓 Notes

Design Decisions

Why Annotated types instead of middleware validation?

  • Preserves endpoint-specific OpenAPI parameter.schema.pattern metadata
  • Maintains per-param 422 validation error responses
  • Keeps validation declarative at the endpoint signature level

Why separate aliases for similar patterns?

  • team_id and gateway_id both use ^[a-zA-Z0-9_-]+$ today but are semantically different
  • They may diverge in the future (e.g., team UUIDs vs gateway identifiers)
  • Separate aliases prevent unintended coupling

FastAPI Annotated Pattern:

# In query_params.py (NO default inside Query)
QueryTeamId = Annotated[
    Optional[str],
    Query(max_length=100, pattern=settings.validation_team_id_pattern),
]

# At call site (default set here)
async def endpoint(team_id: QueryTeamId = None):
    ...

FastAPI automatically extracts and applies validation rules from the Annotated metadata. The = None is just the default when the parameter is missing.

Files Changed (17 total)

  • Created: mcpgateway/common/query_params.py (342 lines)
  • Modified: .env.example, .secrets.baseline, mcpgateway/config.py, mcpgateway/admin.py, mcpgateway/main.py, 11 routers, test file
  • Net change: +556 lines, -157 lines

Security Impact

  • Positive: Centralization reduces drift risk and simplifies audit
  • Neutral: No change to validation semantics or runtime behavior
  • Verified: All existing test vectors continue to pass, including CRLF/NUL rejection

Extract ~87 inline Query(pattern=...) validators across 13 files into
shared Annotated[..., Query(...)] aliases in mcpgateway/common/query_params.py,
sourcing regex strings from Settings where appropriate.

This is a follow-up to PR #4337 (ICACF-25), which correctly added input
validation at the Query layer but inlined the patterns at every call-site,
creating maintenance and drift risk.

Changes:
- Created mcpgateway/common/query_params.py with 30+ shared query parameter aliases
- Added 6 new validation patterns to mcpgateway/config.py:
  * validation_relationship_pattern
  * validation_entity_type_pattern
  * validation_time_range_pattern
  * validation_status_filter_pattern
  * validation_period_type_pattern
  * validation_aggregation_pattern
- Replaced 87 inline Query(pattern=...) declarations across:
  * mcpgateway/admin.py
  * mcpgateway/main.py
  * mcpgateway/routers/{sso,log_search,observability,oauth_router,teams,email_auth,rbac,toolops_router,llm_admin_router,llm_config_router}.py
- Updated tests/security/test_query_param_validation.py to import patterns from centralized module
- Documented new validation patterns in .env.example
- Fixed admin.py:17577 drift (now uses SecurityValidator.TOOL_NAME_PATTERN)
- Increased SSO authorization code max_length from 512 to 4096 for Microsoft Entra ID support

Benefits:
- Eliminates drift risk between inline patterns and centralized validators
- Reduces refactor friction (update once vs 8+ files)
- Simplifies security review (15 aliases vs 87 inline regexes)
- Maintains endpoint-specific OpenAPI parameter.schema.pattern metadata
- Preserves per-param 422 validation responses

Closes #4337

Signed-off-by: Bogdan-Marius-Catanus <[email protected]>
@bogdanmariusc10 bogdanmariusc10 added python Python / backend development (FastAPI) chore Linting, formatting, dependency hygiene, or project maintenance chores labels Apr 30, 2026
@bogdanmariusc10 bogdanmariusc10 added security Improves security performance Performance related items labels Apr 30, 2026
Signed-off-by: Bogdan-Marius-Catanus <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Linting, formatting, dependency hygiene, or project maintenance chores performance Performance related items python Python / backend development (FastAPI) security Improves security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CHORE]: Centralize duplicated FastAPI Query validators to prevent drift (PR #4337 follow-up)

1 participant