feat(proxy): add redeem_phantoms for by-value nonce redemption - #1469
Open
kipz wants to merge 1 commit into
Open
feat(proxy): add redeem_phantoms for by-value nonce redemption#1469kipz wants to merge 1 commit into
kipz wants to merge 1 commit into
Conversation
Contributor
PR Review SummarySize
Affected crates
Blast radius — ModerateThis PR touches: source code,configuration / policy files Updated automatically on each push to this PR. |
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
July 21, 2026 11:11
8800d6c to
e034baa
Compare
kipz
marked this pull request as ready for review
July 21, 2026 13:12
kipz
added a commit
to kipz/nono
that referenced
this pull request
Jul 21, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
added a commit
to kipz/nono
that referenced
this pull request
Jul 21, 2026
Integration fixup: nolabs-ai#1469/nolabs-ai#1443 added CredentialRouteDef.upgrades; Signed-off-by: James Carnegie <me@kipz.org> nolabs-ai#1476's vault test literal predates it. Combined-branch only.
kipz
added a commit
to kipz/nono
that referenced
this pull request
Jul 23, 2026
…e nonce redemption # Conflicts: # crates/nono-cli/src/proxy_runtime.rs # crates/nono-cli/src/tool-sandbox/token_broker.rs # crates/nono-proxy/src/server.rs # crates/nono-proxy/src/tls_intercept/handle.rs # crates/nono-proxy/src/token.rs
kipz
added a commit
to kipz/nono
that referenced
this pull request
Jul 24, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
July 24, 2026 16:19
e9b75ba to
79658a9
Compare
Contributor
|
@kipz , this one needs a bit of a rebase , a few network PRs landed before |
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 3, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org> (cherry picked from commit 79658a9)
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 3, 2026
… PRs Cross-PR semantic conflicts: rate_limit/redeem_phantoms/format/credential_name test initializers, filter_child_env caller arg, and nolabs-ai#1443's CR/LF/NUL guard re-applied on top of nolabs-ai#1469's rewritten resolve_nonce_in_header_value. Signed-off-by: James Carnegie <me@kipz.org>
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 3, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 3, 2026 14:38
79658a9 to
9acede4
Compare
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 3, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 3, 2026 21:44
9acede4 to
998f3e4
Compare
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 3, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 6, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 6, 2026 10:31
50e0ac9 to
5fcef26
Compare
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 9, 2026
Address nogent review feedback on nolabs-ai#1469: - websocket.rs: read_response used unbounded read_line for both the status line and header lines, so an upstream that never sends a newline could grow the buffer without limit until OOM or the 30s timeout. Add a bounded line reader (8KB/line) that fails fast. - h2_forward.rs: handle_h2_stream hardcoded websocket_path: None, skipping the upgrade_rules gate for RFC 8441 extended CONNECT streams. Detect :protocol: websocket and route it through the same check as the HTTP/1.1 Upgrade path, so enabling h2 WebSocket tunneling later can't silently bypass the allowlist. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 9, 2026 11:14
5fcef26 to
d3b11c5
Compare
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 9, 2026
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 9, 2026
…n_header_value Threads the matched route's redeem_phantoms through the absolute-form forward-proxy path so nolabs-ai#1589 and nolabs-ai#1469 compose. Signed-off-by: James Carnegie <me@kipz.org>
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 9, 2026
Resolutions: - websocket.rs: kept nolabs-ai#1469's bounded line reads, added RFC 6455 Sec-WebSocket-Accept validation from nolabs-ai#1443. - handle.rs: adopted nolabs-ai#1443's run_websocket_tunnel split; kept the 4-arg resolve_nonce_in_header_value (redeem_phantoms) from nolabs-ai#1469 and nolabs-ai#1489's templated-phantom rewrite path. - token.rs: CRLF/NUL fail-closed guard moved into rewrite_first_phantom so the grant-set/templated path is covered too. - reverse.rs: header_pairs replaced by http1::parse_header_fields. - Deduplicated RouteConfig 'upgrades' fields introduced twice by the merge. Signed-off-by: James Carnegie <me@kipz.org>
kipz
added a commit
to kipz/nono
that referenced
this pull request
Aug 9, 2026
…e nonce redemption # Conflicts: # crates/nono-cli/src/proxy_runtime.rs # crates/nono-cli/src/tool-sandbox/token_broker.rs # crates/nono-proxy/src/config.rs # crates/nono-proxy/src/reverse.rs # crates/nono-proxy/src/route.rs # crates/nono-proxy/src/server.rs # crates/nono-proxy/src/tls_intercept/h2_forward.rs # crates/nono-proxy/src/tls_intercept/handle.rs # crates/nono-proxy/src/tls_intercept/websocket.rs # crates/nono-proxy/src/token.rs
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 10, 2026 10:59
d3b11c5 to
66c72e6
Compare
Routes may declare `redeem_phantoms`: broker credential names the route will redeem from a caller-presented phantom, authorized by credential name rather than by the consumer's grant set. The broker tracks the name behind every issued phantom so a reissued historical value stays redeemable, and a phantom for an unlisted credential fails closed. Signed-off-by: James Carnegie <me@kipz.org>
kipz
force-pushed
the
kipz/redeem-phantoms-upstream
branch
from
August 10, 2026 14:47
66c72e6 to
7d7bc44
Compare
This was referenced Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked Issue
Closes #1468
Summary
Adds
redeem_phantomsto acustom_credentialsroute — a list of brokercredential names the route resolves from a caller-presented phantom in a request
header (by-value / proof-of-possession). A non-empty list forces interception for
the route's host; resolution is gated by credential name (not value); it composes
with a managed
credential_key/author stands alone. JWT-shaped phantoms arewhole-token replaced (anchored to the parsed nonce) so a real JWT stays 3 segments.
The broker gains a name-gated
resolve_nonce_for_credentials(per-nonce name map)and the
NonceResolvertrait gains aresolve_for_credentialsmethod (defaultNone).Stacked — do not merge until #1443 lands in
main:build_websocket_upstream_requestcall site.Test Plan
make ciclean. New unit tests: shape-aware JWT resolution (3-segment result),opaque substring replacement, route-authoritative name gate + fail-closed,
name-vs-value across per-audience overwrites, raw-value reissue relabel, a
multibyte-boundary panic regression, and profile validation (composes with
credential_key; rejected withaws_auth/spiffe; empty-name rejected).Checklist
CHANGELOG.mdif neededAgent Disclosure
Generated by an AI agent. Reuses the existing
NonceResolverand CONNECT interceptdispatch; no new resolver trait, URI scheme, or consumer class. Files changed:
crates/nono-proxy/src/{config,route,server,token,tls_intercept/{handle,h2_forward}}.rs,crates/nono-cli/src/{network_policy,profile/mod,proxy_runtime,tool-sandbox/token_broker}.rs,crates/nono-cli/data/nono-profile.schema.json.Agent Compliance Check