Skip to content

feat(sandbox): 接頭辞付きの credential 別名を placeholder と同じ秘密に解決する - #4

Merged
striderkein merged 4 commits into
fix/basic-auth-credential-resolvefrom
feat/provider-alias-resolve
Oct 9, 2026
Merged

striderkein merged 4 commits into
fix/basic-auth-credential-resolvefrom
feat/provider-alias-resolve

Conversation

@striderkein

@striderkein striderkein commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

概要

upstream NVIDIA#1286 の「接頭辞付きの別名(provider-shaped alias)の解決」を、本番のビルド元のブランチへ移植する(ヘッダとリクエスト行に限る)。proxy は <接頭辞>OPENSHELL-RESOLVE-ENV-<KEY>(例: github_pat_OPENSHELL-RESOLVE-ENV-GITHUB_TOKEN)を、正規の placeholder openshell:resolve:env:<KEY> と同じ秘密に差し替える。

送信前に credential の形を検査するクライアントを、sandbox の中で使えるようにするための変更である。直接のきっかけは gh pr comment --attach(gh v2.99.0 以降)で、token が github_pat_ / ghp_ / gho_ / ghu_ のいずれかで始まらないと、通信する前に拒否する。正規の placeholder はこの検査を通らない。

関連 Issue

simount/NemoClaw-on-AWS#254(AutoDev の受け入れ試験のエビデンスを、sandbox の中から PR に添付する)。進め方は https://github.com/simount/NemoClaw-on-AWS/issues/254#issuecomment-6052307911 で合意した(fork に移植し、upstream には追従しない)。

変更内容

  • test(sandbox): wrap env mutations in unsafe blocks for edition 2024(49ce5baa)
    • netns.rs と child_env.rs の direct TCP のテストが、std::env::set_var / remove_var をそのまま呼んでいる。edition 2024 ではこれらが unsafe になったため、cargo test -p openshell-sandbox --lib がコンパイルできず(19 件のエラー)、このブランチでは sandbox のテストを 1 本も実行できない状態だった。各呼び出しを unsafe ブロックで囲んだ。動作は変わらない
  • feat(sandbox): resolve provider-shaped credential aliases(78010598、crates/openshell-sandbox/src/secrets.rs)
    • resolve_placeholder は、完全一致する placeholder が無いとき、別名として解釈して引き直す。別名と認めるのは値まるごとが次の形のときだけ: 1 文字以上の接頭辞(RFC 3986 の非予約文字 A-Za-z0-9_-.~)、目印 OPENSHELL-RESOLVE-ENV-、末尾まで続く環境変数名(upstream の alias_env_key と同じ規則)
    • 差し替えた後の fail-closed の検査で、ヘッダと、パーセントデコードしたリクエスト行に目印が残っていれば止める。解決できなかった別名が upstream へ送られることはない
    • 移植していないもの: Basic 認証の中の別名、パスやクエリの中の別名、リクエスト本文、upstream の後の版で入った endpoint binding の規則。子プロセスの環境変数は正規の placeholder のままなので、git(Basic 認証)には影響しない。別名は呼び出しごとに明示して使う(例: GH_TOKEN=github_pat_OPENSHELL-RESOLVE-ENV-GITHUB_TOKEN gh pr comment --attach ...)

テスト

pf のホスト(aarch64)の rust:1.88-bookworm コンテナで実行した。

  • 新しいテストだけを入れた状態で cargo test -p openshell-sandbox --lib secrets:: を実行し、追加した 12 件のうち 6 件が失敗することを確認した(RED)。実装を入れた後は全件通る

  • cargo test -p openshell-sandbox --lib: 456 件通過、失敗 0、無効 1。なお baseline_tests::enrich_proto_baseline_paths_adds_pty_paths_for_proxy_mode は、テスト環境に /sandbox が無いと失敗する(既存のテストで環境に依存する。mkdir -p /sandbox すると通る)

  • cargo build --release -p openshell-sandbox: 成功(4 分 18 秒)。バイナリに別名の目印と OPENSHELL_DIRECT_TCP_ENDPOINTS の両方が含まれることを確認した。まだ配布していない

  • 追加したテストの内容: 別名が正規の秘密に解決される、token <別名> のヘッダの差し替え、接頭辞の非予約文字、未知の KEY、空の接頭辞、接頭辞の予約文字、KEY の後ろの余分な文字、解決した秘密に CRLF を含む場合、ヘッダブロックの往復、ヘッダとリクエスト行(パーセントエンコードを含む)に解決できない別名が残ったときの fail-closed、正規の placeholder が引き続き解決されること

  • fork の CI は、ビルドの job が upstream 用の self-hosted runner(build-amd64 / build-arm64)を要求するため、fork では実行されない(queued のまま)

  • mise run pre-commit が通る(未実行。ビルドしたホストに mise を入れていない)

  • ユニットテストを追加・更新した

  • E2E テストを追加・更新した(該当する場合)

