Enable sandboxed V8 for code mode (#36374)

## Why

Code mode must link against a V8 build with sandbox support, but Windows MSVC
still used upstream non-sandboxed prebuilts and package builds selected the
older release artifact profile.

## What changed

- Enable the `v8_enable_sandbox` feature directly for the code mode runtime.
- Select the `ptrcomp_sandbox_release` archive and bindings in Cargo packaging
  and CI, including Windows MSVC release builds.
- Point Bazel's Windows MSVC targets at the sandbox-enabled Codex artifacts and
  enable the matching crate feature.

## Testing

Add a runtime test that calls `v8__V8__IsSandboxEnabled()` and verifies that
the linked V8 library has sandbox support enabled.

GitOrigin-RevId: c1b49b44a6ccfea5b5006d69ec7866848d1cddd7
This commit is contained in:
Sean Huang
2026-07-31 18:21:18 +00:00
committed by copyberry
parent b7a6106608
commit 2e32d95894
8 changed files with 58 additions and 32 deletions

View File

@@ -19,14 +19,25 @@ runs:
release_tag="rusty-v8-v${version}" release_tag="rusty-v8-v${version}"
base_url="https://github.com/openai/codex/releases/download/${release_tag}" base_url="https://github.com/openai/codex/releases/download/${release_tag}"
binding_dir="${RUNNER_TEMP}/rusty_v8" binding_dir="${RUNNER_TEMP}/rusty_v8"
archive_path="${binding_dir}/librusty_v8_release_${TARGET}.a.gz"
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs" profile="ptrcomp_sandbox_release"
checksums_path="${binding_dir}/rusty_v8_release_${TARGET}.sha256"
if [[ "$TARGET" == *-pc-windows-msvc ]]; then
archive_name="rusty_v8_${profile}_${TARGET}.lib.gz"
else
archive_name="librusty_v8_${profile}_${TARGET}.a.gz"
fi
binding_name="src_binding_${profile}_${TARGET}.rs"
checksums_name="rusty_v8_${profile}_${TARGET}.sha256"
archive_path="${binding_dir}/${archive_name}"
binding_path="${binding_dir}/${binding_name}"
checksums_path="${binding_dir}/${checksums_name}"
mkdir -p "${binding_dir}" mkdir -p "${binding_dir}"
curl -fsSL "${base_url}/librusty_v8_release_${TARGET}.a.gz" -o "${archive_path}" curl -fsSL "${base_url}/${archive_name}" -o "${archive_path}"
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}" curl -fsSL "${base_url}/${binding_name}" -o "${binding_path}"
curl -fsSL "${base_url}/rusty_v8_release_${TARGET}.sha256" -o "${checksums_path}" curl -fsSL "${base_url}/${checksums_name}" -o "${checksums_path}"
if [[ "$(wc -l < "${checksums_path}")" -ne 2 ]]; then if [[ "$(wc -l < "${checksums_path}")" -ne 2 ]]; then
echo "Expected exactly two checksums for ${TARGET} in ${checksums_path}" >&2 echo "Expected exactly two checksums for ${TARGET} in ${checksums_path}" >&2

View File

@@ -373,8 +373,7 @@ jobs:
shell: bash shell: bash
run: bash "${GITHUB_WORKSPACE}/.github/scripts/install-musl-build-tools.sh" run: bash "${GITHUB_WORKSPACE}/.github/scripts/install-musl-build-tools.sh"
- if: ${{ !contains(matrix.target, 'windows') }} - name: Configure rusty_v8 artifact overrides and verify checksums
name: Configure rusty_v8 artifact overrides and verify checksums
uses: ./.github/actions/setup-rusty-v8 uses: ./.github/actions/setup-rusty-v8
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}

View File

@@ -88,6 +88,11 @@ jobs:
with: with:
targets: ${{ matrix.target }} targets: ${{ matrix.target }}
- name: Configure rusty_v8 artifact overrides and verify checksums
uses: ./.github/actions/setup-rusty-v8
with:
target: ${{ matrix.target }}
- name: Configure LLVM linker - name: Configure LLVM linker
uses: ./.github/actions/setup-msvc-env uses: ./.github/actions/setup-msvc-env
with: with:

View File

