Skip to content

Fix significant audit findings: async I/O, public URL, Bearer case, Dockerfile#98

Merged
cmeans merged 6 commits into
mainfrom
fix/significant-audit-findings
Mar 30, 2026
Merged

Fix significant audit findings: async I/O, public URL, Bearer case, Dockerfile#98
cmeans merged 6 commits into
mainfrom
fix/significant-audit-findings

Conversation

@cmeans
Copy link
Copy Markdown
Owner

@cmeans cmeans commented Mar 30, 2026

Summary

Addresses 6 significant findings from the multi-tenant/OAuth code audit:

  • S1: Sync DB I/O off event loop_try_oauth() and _resolve_user() now use asyncio.to_thread() so sync psycopg calls don't block the async event loop during OAuth authentication
  • S2: AWARENESS_PUBLIC_URL — new env var for well-known metadata resource URL. Fixes 0.0.0.0:8420 appearing in /.well-known/oauth-protected-resource for Cloudflare tunnel deployments
  • S3: Custom prompts multi-tenant — documented as DEFAULT_OWNER-only (known limitation until FastMCP supports request-scoped prompt registration)
  • S4: Case-insensitive BearerAuthMiddleware now accepts bearer, Bearer, BEARER per RFC 7235
  • S5: Dockerfile license — label corrected from Apache-2.0 to AGPL-3.0-or-later
  • S6: docker-compose.yaml — all auth/OAuth env vars now passed through

QA

Prerequisites

  • pip install -e ".[dev]"

Manual tests

    • Case-insensitive Bearer
    curl -H "Authorization: bearer <token>" https://<host>/mcp
    

    Expected: accepted (not 401)

    • Public URL in metadata
      Set AWARENESS_PUBLIC_URL=https://mcpawareness.com, verify:
    curl https://<host>/.well-known/oauth-protected-resource
    

    Expected: resource field shows https://mcpawareness.com/mcp, not 0.0.0.0:8420

    • docker-compose auth vars — verify docker compose config shows auth env vars
    • Dockerfile licensedocker inspect shows AGPL-3.0-or-later

🤖 Generated with Claude Code

…ockerfile license

S1: _try_oauth and _resolve_user now use asyncio.to_thread() — prevents
    blocking the async event loop with sync psycopg DB calls
S2: AWARENESS_PUBLIC_URL env var for well-known metadata — fixes
    0.0.0.0:8420 in resource URL for Cloudflare tunnel deployments
S3: _sync_custom_prompts documented as DEFAULT_OWNER-only (known limitation)
S4: Bearer scheme check is now case-insensitive per RFC 7235
S5: Dockerfile license label corrected from Apache-2.0 to AGPL-3.0-or-later
S6: Auth/OAuth env vars added to docker-compose.yaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cmeans cmeans added the Dev Active Developer is actively working on this PR; QA should not start label Mar 30, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 30, 2026

Codecov Report

❌ Patch coverage is 93.93939% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/mcp_awareness/server.py 33.33% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

cmeans and others added 2 commits March 30, 2026 01:50
Updated test calls to use keyword args after signature change.
New test verifies public_url is used in resource metadata.
middleware.py at 100% coverage. 491 tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cmeans
Copy link
Copy Markdown
Owner Author

cmeans commented Mar 30, 2026

Codecov note: 2 lines remain uncovered in server.py — same WellKnownMiddleware instantiation inside _run() that was accepted on PR #95. Only exercised when the server starts with uvicorn + AWARENESS_OAUTH_ISSUER set. Cannot be unit tested without booting the full server. Accepted by project owner (same lines as PR #95).

@cmeans cmeans removed the Dev Active Developer is actively working on this PR; QA should not start label Mar 30, 2026
@github-actions github-actions Bot added the Ready for QA Dev work complete — QA can begin review label Mar 30, 2026
S7: Per-owner semaphore (max 3 concurrent requests) prevents a single
aggressive MCP client from saturating the pool and DOSing other tenants.
Returns 429 when all slots are taken. Connection pool default bumped
from 5 to 10 for multi-tenant deployments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA and removed Ready for QA Dev work complete — QA can begin review labels Mar 30, 2026
cmeans and others added 2 commits March 30, 2026 02:11
When AWARENESS_PUBLIC_URL is not set, the resource URL in
/.well-known/oauth-protected-resource is now derived from the
request's Host header instead of the bind address (0.0.0.0:8420).
This handles reverse proxy / tunnel deployments without explicit config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two new tests:
- WellKnownMiddleware derives resource URL from Host header when no public_url
- 429 returned when per-owner concurrency slots exhausted
middleware.py at 100% coverage. 493 tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cmeans cmeans added Ready for QA Dev work complete — QA can begin review QA Active QA is actively reviewing; Dev should not push changes and removed Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA labels Mar 30, 2026
Copy link
Copy Markdown
Owner Author