チェックリスト

  • Conventional Commits に従っている
  • コミットに sign-off がある(DCO)
  • アーキテクチャ文書を更新した(該当する場合)

🤖 Generated with Claude Code

striderkein and others added 2 commits October 8, 2026 13:49
The direct-TCP tests call std::env::set_var / remove_var directly. These are
unsafe in edition 2024, so `cargo test -p openshell-sandbox --lib` failed to
compile (19 errors in netns.rs and child_env.rs) and no sandbox test could run.
Wrap each call in an unsafe block; behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port the alias resolution from NVIDIA#1286 (header and request-line
scope only). A client that validates the credential's shape before sending
cannot carry the canonical `openshell:resolve:env:KEY` placeholder; for example
gh's `--attach` only accepts github_pat_ / ghp_ / gho_ / ghu_ tokens. Such a
client can send `<prefix>OPENSHELL-RESOLVE-ENV-KEY` (e.g.
`github_pat_OPENSHELL-RESOLVE-ENV-GITHUB_TOKEN`), and the proxy now resolves it
to the same secret as the canonical placeholder.

- resolve_placeholder falls back to the alias when there is no exact match.
  The alias must be the whole token: a non-empty prefix of RFC 3986 unreserved
  characters, the marker, and an env key running to the end.
- The fail-closed scans after rewriting also reject a remaining alias marker
  in the header block and in the percent-decoded request line, so an
  unresolved alias is never forwarded upstream.

The child env keeps the canonical placeholder; callers opt in to an alias per
invocation (GH_TOKEN=github_pat_OPENSHELL-RESOLVE-ENV-GITHUB_TOKEN gh ...).
Aliases inside Basic credentials are not resolved; git keeps using the
canonical placeholder.

Refs simount/NemoClaw-on-AWS#254

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@striderkein
striderkein marked this pull request as ready for review October 9, 2026 03:08
@striderkein
striderkein requested a review from kosaku-sim October 9, 2026 03:08
@striderkein striderkein changed the title feat(sandbox): resolve provider-shaped credential aliases feat(sandbox): 接頭辞付きの credential 別名を placeholder と同じ秘密に解決する Oct 9, 2026
@striderkein
striderkein requested a balanced review from Copilot October 9, 2026 04:17
@striderkein striderkein self-assigned this Oct 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

fail-closed 検査の迂回経路と、並列テストで未同期の unsafe な環境変数操作が残っています。

3 open findings
What changed in this PR

Sandbox の credential alias 解決を追加し、特定クライアントの事前 token 検証に対応する変更です。

Changes:

  • provider-shaped alias の解析・秘密解決を追加
  • 未解決 alias の fail-closed 検査とテストを追加
  • Rust 2024 向けに環境変数操作を unsafe 化
File Description
crates/​openshell-sandbox/​src/​secrets.rs alias 解決、fail-closed 検査、テストを追加
crates/​openshell-sandbox/​src/​sandbox/​linux/​netns.rs テスト内の環境変数操作を更新
crates/​openshell-sandbox/​src/​child_env.rs テスト内の環境変数操作を更新

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/openshell-sandbox/src/secrets.rs Outdated
Comment thread crates/openshell-sandbox/src/child_env.rs Outdated
Comment thread crates/openshell-sandbox/src/sandbox/linux/netns.rs Outdated

@kosaku-sim kosaku-sim left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@striderkein
移植という方針ですね!
ご対応ありがとうございます。
LGTMです。

striderkein and others added 2 commits October 9, 2026 13:50
…d request target

The forward-proxy path (rewrite_forward_request) still scanned only for the
canonical placeholder after rewriting, so an unknown alias in a header, or any
alias in the request line, was forwarded upstream. rewrite_target_for_eval also
let an alias in the target through to OPA.

- rewrite_forward_request: reject a remaining placeholder or alias marker in
  the output, and in the raw and percent-decoded request line
- rewrite_target_for_eval: reject an alias marker in the target (raw and
  percent-decoded). Aliases are resolved in headers only, so one in the target
  would never be resolved
- share the marker checks (contains_credential_marker,
  request_line_has_credential_marker) and drop the now-unused
  PLACEHOLDER_PREFIX_PUBLIC

Addresses review: #4 (comment)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vars

Wrapping set_var / remove_var in unsafe blocks did not meet their safety
contract: tests run in parallel, and the tests in child_env.rs and
sandbox/linux/netns.rs read and write the same variables. Every such test now
holds a shared lock (child_env::lock_direct_tcp_env) for its whole body,
including the ones that only read through build_no_proxy / proxy_env_vars.

Addresses review:
#4 (comment)
#4 (comment)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@striderkein
striderkein merged commit 68ac1c7 into fix/basic-auth-credential-resolve Oct 9, 2026
4 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants