Environment variable pollution in vscode, codex extension sets DEBUG="release"

Open 💬 8 comments Opened Mar 6, 2026 by TTTPOB

What version of the IDE extension are you using?

26.304.20706, vscode

What subscription do you have?

plus

Which IDE are you using?

vscode

What platform is your computer?

Microsoft Windows NT 10.0.26100.0 x64

What issue are you seeing?

Codex extension inject DEBUG=release env var into some other extension created integrated terminal. For now I can confirm, Kubernetes plugin created port-forward terminal have this pollution, which will then cause it turn on verbose logging.

❯ Get-ChildItem Env: | Sort-Object Name | rg DEBUG
DEBUG                          release

If disable codex extension, or just run the same command outside of vscode integrated terminal, no output.

And to verify:

❯ cd C:\Users\tpob\.vscode\extensions\openai.chatgpt-0.4.79\

❯ rg 'DEBUG.{0,100}release'
out\extension.js
36:`).some(n=>n.indexOf("(https.js:")!==-1||n.indexOf("node:https:")!==-1)}incrementSockets(e){if(this.maxSockets===1/0&&this.maxTotalSockets===1/0)return null;this.sockets[e]||(this.sockets[e]=[]);let r=new Uue.Socket({writable:!1});return this.sockets[e].push(r),this.totalSocketCount++,r}decrementSockets(e,r){if(!this.sockets[e]||r===null)return;let n=this.sockets[e],o=n.indexOf(r);o!==-1&&(n.splice(o,1),this.totalSocketCount--,n.length===0&&delete this.sockets[e])}getName(e){return(typeof e.secureEndpoint=="boolean"?e.secureEndpoint:this.isSecureEndpoint(e))?Fue.Agent.prototype.getName.call(this,e):super.getName(e)}createSocket(e,r,n){let o={...r,secureEndpoint:this.isSecureEndpoint(r)},i=this.getName(o),s=this.incrementSockets(i);Promise.resolve().then(()=>this.connect(e,o)).then(a=>{if(this.decrementSockets(i,s),a instanceof Dq.Agent)try{return a.addRequest(e,o)}catch(c){return n(c)}this[_o].currentSocket=a,super.createSocket(e,r,n)},a=>{this.decrementSockets(i,s),n(a)})}createConnection(){let e=this[_o].currentSocket;if(this[_o].currentSocket=void 0,!e)throw new Error("No socket was returned in the `connect()` function");return e}get defaultPort(){return this[_o].defaultPort??(this.protocol==="https:"?443:80)}set defaultPort(e){this[_o]&&(this[_o].defaultPort=e)}get protocol(){return this[_o].protocol??(this.isSecureEndpoint()?"https:":"http:")}set protocol(e){this[_o]&&(this[_o].protocol=e)}};nn.Agent=KR});var jq=S((jFe,zq)=>{var tu=1e3,ru=tu*60,nu=ru*60,Ys=nu*24,zue=Ys*7,jue=Ys*365.25;zq.exports=function(t,e){e=e||{};var r=typeof t;if(r==="string"&&t.length>0)return que(t);if(r==="number"&&isFinite(t))return e.long?Wue(t):Bue(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))};function que(t){if(t=String(t),!(t.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(t);if(e){var r=parseFloat(e[1]),n=(e[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"yrs":case"yr":case"y":return r*jue;case"weeks":case"week":case"w":return r*zue;case"days":case"day":case"d":return r*Ys;case"hours":case"hour":case"hrs":case"hr":case"h":return r*nu;case"minutes":case"minute":case"mins":case"min":case"m":return r*ru;case"seconds":case"second":case"secs":case"sec":case"s":return r*tu;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}}}function Bue(t){var e=Math.abs(t);return e>=Ys?Math.round(t/Ys)+"d":e>=nu?Math.round(t/nu)+"h":e>=ru?Math.round(t/ru)+"m":e>=tu?Math.round(t/tu)+"s":t+"ms"}function Wue(t){var e=Math.abs(t);return e>=Ys?pv(t,e,Ys,"day"):e>=nu?pv(t,e,nu,"hour"):e>=ru?pv(t,e,ru,"minute"):e>=tu?pv(t,e,tu,"second"):t+" ms"}function pv(t,e,r,n){var o=e>=r*1.5;return Math.round(t/r)+" "+n+(o?"s":"")}});var JR=S((qFe,qq)=>{function Gue(t){r.debug=r,r.default=r,r.coerce=c,r.disable=s,r.enable=o,r.enabled=a,r.humanize=jq(),r.destroy=u,Object.keys(t).forEach(l=>{r[l]=t[l]}),r.names=[],r.skips=[],r.formatters={};function e(l){let d=0;for(let f=0;f<l.length;f++)d=(d<<5)-d+l.charCodeAt(f),d|=0;return r.colors[Math.abs(d)%r.colors.length]}r.selectColor=e;function r(l){let d,f=null,m,g;function v(...w){if(!v.enabled)return;let _=v,k=Number(new Date),E=k-(d||k);_.diff=E,_.prev=d,_.curr=k,d=k,w[0]=r.coerce(w[0]),typeof w[0]!="string"&&w.unshift("%O");let T=0;w[0]=w[0].replace(/%([a-zA-Z%])/g,(G,Q)=>{if(G==="%%")return"%";T++;let Pe=r.formatters[Q];if(typeof Pe=="function"){let ie=w[T];G=Pe.call(_,ie),w.splice(T,1),T--}return G}),r.formatArgs.call(_,w),(_.log||r.log).apply(_,w)}return v.namespace=l,v.useColors=r.useColors(),v.color=r.selectColor(l),v.extend=n,v.destroy=r.destroy,Object.defineProperty(v,"enabled",{enumerable:!0,configurable:!1,get:()=>f!==null?f:(m!==r.namespaces&&(m=r.namespaces,g=r.enabled(l)),g),set:w=>{f=w}}),typeof r.init=="function"&&r.init(v),v}function n(l,d){let f=r(this.namespace+(typeof d>"u"?":":d)+l);return f.log=this.log,f}function o(l){r.save(l),r.namespaces=l,r.names=[],r.skips=[];let d=(typeof l=="string"?l:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let f of d)f[0]==="-"?r.skips.push(f.slice(1)):r.names.push(f)}function i(l,d){let f=0,m=0,g=-1,v=0;for(;f<l.length;)if(m<d.length&&(d[m]===l[f]||d[m]==="*"))d[m]==="*"?(g=m,v=f,m++):(f++,m++);else if(g!==-1)m=g+1,v++,f=v;else return!1;for(;m<d.length&&d[m]==="*";)m++;return m===d.length}function s(){let l=[...r.names,...r.skips.map(d=>"-"+d)].join(",");return r.enable(""),l}function a(l){for(let d of r.skips)if(i(l,d))return!1;for(let d of r.names)if(i(l,d))return!0;return!1}function c(l){return l instanceof Error?l.stack||l.message:l}function u(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return r.enable(r.load()),r}qq.exports=Gue});var Bq=S((jr,fv)=>{jr.formatArgs=Vue;jr.save=Zue;jr.load=Kue;jr.useColors=Hue;jr.storage=Jue();jr.destroy=(()=>{let t=!1;return()=>{t||(t=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();jr.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function Hue(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let t;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(t=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(t[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function Vue(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+fv.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;t.splice(1,0,e,"color: inherit");let r=0,n=0;t[0].replace(/%[a-zA-Z%]/g,o=>{o!=="%%"&&(r++,o==="%c"&&(n=r))}),t.splice(n,0,e)}jr.log=console.debug||console.log||(()=>{});function Zue(t){try{t?jr.storage.setItem("debug",t):jr.storage.removeItem("debug")}catch{}}function Kue(){let t;try{t=jr.storage.getItem("debug")||jr.storage.getItem("DEBUG")}catch{}return!t&&typeof process<"u"&&"env"in process&&(t="release"),t}function Jue(){try{return localStorage}catch{}}fv.exports=JR()(jr);var{formatters:Yue}=fv.exports;Yue.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var Gq=S((BFe,Wq)=>{"use strict";Wq.exports=(t,e=process.argv)=>{let r=t.startsWith("-")?"":t.length===1?"-":"--",n=e.indexOf(r+t),o=e.indexOf("--");return n!==-1&&(o===-1||n<o)}});var Zq=S((WFe,Vq)=>{"use strict";var Xue=require("os"),Hq=require("tty"),bn=Gq(),{env:tr}=process,mv;bn("no-color")||bn("no-colors")||bn("color=false")||bn("color=never")?mv=0:(bn("color")||bn("colors")||bn("color=true")||bn("color=always"))&&(mv=1);function Que(){if("FORCE_COLOR"in tr)return tr.FORCE_COLOR==="true"?1:tr.FORCE_COLOR==="false"?0:tr.FORCE_COLOR.length===0?1:Math.min(Number.parseInt(tr.FORCE_COLOR,10),3)}function ele(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function tle(t,{streamIsTTY:e,sniffFlags:r=!0}={}){let n=Que();n!==void 0&&(mv=n);let o=r?mv:n;if(o===0)return 0;if(r){if(bn("color=16m")||bn("color=full")||bn("color=truecolor"))return 3;if(bn("color=256"))return 2}if(t&&!e&&o===void 0)return 0;let i=o||0;if(tr.TERM==="dumb")return i;if(process.platform==="win32"){let s=Xue.release().split(".");return Number(s[0])>=10&&Number(s[2])>=10586?Number(s[2])>=14931?3:2:1}if("CI"in tr)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE","DRONE"].some(s=>s in tr)||tr.CI_NAME==="codeship"?1:i;if("TEAMCITY_VERSION"in tr)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(tr.TEAMCITY_VERSION)?1:0;if(tr.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in tr){let s=Number.parseInt((tr.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(tr.TERM_PROGRAM){case"iTerm.app":return s>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(tr.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(tr.TERM)||"COLORTERM"in tr?1:i}function YR(t,e={}){let r=tle(t,{streamIsTTY:t&&t.isTTY,...e});return ele(r)}Vq.exports={supportsColor:YR,stdout:YR({isTTY:Hq.isatty(1)}),stderr:YR({isTTY:Hq.isatty(2)})}});var Jq=S((rr,gv)=>{var rle=require("tty"),hv=require("util");rr.init=ule;rr.log=sle;rr.formatArgs=ole;rr.save=ale;rr.load=cle;rr.useColors=nle;rr.destroy=hv.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");rr.colors=[6,2,3,4,5,1];try{let t=Zq();t&&(t.stderr||t).level>=2&&(rr.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}rr.inspectOpts=Object.keys(process.env).filter(t=>/^debug_/i.test(t)).reduce((t,e)=>{let r=e.substring(6).toLowerCase().replace(/_([a-z])/g,(o,i)=>i.toUpperCase()),n=process.env[e];return/^(yes|on|true|enabled)$/i.test(n)?n=!0:/^(no|off|false|disabled)$/i.test(n)?n=!1:n==="null"?n=null:n=Number(n),t[r]=n,t},{});function nle(){return"colors"in rr.inspectOpts?!!rr.inspectOpts.colors:rle.isatty(process.stderr.fd)}function ole(t){let{namespace:e,useColors:r}=this;if(r){let n=this.color,o="\x1B[3"+(n<8?n:"8;5;"+n),i=`  ${o};1m${e} \x1B[0m`;t[0]=i+t[0].split(`
39:`)}function ale(t){t?process.env.DEBUG=t:delete"release"}function cle(){return"release"}function ule(t){t.inspectOpts={};let e=Object.keys(rr.inspectOpts);for(let r=0;r<e.length;r++)t.inspectOpts[e[r]]=rr.inspectOpts[e[r]]}gv.exports=JR()(rr);var{formatters:Kq}=gv.exports;Kq.o=function(t){return this.inspectOpts.colors=this.useColors,hv.inspect(t,this.inspectOpts).split(`

which means the packed extension indeed have this DEBUG env var setting logic. But since source code of it not available, I can't see which kind of integrated terminal it affects.

What steps can reproduce the bug?

  1. install codex extension
  2. install kubernetes extension ms-kubernetes-tools.vscode-kubernetes-tools.
  3. right click a pod and select port-forward, to forward an arbitary port. (fig 1) thiis will open an integrated terminal.
  4. in the created terminal, ctrl + c to interrupt the process, and check the env var like above
  5. turn off codex extension and try again

<img width="703" height="1037" alt="Image" src="https://github.com/user-attachments/assets/61e82edc-5313-4b94-beba-307aa3e81c54" />

but i think from the packed extension it may be more easy to reproduce it because finding a set k8s environment seems a little bit heavy for debugging this problem.

What is the expected behavior?

no env var pollution

Additional information

_No response_

View original on GitHub ↗

8 Comments

csanz91 · 4 months ago

I have also found this issue in vscode in macos. Its breaking my tests that relies on DEBUG being a bool variable.

connesy · 3 months ago
I have also found this issue in vscode in macos. Its breaking my tests that relies on DEBUG being a bool variable.

I'm seeing the same issue. I have code that relies on the DEBUG variable being a bool, which breaks when running python test discovery.

To reproduce, create a python file test_dummy.py:

import os

assert os.getenv("DEBUG") is None

Then run VSCode test discovery with the Codex extension enabled. This is the resulting log:

==================================== ERRORS ====================================
_____________________ ERROR collecting tests/test_dummy.py _____________________
tests/test_dummy.py:3: in <module>
    assert os.getenv("DEBUG") is None
E   AssertionError: assert 'release' is None

With Codex disabled, DEBUG is not set.

alex29ua · 2 months ago

I'm having the same issue with some Rails app, and Codex was triggering lots of tests to fail. Codex admitted it's his fault, but he can't pinpoint to exact source of this.

sherpya · 2 months ago

I traced the exact source of the DEBUG=release pollution by inspecting the bundled out/extension.js.

The culprit is this code:

function VAe(t) {
    t ? process.env.DEBUG = t : delete "release"
}
function KAe() {
    return "release"
}

This appears to be a bundled/minified version of the popular debug npm library. The original source likely looked something like:

function disable() {
    const namespaces = ...;
    createDebug.enable('');
    namespaces ? process.env.DEBUG = namespaces : delete process.env.DEBUG;
}

During bundling/minification, the build mode constant "release" was inlined in the wrong place: the delete process.env.DEBUG expression became delete "release", which is a no-op in JavaScript (deleting a string literal does nothing). Meanwhile, KAe() always returns the hardcoded string "release".

The result is that at extension initialization, VAe("release") is called → process.env.DEBUG = "release" is set, and the cleanup branch (delete process.env.DEBUG) is permanently broken by the minifier substituting the variable with its constant value.

This DEBUG=release then propagates to all child processes spawned by the extension's sandbox, affecting any framework or tool that reads DEBUG from the environment (Django, Spring Boot, etc.) with unexpected results.

Root cause: minifier/tree-shaker constant folding incorrectly replaced a variable reference with its string value inside a delete expression.

Fix: ensure the delete process.env.DEBUG path is preserved correctly in the bundle, or explicitly unset/delete process.env.DEBUG after the extension initializes the debug library.

alex29ua · 2 months ago

woa! This is a nice investigation here.
I hope it will be fixed though. I'm not sure how these issues get into work, if ever.

sherpya · 2 months ago
woa! This is a nice investigation here. I hope it will be fixed though. I'm not sure how these issues get into work, if ever.

as a workaround you can change:
{t?process.env.DEBUG=t:delete"release"}

with:
{t?process.env.DEBUG=t:delete process.env.DEBUG}

and
{return"release"}

with:
{return process.env.DEBUG}

in out/extension.js

sherpya · 1 month ago

please fix this bug, I've already got multiple updates, I don't want to fix the obfuscated js each update

arvindashtekar · 8 days ago

I can confirm this is still reproducible on Windows with Codex VS Code extension versions 26.623.141536 and 26.707.41301, and it has a concrete downstream impact on Spring Boot applications launched through Gradle.

Observed inheritance chain:

VS Code extension host (DEBUG=release)
  -> Gradle for Java server
    -> Gradle daemon
      -> Spring Boot bootRun JVM

Even with the application root logging level set to INFO, Spring Boot interprets the inherited DEBUG environment variable as its global debug property. The result is framework DEBUG output and the full conditions evaluation report.

I ran a controlled A/B test using the same application source, configuration, database, and Spring Boot 3.5.6 runtime:

  • inherited DEBUG=release: framework DEBUG lines and the conditions evaluation report appeared
  • DEBUG removed immediately before bootRun: application reached Started with 0 DEBUG lines and no conditions evaluation report

This also rules out an application logger being changed later at runtime: the debug output is already active during SpringApplication bootstrap.

The affected extension bundles contain behavior equivalent to:

function save(value) {
  value ? process.env.DEBUG = value : delete "release";
}
function load() {
  return "release";
}

The debug package initialization then enables the value returned by load(), leaving process.env.DEBUG=release in the shared extension host.

Temporary PowerShell workaround:

Remove-Item Env:DEBUG -ErrorAction SilentlyContinue
.\gradlew.bat --stop
.\gradlew.bat :apps:tm-app-single:bootRun --no-daemon

A safe downstream mitigation is to remove case-insensitive DEBUG entries only from each Spring Boot BootRun task's child environment. That avoids changing the developer's global environment or unrelated Gradle tasks.