@cmeans cmeans left a comment

Choose a reason for hiding this comment

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

QA Review — PR #98: Fix significant audit findings

QA Failed — codecov/patch is FAILURE.

All other checks pass (lint, typecheck, test 3.10/3.11/3.12). Coverage gap needs to be addressed before QA can proceed.

Will do full review once codecov is green.

@cmeans
Copy link
Copy Markdown
Owner Author

cmeans commented Mar 30, 2026

Applying QA Failed — codecov/patch check is FAILURE. Dev needs to fix coverage gap before re-review.

@cmeans cmeans added QA Failed QA found issues — needs dev attention and removed QA Active QA is actively reviewing; Dev should not push changes labels Mar 30, 2026
@github-actions github-actions Bot removed the Ready for QA Dev work complete — QA can begin review label Mar 30, 2026
@cmeans cmeans added QA Active QA is actively reviewing; Dev should not push changes and removed QA Failed QA found issues — needs dev attention labels Mar 30, 2026
Copy link
Copy Markdown
Owner Author

@cmeans cmeans left a comment

Choose a reason for hiding this comment

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

QA Review — PR #98: Fix significant audit findings

Code Review

All 6 significant findings addressed, plus bonus improvements (concurrency limit, pool size):

S1: Sync DB I/O off event loop

  • _try_oauth(): validator.validate(token)await asyncio.to_thread(validator.validate, token)
  • _resolve_user(): called via await asyncio.to_thread(self._resolve_user, ...)
  • Both sync psycopg paths now run in thread pool, won't block the async event loop

S2: AWARENESS_PUBLIC_URL

  • New env var, read in server.py, passed to WellKnownMiddleware
  • _resource_url() priority: static public_url → Host header fallback → localhost
  • Verified: AWARENESS_PUBLIC_URL=https://mcpawareness.comresource: https://mcpawareness.com/mcp

S3: Custom prompts multi-tenant

  • Documented as DEFAULT_OWNER-only limitation with clear NOTE in _sync_custom_prompts() docstring ✅

S4: Case-insensitive Bearer

  • auth_header.startswith("Bearer ")auth_header.lower().startswith("bearer ")
  • Token extraction still uses auth_header[7:] (correct — scheme length is always 7)
  • Verified: bearer, Bearer, BEARER all return 200

S5: Dockerfile license

  • Apache-2.0AGPL-3.0-or-later
  • Verified via docker inspect

S6: docker-compose.yaml auth vars

  • 9 auth/OAuth env vars added with sensible defaults ✅

Bonus: Per-owner concurrency limit

  • max_concurrent_per_owner=3 with per-owner semaphores
  • Returns 429 when all slots taken (sem._value check for immediate rejection)
  • Prevents single-client DOS of connection pool

Bonus: Connection pool default

  • max_pool 5 → 10 for multi-tenant

CI Exception

codecov/patch FAILURE — owner-acknowledged exception. The uncovered lines were reviewed and accepted by the repo owner before QA.

Test Results

Check Result
pytest (493 tests) ✅ 493/493 pass
ruff, mypy ✅ Clean
CI (lint, typecheck, tests) ✅ All green
codecov/patch ⚠️ FAILURE (owner-acknowledged, reviewed lines)
Manual #1: Case-insensitive Bearer ✅ bearer/Bearer/BEARER all 200
Manual #2: Public URL in metadata https://mcpawareness.com/mcp
Manual #3: docker-compose auth vars ✅ 9 vars present
Manual #4: Dockerfile license AGPL-3.0-or-later

Verdict

Zero findings. codecov exception acknowledged by owner. All manual tests pass. Ready for QA Signoff.

@cmeans
Copy link
Copy Markdown
Owner Author

cmeans commented Mar 30, 2026

Adding Ready for QA Signoff — all 6 significant audit findings + bonus concurrency limit verified. codecov/patch failure reviewed and accepted by owner. CI otherwise green, 493/493 pytest, 4/4 manual tests pass.

@cmeans cmeans added Ready for QA Signoff QA passed — ready for maintainer final review and merge and removed QA Active QA is actively reviewing; Dev should not push changes labels Mar 30, 2026
Copy link
Copy Markdown
Owner Author

@cmeans cmeans left a comment

Choose a reason for hiding this comment

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

LGTM

@cmeans cmeans added QA Approved Manual QA testing completed and passed and removed Ready for QA Signoff QA passed — ready for maintainer final review and merge labels Mar 30, 2026
@cmeans cmeans merged commit 48b9e23 into main Mar 30, 2026
66 of 67 checks passed
@cmeans cmeans deleted the fix/significant-audit-findings branch March 30, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA Approved Manual QA testing completed and passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant