VSCode Extension ignores proxy settings

Resolved 💬 12 comments Opened Aug 30, 2025 by eliotcougar Closed Oct 31, 2025
💡 Likely answer: A maintainer (etraut-openai, contributor) responded on this thread — see the highlighted reply below.

What version of the VS Code extension are you using?

0.4.0

Which IDE are you using?

VS Code

What platform is your computer?

Microsoft Windows NT 10.0.26100.0 x64

What steps can reproduce the bug?

Trying to use the extension in a restricted environment with a mandatory proxy.
(I know it's a common problem with many VSCode extensions)

What is the expected behavior?

Extension should honor the system-level or VSCode-level proxy settings. Alternatively, the extension can have its own proxy setting.

What do you see instead?

The extension tries to access the Internet directly, and due to restricted nature of our environment, it fails. It basically ignores all proxy settings.

Additional information

_No response_

View original on GitHub ↗

12 Comments

bobitluo · 10 months ago

I've also encountered this issue. I hope to apply the proxy settings of VScode or the system's proxy settings. I'm using MacOS. Are there any plans to resolve this issue? Or are there any other solutions you can provide for reference?

eliotcougar · 10 months ago
I've also encountered this issue. I hope to apply the proxy settings of VScode or the system's proxy settings. I'm using MacOS. Are there any plans to resolve this issue? Or are there any other solutions you can provide for reference?

First workaround on Windows is to just use codex-cli in git bash.
Second workaround is to use some app that directs all traffic through a proxy, but acts as a network adapter (VPN). However, that may not work with some restrictive corporate proxies.

mephistiks · 10 months ago

I also have this problem, but on Linux. Usually, VSCode extensions use "http.proxy" in settings.json, or "export HTTP_PROXY=..." in the terminal for tools like Claude Code. But Codex ignores all the ways to use a proxy.

bobitluo · 10 months ago
> I've also encountered this issue. I hope to apply the proxy settings of VScode or the system's proxy settings. I'm using MacOS. Are there any plans to resolve this issue? Or are there any other solutions you can provide for reference? First workaround on Windows is to just use codex-cli in git bash. Second workaround is to use some app that directs all traffic through a proxy, but acts as a network adapter (VPN). However, that may not work with some restrictive corporate proxies.

Thank you so much for your suggestion! For now, I'm only using Codex CLI or Codex Web/App directly. I'm holding off on using Codex IDE until they fix this issue, then I'll try it again.

liyz15 · 9 months ago

A workaround is to hack the codex binary, for remote ssh:

cd "$HOME/.vscode-server/extensions/openai.chatgpt-0.4.15/bin/linux-x86_64"

# keep the original
mv codex codex.real

# wrapper that forces a proxy and then calls the original
cat > codex <<'EOF'
#!/usr/bin/env bash
export HTTPS_PROXY="http://<your-proxy-host>:<port>"
export HTTP_PROXY="http://<your-proxy-host>:<port>"
export NO_PROXY="http://<your-proxy-host>:<port>"
# ------------------------------------------------
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
exec "$HERE/codex.real" "$@"
EOF
chmod +x codex

replace openai.chatgpt-0.4.15 with your version and http://<your-proxy-host>:<port> with your proxy

kitdavidenko · 9 months ago
A workaround is to hack the codex binary, for remote ssh: cd "$HOME/.vscode-server/extensions/openai.chatgpt-0.4.15/bin/linux-x86_64" # keep the original mv codex codex.real # wrapper that forces a proxy and then calls the original cat > codex <<'EOF' #!/usr/bin/env bash export HTTPS_PROXY="http://<your-proxy-host>:<port>" export HTTP_PROXY="http://<your-proxy-host>:<port>" export NO_PROXY="http://<your-proxy-host>:<port>" # ------------------------------------------------ HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" exec "$HERE/codex.real" "$@" EOF chmod +x codex replace openai.chatgpt-0.4.15 with your version and http://<your-proxy-host>:<port> with your proxy

Inspired by your solution but for windows, I made small launcher on C.

// launcher.c
// Compile examples:
//  MSVC: cl /nologo /O2 launcher.c /Fe:codex.exe
//  MinGW: x86_64-w64-mingw32-gcc launcher.c -municode -o codex.exe
// Usage:
//  Rename codex.exe to codex.real.exe in 
//  .vscode\extensions\openai.chatgpt-0.4.19-win32-x64\bin\windows-x86_64 
//  and place your rebuilt codex.exe there. 
//  Redefine DEFAULT_PROXY and DEFAULT_NO_PROXY or use 
//  CODEX_PROXY CODEX_NO_PROXY env variables
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <shellapi.h>   // CommandLineToArgvW (not used directly here but keeps headers consistent)
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

#ifndef DEFAULT_PROXY
// default proxy requested by user
#define DEFAULT_PROXY L"http://192.168.1.3:1081"
#endif

#ifndef DEFAULT_NO_PROXY
#define DEFAULT_NO_PROXY L"localhost,127.0.0.1"
#endif

// Quote an argument according to Windows CreateProcess rules so that
// CommandLineToArgvW will parse it back to the original argument.
static int quote_arg(const wchar_t *arg, wchar_t *out, size_t out_size) {
    const wchar_t *p = arg;
    int need_quote = 0;
    while (*p) {
        if (*p == L' ' || *p == L'\t' || *p == L'"') { need_quote = 1; break; }
        p++;
    }
    if (!need_quote) {
        if (wcslen(arg) + 1 > out_size) return 0;
        wcscpy_s(out, out_size, arg);
        return 1;
    }

    size_t pos = 0;
    if (pos + 1 >= out_size) return 0;
    out[pos++] = L'"';

    const wchar_t *s = arg;
    while (*s) {
        if (*s == L'\\') {
            const wchar_t *start = s;
            while (*s == L'\\') s++;
            size_t backslashes = (size_t)(s - start);
            if (*s == L'"') {
                size_t need = backslashes * 2;
                if (pos + need >= out_size) return 0;
                for (size_t i = 0; i < need; ++i) out[pos++] = L'\\';
                if (pos + 1 >= out_size) return 0;
                out[pos++] = L'"';
                s++; // skip the quote
            } else {
                if (pos + backslashes >= out_size) return 0;
                for (size_t i = 0; i < backslashes; ++i) out[pos++] = L'\\';
            }
        } else if (*s == L'"') {
            if (pos + 2 >= out_size) return 0;
            out[pos++] = L'\\';
            out[pos++] = L'"';
            s++;
        } else {
            if (pos + 1 >= out_size) return 0;
            out[pos++] = *s++;
        }
    }

    // trailing backslashes doubling
    size_t trail = 0;
    const wchar_t *t = arg + wcslen(arg);
    while (t > arg && *(t-1) == L'\\') { ++trail; --t; }
    if (trail > 0) {
        if (pos + trail >= out_size) return 0;
        for (size_t i = 0; i < trail; ++i) out[pos++] = L'\\';
    }

    if (pos + 1 >= out_size) return 0;
    out[pos++] = L'"';
    out[pos] = L'\0';
    return 1;
}

int wmain(int argc, wchar_t **argv) {
    wchar_t modulePath[MAX_PATH];
    if (!GetModuleFileNameW(NULL, modulePath, MAX_PATH)) {
        fwprintf(stderr, L"GetModuleFileNameW failed (%lu)\n", GetLastError());
        return 1;
    }

    wchar_t *lastSlash = wcsrchr(modulePath, L'\\');
    if (!lastSlash) {
        fwprintf(stderr, L"Unexpected module path format\n");
        return 1;
    }

    size_t dirLen = (size_t)(lastSlash - modulePath + 1); // include '\'
    wchar_t dirPath[MAX_PATH];
    if (dirLen >= MAX_PATH) { fwprintf(stderr, L"path too long\n"); return 1; }
    wmemcpy(dirPath, modulePath, dirLen);
    dirPath[dirLen] = L'\0';

    wchar_t realPath[MAX_PATH];
    if (swprintf_s(realPath, MAX_PATH, L"%s%s", dirPath, L"codex.real.exe") < 0) {
        fwprintf(stderr, L"Failed composing real exe path\n");
        return 1;
    }

    wchar_t proxyBuf[1024] = {0};
    wchar_t noProxyBuf[1024] = {0};
    DWORD n;

    n = GetEnvironmentVariableW(L"CODEX_PROXY", proxyBuf, (DWORD)_countof(proxyBuf));
    if (n == 0) {
        wcscpy_s(proxyBuf, _countof(proxyBuf), DEFAULT_PROXY);
    }
    n = GetEnvironmentVariableW(L"CODEX_NO_PROXY", noProxyBuf, (DWORD)_countof(noProxyBuf));
    if (n == 0) {
        wcscpy_s(noProxyBuf, _countof(noProxyBuf), DEFAULT_NO_PROXY);
    }

    // set environment variables for this process (and children)
    SetEnvironmentVariableW(L"HTTP_PROXY", proxyBuf);
    SetEnvironmentVariableW(L"HTTPS_PROXY", proxyBuf);
    SetEnvironmentVariableW(L"NO_PROXY", noProxyBuf);

    const size_t CMD_MAX = 32768;
    wchar_t *cmdline = (wchar_t*) malloc((CMD_MAX) * sizeof(wchar_t));
    if (!cmdline) { fwprintf(stderr, L"Out of memory\n"); return 1; }
    cmdline[0] = L'\0';
    size_t pos = 0;

    wchar_t quoted[MAX_PATH * 2];
    if (!quote_arg(realPath, quoted, _countof(quoted))) {
        fwprintf(stderr, L"Failed to quote realPath\n");
        free(cmdline);
        return 1;
    }
    wcscpy_s(cmdline, CMD_MAX, quoted);
    pos = wcslen(cmdline);

    for (int i = 1; i < argc; ++i) {
        wchar_t buf[4096];
        if (!quote_arg(argv[i], buf, _countof(buf))) {
            fwprintf(stderr, L"Argument too long or quoting failed for arg %d\n", i);
            free(cmdline);
            return 1;
        }
        size_t need = pos + 1 + wcslen(buf) + 1;
        if (need > CMD_MAX) {
            fwprintf(stderr, L"Command line too long\n");
            free(cmdline);
            return 1;
        }
        cmdline[pos++] = L' ';
        cmdline[pos] = L'\0';
        wcscat_s(cmdline, CMD_MAX, buf);
        pos = wcslen(cmdline);
    }

    STARTUPINFOW si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    BOOL ok = CreateProcessW(
        NULL,
        cmdline,
        NULL, NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi
    );

    if (!ok) {
        fwprintf(stderr, L"CreateProcessW failed (%lu). CommandLine: %s\n", GetLastError(), cmdline);
        free(cmdline);
        return 1;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitCode = 0;
    if (!GetExitCodeProcess(pi.hProcess, &exitCode)) exitCode = 1;

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    free(cmdline);

    return (int) exitCode;
}
Dcatfly · 9 months ago

This issue appears to be caused by the extension not passing the http_proxy environment variable set in VSCode when calling the codex CLI. Additionally, the current codex does not support setting http_proxy through its own configuration.
However, the extension does support setting the path to the codex executable. This feature can be leveraged to create a wrapper script that sets the environment variable before calling codex.

  1. Create a new script, e.g., /usr/local/bin/codex-cli-proxy
#!/usr/bin/env zsh
set -e

export HTTP_PROXY=xxx
export HTTPS_PROXY="$HTTP_PROXY"

exec /usr/local/bin/codex "$@"

Remember to chmod +x /usr/local/bin/codex-cli-proxy

  1. In the Codex extension's IDE settings, set the Codex executable path (Chatgpt: Cli Executable) to the wrapper script path
  1. Restart the Codex extension
rixin183 · 9 months ago
#!/usr/bin/env zsh

set -e

export HTTP_PROXY=xxx
export HTTPS_PROXY="$HTTP_PROXY"

exec /usr/local/bin/codex "$@"

After modifying the plugin, it won't open and keeps spinning.

etraut-openai contributor · 8 months ago

Thanks for the feature request. This will be addressed in the next release.

gaby · 7 months ago

Proxy works now, but "NO_PROXY" is ignored.

steveepreston · 6 months ago

Please clearly say, is VSCode codex Respects the VSCode http-proxy value?
or it's ignoring it?

etraut-openai contributor · 6 months ago

@steveepreston, this issue was resolved. If you're seeing a related issue with the latest version of Codex, please use the /feedback slash command to open a new bug report and provide details and repro steps.