summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/api/revocation.py')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/revocation.py18
1 files changed, 17 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
index 0f1ddba..2e3323c 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
@@ -33,7 +33,7 @@ import time
import uuid
from typing import Any
-from fastapi import APIRouter, Depends, HTTPException, WebSocket, WebSocketDisconnect
+from fastapi import APIRouter, Depends, HTTPException, Request, WebSocket, WebSocketDisconnect
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -274,12 +274,28 @@ class IncomingRequest(BaseModel):
async def notify_incoming(
node_id: str,
body: IncomingRequest,
+ request: Request,
current_user: User = Depends(get_current_user),
):
"""
Signal a node that a client wants to connect (NAT punch coordination).
Hub forwards the request via WebSocket; node punches NAT and replies punch_ready.
+
+ Finding H6: peer_ip was taken verbatim, so any authenticated user could make an
+ arbitrary node emit UDP packets to an address of their choosing — a small
+ reflection primitive using someone else's machine. The probe target must now be
+ the caller's own source address.
"""
+ from meshbay_hub.api.netutil import client_ip
+
+ caller_ip = client_ip(request)
+ if body.peer_ip != caller_ip:
+ raise HTTPException(
+ status_code=403,
+ detail="peer_ip must match the requesting address")
+ if not (1 <= body.peer_port <= 65535):
+ raise HTTPException(status_code=422, detail="Invalid peer_port")
+
ws = _connected_nodes.get(node_id)
if not ws:
raise HTTPException(status_code=404, detail="Node not connected")