fix(security): sanitize agent-card topology, anti-spoof login rate-limit peer IP, and add 429 Retry-After (#S1 #S2 #S4) (#11418)

Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (S1/S2/S4, tests/unit/security-s1-s2-s4.test.ts, 9/9).

Boa integração com o padrão já existente de peer IP stamped por HMAC (resolveStampedPeer/OMNIROUTE_PEER_STAMP_TOKEN) — reusa em vez de reimplementar, e o header confiável só é honrado quando o stamp token está configurado. S2 remove corretamente a disclosure de topologia hardcoded do agent-card. Obrigado pela contribuição!
This commit is contained in:
Bob.Hou
2026-08-24 16:24:08 -04:00
committed by GitHub
parent 9464792cfc
commit 59dccdd9e1
8 changed files with 408 additions and 16 deletions

View File

@@ -62,6 +62,16 @@ export const VIA_PROXY_HEADER = "x-omniroute-via-proxy";
*/
export const AUTHZ_HEADER_PEER_LOCALITY = "x-omniroute-peer-locality";
/**
* The resolved real peer IP, stamped by the pipeline AFTER verifying the
* token-stamped PEER_IP_HEADER. This is the trusted, non-spoofable IP that
* route handlers (e.g. login rate-limit key) should use instead of re-deriving
* from X-Forwarded-For / X-Real-IP. Set only when the stamp token is configured
* and the HMAC signature validates; absent when the stamp is not in use.
* Stripped from incoming requests like all other trusted headers.
*/
export const AUTHZ_HEADER_TRUSTED_PEER_IP = "x-omniroute-trusted-peer-ip";
/**
* Headers the pipeline must NEVER trust on incoming requests. They are
* stripped before route classification to prevent header-spoofing attacks.
@@ -73,4 +83,5 @@ export const AUTHZ_TRUSTED_HEADERS: ReadonlyArray<string> = [
AUTHZ_HEADER_AUTH_LABEL,
AUTHZ_HEADER_AUTH_SCOPES,
AUTHZ_HEADER_PEER_LOCALITY,
AUTHZ_HEADER_TRUSTED_PEER_IP,
];

View File

@@ -25,6 +25,7 @@ import {
AUTHZ_HEADER_PEER_LOCALITY,
AUTHZ_HEADER_REQUEST_ID,
AUTHZ_HEADER_ROUTE_CLASS,
AUTHZ_HEADER_TRUSTED_PEER_IP,
AUTHZ_TRUSTED_HEADERS,
CLI_TOKEN_HEADER,
PEER_IP_HEADER,
@@ -332,6 +333,16 @@ export async function runAuthzPipeline(
process.env.OMNIROUTE_PEER_STAMP_TOKEN
);
requestHeaders.set(AUTHZ_HEADER_PEER_LOCALITY, peerLocality);
// Stamp the resolved, non-spoofable peer IP for route handlers that need
// the real client IP (e.g. login rate-limit key). Only set when the stamp
// token is configured and the HMAC signature validates; absent otherwise.
const trustedPeerIp = resolveStampedPeer(
request.headers.get(PEER_IP_HEADER),
process.env.OMNIROUTE_PEER_STAMP_TOKEN
);
if (trustedPeerIp) {
requestHeaders.set(AUTHZ_HEADER_TRUSTED_PEER_IP, trustedPeerIp);
}
// Local CLI-token auth is decided centrally above. Preserve that trusted
// decision for route-level requireManagementAuth without forwarding the
// machine token itself: custom client auth headers are stripped before the