fix open redirect, error leaking, unused imports, state validation

This commit is contained in:
CREDO23 2026-04-22 08:42:38 +02:00
parent e676ebfabe
commit 940889c291
6 changed files with 13 additions and 24 deletions

View file

@ -96,7 +96,7 @@ router.include_router(logs_router)
router.include_router(circleback_webhook_router) # Circleback meeting webhooks
router.include_router(surfsense_docs_router) # Surfsense documentation for citations
router.include_router(notifications_router) # Notifications with Zero sync
router.include_router(mcp_oauth_router) # MCP OAuth 2.1 for Linear, Jira, ClickUp
router.include_router(mcp_oauth_router) # MCP OAuth 2.1 for Linear, Jira, ClickUp, Slack, Airtable
router.include_router(composio_router) # Composio OAuth and toolkit management
router.include_router(public_chat_router) # Public chat sharing and cloning
router.include_router(incentive_tasks_router) # Incentive tasks for earning free pages

View file

@ -182,7 +182,7 @@ async def connect_mcp_service(
except Exception as e:
logger.error("Failed to initiate %s MCP OAuth: %s", service, e, exc_info=True)
raise HTTPException(
status_code=500, detail=f"Failed to initiate {service} MCP OAuth: {e!s}",
status_code=500, detail=f"Failed to initiate {service} MCP OAuth.",
) from e
@ -221,6 +221,9 @@ async def mcp_oauth_callback(
space_id = data["space_id"]
svc_key = data.get("service", service)
if svc_key != service:
raise HTTPException(status_code=400, detail="State/path service mismatch")
from app.services.mcp_oauth.registry import get_service
svc = get_service(svc_key)
@ -315,7 +318,7 @@ async def mcp_oauth_callback(
svc.name, db_connector.id, user_id,
)
reauth_return_url = data.get("return_url")
if reauth_return_url and reauth_return_url.startswith("/"):
if reauth_return_url and reauth_return_url.startswith("/") and not reauth_return_url.startswith("//"):
return RedirectResponse(
url=f"{config.NEXT_FRONTEND_URL}{reauth_return_url}"
)
@ -347,7 +350,7 @@ async def mcp_oauth_callback(
except IntegrityError as e:
await session.rollback()
raise HTTPException(
status_code=409, detail=f"Database integrity error: {e!s}",
status_code=409, detail="A connector for this service already exists.",
) from e
_invalidate_cache(space_id)
@ -368,7 +371,7 @@ async def mcp_oauth_callback(
)
raise HTTPException(
status_code=500,
detail=f"Failed to complete {service} MCP OAuth: {e!s}",
detail=f"Failed to complete {service} MCP OAuth.",
) from e
@ -495,7 +498,7 @@ async def reauth_mcp_service(
)
raise HTTPException(
status_code=500,
detail=f"Failed to initiate {service} MCP re-auth: {e!s}",
detail=f"Failed to initiate {service} MCP re-auth.",
) from e

View file

@ -430,7 +430,7 @@ class OAuthConnectorRoute:
state_mgr = oauth._get_state_manager()
extra: dict[str, Any] = {"connector_id": connector_id}
if return_url and return_url.startswith("/"):
if return_url and return_url.startswith("/") and not return_url.startswith("//"):
extra["return_url"] = return_url
auth_params: dict[str, str] = {
@ -498,7 +498,7 @@ class OAuthConnectorRoute:
data = state_mgr.validate_state(state)
except Exception as e:
raise HTTPException(
status_code=400, detail=f"Invalid state parameter: {e!s}"
status_code=400, detail="Invalid or expired state parameter."
) from e
user_id = UUID(data["user_id"])
@ -552,7 +552,7 @@ class OAuthConnectorRoute:
db_connector.id,
user_id,
)
if reauth_return_url and reauth_return_url.startswith("/"):
if reauth_return_url and reauth_return_url.startswith("/") and not reauth_return_url.startswith("//"):
return RedirectResponse(
url=f"{config.NEXT_FRONTEND_URL}{reauth_return_url}"
)
@ -603,7 +603,7 @@ class OAuthConnectorRoute:
except IntegrityError as e:
await session.rollback()
raise HTTPException(
status_code=409, detail=f"Database integrity error: {e!s}"
status_code=409, detail="A connector for this service already exists."
) from e
logger.info(