Skip to content

Commit 66f1964

Browse files
lee101claude
andcommitted
Codex Infinity v1.3.29 - merge upstream + maintain custom features
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 parents b8f0aac + 0bdeab3 commit 66f1964

330 files changed

Lines changed: 9243 additions & 4769 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/Dockerfile.secure

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
2+
3+
ARG TZ
4+
ARG DEBIAN_FRONTEND=noninteractive
5+
ARG NODE_MAJOR=22
6+
ARG RUST_TOOLCHAIN=1.92.0
7+
ARG CODEX_NPM_VERSION=latest
8+
9+
ENV TZ="$TZ"
10+
11+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
12+
13+
RUN apt-get update \
14+
&& apt-get install -y --no-install-recommends \
15+
build-essential \
16+
curl \
17+
git \
18+
ca-certificates \
19+
pkg-config \
20+
clang \
21+
musl-tools \
22+
libssl-dev \
23+
libsqlite3-dev \
24+
just \
25+
python3 \
26+
python3-pip \
27+
jq \
28+
less \
29+
man-db \
30+
unzip \
31+
ripgrep \
32+
fzf \
33+
fd-find \
34+
zsh \
35+
dnsutils \
36+
iproute2 \
37+
ipset \
38+
iptables \
39+
aggregate \
40+
&& apt-get clean \
41+
&& rm -rf /var/lib/apt/lists/*
42+
43+
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - \
44+
&& apt-get update \
45+
&& apt-get install -y --no-install-recommends nodejs \
46+
&& npm install -g corepack@latest "@openai/codex@${CODEX_NPM_VERSION}" \
47+
&& corepack enable \
48+
&& corepack prepare pnpm@10.28.2 --activate \
49+
&& apt-get clean \
50+
&& rm -rf /var/lib/apt/lists/*
51+
52+
COPY .devcontainer/init-firewall.sh /usr/local/bin/init-firewall.sh
53+
COPY .devcontainer/post_install.py /opt/post_install.py
54+
COPY .devcontainer/post-start.sh /opt/post_start.sh
55+
56+
RUN chmod 500 /usr/local/bin/init-firewall.sh \
57+
&& chmod 755 /opt/post_start.sh \
58+
&& chmod 644 /opt/post_install.py \
59+
&& chown vscode:vscode /opt/post_install.py
60+
61+
RUN install -d -m 0775 -o vscode -g vscode /commandhistory /workspace \
62+
&& touch /commandhistory/.bash_history /commandhistory/.zsh_history \
63+
&& chown vscode:vscode /commandhistory/.bash_history /commandhistory/.zsh_history
64+
65+
USER vscode
66+
ENV PATH="/home/vscode/.cargo/bin:${PATH}"
67+
WORKDIR /workspace
68+
69+
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${RUST_TOOLCHAIN}" \
70+
&& rustup component add clippy rustfmt rust-src \
71+
&& rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl

.devcontainer/README.md

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
# Containerized Development
22

3-
We provide the following options to facilitate Codex development in a container. This is particularly useful for verifying the Linux build when working on a macOS host.
3+
We provide two container paths:
4+
5+
- `devcontainer.json` keeps the existing Codex contributor setup for working on this repository.
6+
- `devcontainer.secure.json` adds a customer-oriented profile with stricter outbound network controls.
7+
8+
## Codex contributor profile
9+
10+
Use `devcontainer.json` when you are developing Codex itself. This is the same lightweight arm64 container that already exists in the repo.
11+
12+
## Secure customer profile
13+
14+
Use `devcontainer.secure.json` when you want a stricter runtime profile for running Codex inside a project container:
15+
16+
- installs the Codex CLI plus common build tools
17+
- enables firewall startup with an allowlist-driven outbound policy
18+
- blocks IPv6 by default so the allowlist cannot be bypassed over AAAA routes
19+
- requires `NET_ADMIN` and `NET_RAW` so the firewall can be installed at startup
20+
21+
This profile keeps the stricter networking isolated to the customer path instead of changing the default Codex contributor container.
22+
23+
Start it from the CLI with:
24+
25+
```bash
26+
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.json
27+
```
28+
29+
In VS Code, choose **Dev Containers: Open Folder in Container...** and select `.devcontainer/devcontainer.secure.json`.
430

531
## Docker
632

7-
To build the Docker image locally for x64 and then run it with the repo mounted under `/workspace`:
33+
To build the contributor image locally for x64 and then run it with the repo mounted under `/workspace`:
834

935
```shell
1036
CODEX_DOCKER_IMAGE_NAME=codex-linux-dev
@@ -14,17 +40,6 @@ docker run --platform=linux/amd64 --rm -it -e CARGO_TARGET_DIR=/workspace/codex-
1440

1541
Note that `/workspace/target` will contain the binaries built for your host platform, so we include `-e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64` in the `docker run` command so that the binaries built inside your container are written to a separate directory.
1642

17-
For arm64, specify `--platform=linux/amd64` instead for both `docker build` and `docker run`.
18-
19-
Currently, the `Dockerfile` works for both x64 and arm64 Linux, though you need to run `rustup target add x86_64-unknown-linux-musl` yourself to install the musl toolchain for x64.
20-
21-
## VS Code
43+
For arm64, specify `--platform=linux/arm64` instead for both `docker build` and `docker run`.
2244

23-
VS Code recognizes the `devcontainer.json` file and gives you the option to develop Codex in a container. Currently, `devcontainer.json` builds and runs the `arm64` flavor of the container.
24-
25-
From the integrated terminal in VS Code, you can build either flavor of the `arm64` build (GNU or musl):
26-
27-
```shell
28-
cargo build --target aarch64-unknown-linux-musl
29-
cargo build --target aarch64-unknown-linux-gnu
30-
```
45+
Currently, the contributor `Dockerfile` works for both x64 and arm64 Linux, though you need to run `rustup target add x86_64-unknown-linux-musl` yourself to install the musl toolchain for x64.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
3+
"name": "Codex (Secure)",
4+
"build": {
5+
"dockerfile": "Dockerfile.secure",
6+
"context": "..",
7+
"args": {
8+
"TZ": "${localEnv:TZ:UTC}",
9+
"NODE_MAJOR": "22",
10+
"RUST_TOOLCHAIN": "1.92.0",
11+
"CODEX_NPM_VERSION": "latest"
12+
}
13+
},
14+
"runArgs": [
15+
"--cap-add=NET_ADMIN",
16+
"--cap-add=NET_RAW"
17+
],
18+
"init": true,
19+
"updateRemoteUserUID": true,
20+
"remoteUser": "vscode",
21+
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
22+
"workspaceFolder": "/workspace",
23+
"mounts": [
24+
"source=codex-commandhistory-${devcontainerId},target=/commandhistory,type=volume",
25+
"source=codex-home-${devcontainerId},target=/home/vscode/.codex,type=volume",
26+
"source=codex-gh-${devcontainerId},target=/home/vscode/.config/gh,type=volume",
27+
"source=codex-cargo-registry-${devcontainerId},target=/home/vscode/.cargo/registry,type=volume",
28+
"source=codex-cargo-git-${devcontainerId},target=/home/vscode/.cargo/git,type=volume",
29+
"source=codex-rustup-${devcontainerId},target=/home/vscode/.rustup,type=volume",
30+
"source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,readonly"
31+
],
32+
"containerEnv": {
33+
"RUST_BACKTRACE": "1",
34+
"CODEX_UNSAFE_ALLOW_NO_SANDBOX": "1",
35+
"CODEX_ENABLE_FIREWALL": "1",
36+
"CODEX_INCLUDE_GITHUB_META_RANGES": "1",
37+
"OPENAI_ALLOWED_DOMAINS": "api.openai.com auth.openai.com github.com api.github.com codeload.github.com raw.githubusercontent.com objects.githubusercontent.com crates.io index.crates.io static.crates.io static.rust-lang.org registry.npmjs.org pypi.org files.pythonhosted.org",
38+
"CARGO_TARGET_DIR": "/workspace/.cache/cargo-target",
39+
"GIT_CONFIG_GLOBAL": "/home/vscode/.gitconfig.local",
40+
"COREPACK_ENABLE_DOWNLOAD_PROMPT": "0",
41+
"PYTHONDONTWRITEBYTECODE": "1",
42+
"PIP_DISABLE_PIP_VERSION_CHECK": "1"
43+
},
44+
"remoteEnv": {
45+
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
46+
},
47+
"postCreateCommand": "python3 /opt/post_install.py",
48+
"postStartCommand": "bash /opt/post_start.sh",
49+
"waitFor": "postStartCommand",
50+
"customizations": {
51+
"vscode": {
52+
"settings": {
53+
"terminal.integrated.defaultProfile.linux": "zsh",
54+
"terminal.integrated.profiles.linux": {
55+
"bash": {
56+
"path": "bash",
57+
"icon": "terminal-bash"
58+
},
59+
"zsh": {
60+
"path": "zsh"
61+
}
62+
},
63+
"files.trimTrailingWhitespace": true,
64+
"files.insertFinalNewline": true,
65+
"files.trimFinalNewlines": true
66+
},
67+
"extensions": [
68+
"openai.chatgpt",
69+
"rust-lang.rust-analyzer",
70+
"tamasfe.even-better-toml",
71+
"vadimcn.vscode-lldb",
72+
"ms-azuretools.vscode-docker"
73+
]
74+
}
75+
}
76+
}

.devcontainer/init-firewall.sh

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
IFS=$'\n\t'
4+
5+
allowed_domains_file="/etc/codex/allowed_domains.txt"
6+
include_github_meta_ranges="${CODEX_INCLUDE_GITHUB_META_RANGES:-1}"
7+
8+
if [ -f "$allowed_domains_file" ]; then
9+
mapfile -t allowed_domains < <(sed '/^\s*#/d;/^\s*$/d' "$allowed_domains_file")
10+
else
11+
allowed_domains=("api.openai.com")
12+
fi
13+
14+
if [ "${#allowed_domains[@]}" -eq 0 ]; then
15+
echo "ERROR: No allowed domains configured"
16+
exit 1
17+
fi
18+
19+
add_ipv4_cidr_to_allowlist() {
20+
local source="$1"
21+
local cidr="$2"
22+
23+
if [[ ! "$cidr" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}/[0-9]{1,2}$ ]]; then
24+
echo "ERROR: Invalid ${source} CIDR range: $cidr"
25+
exit 1
26+
fi
27+
28+
ipset add allowed-domains "$cidr" -exist
29+
}
30+
31+
configure_ipv6_default_deny() {
32+
if ! command -v ip6tables >/dev/null 2>&1; then
33+
echo "ERROR: ip6tables is required to enforce IPv6 default-deny policy"
34+
exit 1
35+
fi
36+
37+
ip6tables -F
38+
ip6tables -X
39+
ip6tables -t mangle -F
40+
ip6tables -t mangle -X
41+
ip6tables -t nat -F 2>/dev/null || true
42+
ip6tables -t nat -X 2>/dev/null || true
43+
44+
ip6tables -A INPUT -i lo -j ACCEPT
45+
ip6tables -A OUTPUT -o lo -j ACCEPT
46+
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
47+
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
48+
49+
ip6tables -P INPUT DROP
50+
ip6tables -P FORWARD DROP
51+
ip6tables -P OUTPUT DROP
52+
53+
echo "IPv6 firewall policy configured (default-deny)"
54+
}
55+
56+
# Preserve docker-managed DNS NAT rules before clearing tables.
57+
docker_dns_rules="$(iptables-save -t nat | grep "127\\.0\\.0\\.11" || true)"
58+
59+
iptables -F
60+
iptables -X
61+
iptables -t nat -F
62+
iptables -t nat -X
63+
iptables -t mangle -F
64+
iptables -t mangle -X
65+
ipset destroy allowed-domains 2>/dev/null || true
66+
67+
if [ -n "$docker_dns_rules" ]; then
68+
echo "Restoring Docker DNS NAT rules"
69+
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
70+
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
71+
while IFS= read -r rule; do
72+
[ -z "$rule" ] && continue
73+
iptables -t nat $rule
74+
done <<< "$docker_dns_rules"
75+
fi
76+
77+
# Allow DNS resolution and localhost communication.
78+
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
79+
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
80+
iptables -A INPUT -p udp --sport 53 -j ACCEPT
81+
iptables -A INPUT -p tcp --sport 53 -j ACCEPT
82+
iptables -A INPUT -i lo -j ACCEPT
83+
iptables -A OUTPUT -o lo -j ACCEPT
84+
85+
ipset create allowed-domains hash:net
86+
87+
for domain in "${allowed_domains[@]}"; do
88+
echo "Resolving $domain"
89+
ips="$(dig +short A "$domain" | sed '/^\s*$/d')"
90+
if [ -z "$ips" ]; then
91+
echo "ERROR: Failed to resolve $domain"
92+
exit 1
93+
fi
94+
95+
while IFS= read -r ip; do
96+
if [[ ! "$ip" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
97+
echo "ERROR: Invalid IPv4 address from DNS for $domain: $ip"
98+
exit 1
99+
fi
100+
ipset add allowed-domains "$ip" -exist
101+
done <<< "$ips"
102+
done
103+
104+
if [ "$include_github_meta_ranges" = "1" ]; then
105+
echo "Fetching GitHub meta ranges"
106+
github_meta="$(curl -fsSL --connect-timeout 10 https://api.github.com/meta)"
107+
108+
if ! echo "$github_meta" | jq -e '.web and .api and .git' >/dev/null; then
109+
echo "ERROR: GitHub meta response missing expected fields"
110+
exit 1
111+
fi
112+
113+
while IFS= read -r cidr; do
114+
[ -z "$cidr" ] && continue
115+
if [[ "$cidr" == *:* ]]; then
116+
# Current policy enforces IPv4-only ipset entries.
117+
continue
118+
fi
119+
add_ipv4_cidr_to_allowlist "GitHub" "$cidr"
120+
done < <(echo "$github_meta" | jq -r '((.web // []) + (.api // []) + (.git // []))[]' | sort -u)
121+
fi
122+
123+
host_ip="$(ip route | awk '/default/ {print $3; exit}')"
124+
if [ -z "$host_ip" ]; then
125+
echo "ERROR: Failed to detect host IP"
126+
exit 1
127+
fi
128+
129+
host_network="$(echo "$host_ip" | sed 's/\.[0-9]*$/.0\/24/')"
130+
iptables -A INPUT -s "$host_network" -j ACCEPT
131+
iptables -A OUTPUT -d "$host_network" -j ACCEPT
132+
133+
iptables -P INPUT DROP
134+
iptables -P FORWARD DROP
135+
iptables -P OUTPUT DROP
136+
137+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
138+
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
139+
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
140+
141+
# Reject rather than silently drop to make policy failures obvious.
142+
iptables -A INPUT -j REJECT --reject-with icmp-admin-prohibited
143+
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
144+
iptables -A FORWARD -j REJECT --reject-with icmp-admin-prohibited
145+
146+
configure_ipv6_default_deny
147+
148+
echo "Firewall configuration complete"
149+
150+
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
151+
echo "ERROR: Firewall verification failed - was able to reach https://example.com"
152+
exit 1
153+
fi
154+
155+
if ! curl --connect-timeout 5 https://api.openai.com >/dev/null 2>&1; then
156+
echo "ERROR: Firewall verification failed - unable to reach https://api.openai.com"
157+
exit 1
158+
fi
159+
160+
if [ "$include_github_meta_ranges" = "1" ] && ! curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
161+
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
162+
exit 1
163+
fi
164+
165+
if curl --connect-timeout 5 -6 https://example.com >/dev/null 2>&1; then
166+
echo "ERROR: Firewall verification failed - was able to reach https://example.com over IPv6"
167+
exit 1
168+
fi
169+
170+
echo "Firewall verification passed"

0 commit comments

Comments
 (0)