@@ -394,10 +394,12 @@ crate.annotation(
crate_features_select = { crate_features_select = {
"aarch64-apple-darwin": ["v8_enable_sandbox"], "aarch64-apple-darwin": ["v8_enable_sandbox"],
"aarch64-pc-windows-gnullvm": ["v8_enable_sandbox"], "aarch64-pc-windows-gnullvm": ["v8_enable_sandbox"],
"aarch64-pc-windows-msvc": ["v8_enable_sandbox"],
"aarch64-unknown-linux-gnu": ["v8_enable_sandbox"], "aarch64-unknown-linux-gnu": ["v8_enable_sandbox"],
"aarch64-unknown-linux-musl": ["v8_enable_sandbox"], "aarch64-unknown-linux-musl": ["v8_enable_sandbox"],
"x86_64-apple-darwin": ["v8_enable_sandbox"], "x86_64-apple-darwin": ["v8_enable_sandbox"],
"x86_64-pc-windows-gnullvm": ["v8_enable_sandbox"], "x86_64-pc-windows-gnullvm": ["v8_enable_sandbox"],
"x86_64-pc-windows-msvc": ["v8_enable_sandbox"],
"x86_64-unknown-linux-gnu": ["v8_enable_sandbox"], "x86_64-unknown-linux-gnu": ["v8_enable_sandbox"],
"x86_64-unknown-linux-musl": ["v8_enable_sandbox"], "x86_64-unknown-linux-musl": ["v8_enable_sandbox"],
}, },
@@ -518,18 +520,18 @@ git_repository(
http_file( http_file(
name = "rusty_v8_150_4_0_aarch64_pc_windows_msvc_archive", name = "rusty_v8_150_4_0_aarch64_pc_windows_msvc_archive",
downloaded_file_path = "rusty_v8_release_aarch64-pc-windows-msvc.lib.gz", downloaded_file_path = "rusty_v8_release_aarch64-pc-windows-msvc.lib.gz",
sha256 = "ce9f2e4321e0dd4bc64882b6daefc028863608ed934e387a98ca384f1f7923f8", sha256 = "54722842af36b74248c403ff531254efac6ff65d281198bab0c6350fc1188ad4",
urls = [ urls = [
"https://github.com/denoland/rusty_v8/releases/download/v150.4.0/rusty_v8_release_aarch64-pc-windows-msvc.lib.gz", "https://github.com/openai/codex/releases/download/rusty-v8-v150.4.0/rusty_v8_ptrcomp_sandbox_release_aarch64-pc-windows-msvc.lib.gz",
], ],
) )
http_file( http_file(
name = "rusty_v8_150_4_0_x86_64_pc_windows_msvc_archive", name = "rusty_v8_150_4_0_x86_64_pc_windows_msvc_archive",
downloaded_file_path = "rusty_v8_release_x86_64-pc-windows-msvc.lib.gz", downloaded_file_path = "rusty_v8_release_x86_64-pc-windows-msvc.lib.gz",
sha256 = "571bf6a028576ac1413c8a942383f637f91e94b0c964bbeefff8a098637aaa40", sha256 = "732ec5da4243aa166799780c8519a5eea6f32f6e47657a323342794dc3c239d6",
urls = [ urls = [
"https://github.com/denoland/rusty_v8/releases/download/v150.4.0/rusty_v8_release_x86_64-pc-windows-msvc.lib.gz", "https://github.com/openai/codex/releases/download/rusty-v8-v150.4.0/rusty_v8_ptrcomp_sandbox_release_x86_64-pc-windows-msvc.lib.gz",
], ],
) )

View File

@@ -9,9 +9,6 @@ doctest = false
name = "codex_code_mode_runtime" name = "codex_code_mode_runtime"
path = "src/lib.rs" path = "src/lib.rs"
[features]
sandbox = ["v8/v8_enable_sandbox"]
[lints] [lints]
workspace = true workspace = true
@@ -24,7 +21,7 @@ serde_json = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] } tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] }
tokio-util = { workspace = true, features = ["rt"] } tokio-util = { workspace = true, features = ["rt"] }
tracing = { workspace = true } tracing = { workspace = true }
v8 = { workspace = true } v8 = { workspace = true, features = ["v8_enable_sandbox"] }
[dev-dependencies] [dev-dependencies]
pretty_assertions = { workspace = true } pretty_assertions = { workspace = true }

View File

