mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
Stop Noise relay recovery on rejected executor credentials (#59750)
## Why Registry `401` responses during harness key validation previously produced generic relay resets, causing recovery to retry rejected executor credentials instead of surfacing the authentication failure. ## What changed - Send an authenticated Noise handshake rejection for registry `401` responses without opening an application transport. - Propagate the rejection as `EnvironmentRegistryAuth` and preserve it in the terminal connection state so recovery stops with a specific authentication error. - Preserve registry HTTP status codes so `403` responses for stale harness grants and transient service failures can continue through recovery. ## Testing Add tests that reject tampered authentication rejections and exercise session recovery: `401` stops after one rejected recovery attempt, while `403`, `502`, and `503` retry with fresh harness grants and reconnect successfully. GitOrigin-RevId: 9a55412e583146c094948618c7c9aeb4fb4b953e
This commit is contained in:
@@ -495,7 +495,7 @@ where
|
||||
///
|
||||
/// Implementations must consult an authority independent of rendezvous. The
|
||||
/// exec-server invokes this after parsing the first IK message and before
|
||||
/// completing the responder handshake.
|
||||
/// opening an application transport.
|
||||
pub(crate) trait HarnessKeyValidator: Send + Sync {
|
||||
fn validate_harness_key(
|
||||
&self,
|
||||
@@ -645,7 +645,20 @@ where
|
||||
reason,
|
||||
registry_status,
|
||||
);
|
||||
send_reset(&physical_outgoing_tx, validation_result.stream_id);
|
||||
// Authenticate the rejection so the harness can stop retrying.
|
||||
if registry_status == Some(401)
|
||||
&& let Ok(response) = pending.handshake.reject_registry_authentication()
|
||||
{
|
||||
let frame = RelayMessageFrame::handshake(
|
||||
validation_result.stream_id,
|
||||
response,
|
||||
);
|
||||
let _ = physical_outgoing_tx.try_send(
|
||||
encode_relay_message_frame(&frame),
|
||||
);
|
||||
} else {
|
||||
send_reset(&physical_outgoing_tx, validation_result.stream_id);
|
||||
}
|
||||
record_failed_handshake(
|
||||
&mut failed_handshakes,
|
||||
&mut handshake_cooldown_until,
|
||||
@@ -864,8 +877,8 @@ where
|
||||
);
|
||||
let validator = validator.clone();
|
||||
|
||||
// Failed validation leaves no transport state and sends only a
|
||||
// generic reset.
|
||||
// Failed validation leaves no transport state. Preserve the
|
||||
// trusted registry status for request-scoped rejection handling.
|
||||
validation_tasks.spawn(async move {
|
||||
let result = match timeout(
|
||||
HARNESS_KEY_VALIDATION_TIMEOUT,
|
||||
|
||||
Reference in New Issue
Block a user