From 61805a832ddec35b811f511dd9863e1e0433a70b Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 24 Apr 2025 14:25:02 -0700 Subject: [PATCH] fix: do not grant "node" user sudo access when using run_in_container.sh (#627) This exploration came out of my review of https://github.com/openai/codex/pull/414. `run_in_container.sh` runs Codex in a Docker container like so: https://github.com/openai/codex/blob/bd1c3deed9f4f103e755baa3f3a45e7a1c1a134b/codex-cli/scripts/run_in_container.sh#L51-L58 But then runs `init_firewall.sh` to set up the firewall to restrict network access. Previously, we did this by adding `/usr/local/bin/init_firewall.sh` to the container and adding a special rule in `/etc/sudoers.d` so the unprivileged user (`node`) could run the privileged `init_firewall.sh` script to open up the firewall for `api.openai.com`: https://github.com/openai/codex/blob/31d0d7a305305ad557035a2edcab60b6be5018d8/codex-cli/Dockerfile#L51-L56 Though I believe this is unnecessary, as we can use `docker exec --user root` from _outside_ the container to run `/usr/local/bin/init_firewall.sh` as `root` without adding a special case in `/etc/sudoers.d`. This appears to work as expected, as I tested it by doing the following: ``` ./codex-cli/scripts/build_container.sh ./codex-cli/scripts/run_in_container.sh 'what is the output of `curl https://www.openai.com`' ``` This was a bit funny because in some of my runs, Codex wasn't convinced it had network access, so I had to convince it to try the `curl` request: ![image](https://github.com/user-attachments/assets/80bd487c-74e2-4cd3-aa0f-26a6edd8d3f7) As you can see, when it ran `curl -s https\://www.openai.com`, it a connection failure, so the network policy appears to be working as intended. Note this PR also removes `sudo` from the `apt-get install` list in the `Dockerfile`. --- codex-cli/Dockerfile | 11 +++++------ codex-cli/scripts/run_in_container.sh | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/codex-cli/Dockerfile b/codex-cli/Dockerfile index 5f894203..4ed3089b 100644 --- a/codex-cli/Dockerfile +++ b/codex-cli/Dockerfile @@ -20,7 +20,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ less \ man-db \ procps \ - sudo \ unzip \ ripgrep \ zsh \ @@ -47,10 +46,10 @@ RUN npm install -g codex.tgz \ && rm -rf /usr/local/share/npm-global/lib/node_modules/codex-cli/tests \ && rm -rf /usr/local/share/npm-global/lib/node_modules/codex-cli/docs -# Copy and set up firewall script -COPY scripts/init_firewall.sh /usr/local/bin/ +# Copy and set up firewall script as root. USER root -RUN chmod +x /usr/local/bin/init_firewall.sh && \ - echo "node ALL=(root) NOPASSWD: /usr/local/bin/init_firewall.sh" > /etc/sudoers.d/node-firewall && \ - chmod 0440 /etc/sudoers.d/node-firewall +COPY scripts/init_firewall.sh /usr/local/bin/ +RUN chmod 500 /usr/local/bin/init_firewall.sh + +# Drop back to non-root. USER node diff --git a/codex-cli/scripts/run_in_container.sh b/codex-cli/scripts/run_in_container.sh index c95c57ae..1da286a7 100755 --- a/codex-cli/scripts/run_in_container.sh +++ b/codex-cli/scripts/run_in_container.sh @@ -57,8 +57,8 @@ docker run --name "$CONTAINER_NAME" -d \ codex \ sleep infinity -# Initialize the firewall inside the container. -docker exec "$CONTAINER_NAME" bash -c "sudo /usr/local/bin/init_firewall.sh" +# Initialize the firewall inside the container with root privileges. +docker exec --user root "$CONTAINER_NAME" /usr/local/bin/init_firewall.sh # Execute the provided command in the container, ensuring it runs in the work directory. # We use a parameterized bash command to safely handle the command and directory.