@@ -354,6 +354,19 @@ mod tests {
} }
} }
#[test]
fn linked_v8_has_sandbox_enabled() {
unsafe extern "C" {
fn v8__V8__IsSandboxEnabled() -> bool;
}
// `rusty_v8` exposes this symbol for verifying linked sandbox support.
assert!(
unsafe { v8__V8__IsSandboxEnabled() },
"code mode must link against sandbox-enabled V8"
);
}
#[tokio::test] #[tokio::test]
async fn runtime_thread_panic_before_initialization_is_reported_directly() { async fn runtime_thread_panic_before_initialization_is_reported_directly() {
let (event_tx, event_rx) = mpsc::unbounded_channel(); let (event_tx, event_rx) = mpsc::unbounded_channel();

View File

@@ -11,11 +11,10 @@ from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from urllib.request import urlopen from urllib.request import urlopen
from .targets import REPO_ROOT from .targets import REPO_ROOT, TargetSpec
from .targets import TargetSpec
DOWNLOAD_TIMEOUT_SECS = 120 DOWNLOAD_TIMEOUT_SECS = 120
V8_ARTIFACT_PROFILE = "ptrcomp_sandbox_release"
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -30,9 +29,6 @@ def resolve_codex_v8_cargo_env(
environ: Mapping[str, str] | None = None, environ: Mapping[str, str] | None = None,
cache_root: Path | None = None, cache_root: Path | None = None,
) -> dict[str, str]: ) -> dict[str, str]:
if spec.is_windows:
return {}
environ = os.environ if environ is None else environ environ = os.environ if environ is None else environ
if environ.get("V8_FROM_SOURCE") in {"true", "1", "yes"}: if environ.get("V8_FROM_SOURCE") in {"true", "1", "yes"}:
return {} return {}
@@ -59,20 +55,23 @@ def fetch_codex_v8_artifacts(
version: str | None = None, version: str | None = None,
cache_root: Path | None = None, cache_root: Path | None = None,
) -> RustyV8ArtifactPair: ) -> RustyV8ArtifactPair:
if spec.is_windows:
raise RuntimeError(
f"No Codex-built V8 release artifacts for target: {spec.target}"
)
version = version or resolved_v8_crate_version() version = version or resolved_v8_crate_version()
release_url = ( release_url = (
f"https://github.com/openai/codex/releases/download/rusty-v8-v{version}" f"https://github.com/openai/codex/releases/download/rusty-v8-v{version}"
) )
target = spec.target target = spec.target
cache_dir = (cache_root or default_cache_root()) / f"rusty-v8-{version}-{target}" cache_dir = (cache_root or default_cache_root()) / f"rusty-v8-{version}-{target}"
archive = cache_dir / f"librusty_v8_release_{target}.a.gz"
binding = cache_dir / f"src_binding_release_{target}.rs" if spec.is_windows:
checksums = cache_dir / f"rusty_v8_release_{target}.sha256" archive_name = f"rusty_v8_{V8_ARTIFACT_PROFILE}_{target}.lib.gz"
else:
archive_name = f"librusty_v8_{V8_ARTIFACT_PROFILE}_{target}.a.gz"
binding_name = f"src_binding_{V8_ARTIFACT_PROFILE}_{target}.rs"
checksums_name = f"rusty_v8_{V8_ARTIFACT_PROFILE}_{target}.sha256"
archive = cache_dir / archive_name
binding = cache_dir / binding_name
checksums = cache_dir / checksums_name
download_file(f"{release_url}/{checksums.name}", checksums) download_file(f"{release_url}/{checksums.name}", checksums)
expected_checksums = load_checksums(checksums, {archive.name, binding.name}) expected_checksums = load_checksums(checksums, {archive.name, binding.name})

View File

@@ -1,2 +1,2 @@
ce9f2e4321e0dd4bc64882b6daefc028863608ed934e387a98ca384f1f7923f8 rusty_v8_release_aarch64-pc-windows-msvc.lib.gz 54722842af36b74248c403ff531254efac6ff65d281198bab0c6350fc1188ad4 rusty_v8_release_aarch64-pc-windows-msvc.lib.gz
571bf6a028576ac1413c8a942383f637f91e94b0c964bbeefff8a098637aaa40 rusty_v8_release_x86_64-pc-windows-msvc.lib.gz 732ec5da4243aa166799780c8519a5eea6f32f6e47657a323342794dc3c239d6 rusty_v8_release_x86_64-pc-windows-msvc.lib.gz