{"id":"CVE-2026-128079","kind":"vulnerability","aliases":["CVE-2026-128079","GHSA-jv6m-48w5-5rpr"],"related":[],"title":"envd: Host file disclosure through requirements path traversal and TOCTOU","description":"### Summary\n\nenvd’s `install.python_packages(requirements=...)` could read files outside the build context on the host. Content interpreted as dependency entries could appear in build logs and build-step metadata.\n\nCommit f576c92, released in v1.3.5, added path containment validation but left a time-of-check/time-of-use (TOCTOU) race between symlink resolution and opening the requirements file. Commit 9d575b3 addresses this race by opening requirements files through a directory-rooted filesystem handle.\n\n### Details\n\nenvd reads requirements files on the host to determine whether their contents can be embedded directly into a pip installation build step.\n\nThe vulnerable host-side requirements read was introduced in v0.3.38. Version v1.3.5 added containment checks for static path escapes but remained vulnerable to a TOCTOU race. The complete fix is included in v1.3.6.\n\nBefore f576c92, this host read lacked a build-context containment check. That commit added frontend path validation and a compile-time check using filepath.EvalSymlinks followed by a containment comparison.\n\nHowever, symlink resolution returns a pathname rather than a pinned filesystem object. The subsequent os.Open independently resolves that pathname. Concurrent filesystem changes could therefore invalidate the containment check before the file was opened.\n\nThe complete fix uses os.OpenRoot and Root.Open to enforce containment during filesystem traversal.\n\nResources:\n- first commit: be783264fdd79ad7262cea0485b7d449ca514f80\n- Initial containment fix: f576c92\n- TOCTOU fix: 9d575b3\n\n### Proof of concept\n\nThe security-relevant condition is a requirements-file pathname whose filesystem resolution changes between validation and opening. The containment check describes the filesystem at validation time, while the later pathname-based open may access a different object.\n\nThe fix includes a deterministic regression test for the underlying object-pinning guarantee. It opens a context directory handle, moves that directory, and creates a replacement directory at the original pathname containing different requirements. The rooted reader continues reading the original context; a pathname-based reader reads the replacement.\n\nThis regression test demonstrates the distinction between rooted and pathname-based reads. It is not an end-to-end demonstration of host file disclosure.\n\n### Impact\n\nAn attacker who can influence the build input—and, for the residual race in v1.3.5, concurrently modify the relevant filesystem paths—may cause envd to read files outside the intended build context, subject to the permissions of the envd process.\n\nDepending on the file contents and requirements parsing, information may be exposed through dependency debug logs and build-step metadata. This issue does not establish arbitrary code execution or unrestricted disclosure of every file.\n\nv1.3.5 remains affected by the TOCTOU variant. Earlier versions containing the host requirements-reading behavior are affected by the original containment issue; confirm the earliest affected release before setting the advisory’s version range.\n\nPatched version: v1.3.6.","summary":"envd reads requirements files on the host during builds, and a path traversal plus a race between symlink check and file open lets a build input read files outside its build context. Contents interpreted as dependency entries can appear in build logs and build-step metadata.","severity":"medium","cvss":6.8,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"envd","fixed":["1.3.6"],"affected":">= 0.3.38, < 1.3.6","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["cwe-22","cwe-367","envd","package","python","sandbox-builds"],"not_affected_if":["no-untrusted-build-input","not-using-python-packages-requirements"],"how_to_check":"- Check the installed version with `pip show envd` and compare it to the affected range (>= 0.3.38, < 1.3.6).\n- Look for `install.python_packages(requirements=...)` calls in build definitions that take paths from untrusted input.","fix":"- `envd` `1.3.6` (fixed version per the product data; v1.3.5 is still affected by the TOCTOU variant)","status":"open","published_at":"2026-11-13T18:05:15+00:00","first_seen_at":"2026-11-13T18:07:02+00:00","triaged_at":"2026-11-13T18:07:24+00:00","updated_at":"2026-11-13T18:49:29+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-13T18:07:24Z","model":"claude-haiku-5-5","output":{"fix":"- `envd` `1.3.6` (fixed version per the product data; v1.3.5 is still affected by the TOCTOU variant)","reach":"local","title":"envd: requirements path traversal lets builds read host files","impact":"medium","summary":"envd reads requirements files on the host during builds, and a path traversal plus a race between symlink check and file open lets a build input read files outside its build context. Contents interpreted as dependency entries can appear in build logs and build-step metadata.","audience":"developers","category":"package","nicknames":[],"who_cares":["python","envd","sandbox-builds"],"confidence":0.8,"fix_status":"available","needs_auth":"unknown","worst_case":"envd reads host files and leaks contents into build logs","analyst_note":"","how_to_check":"- Check the installed version with `pip show envd` and compare it to the affected range (>= 0.3.38, < 1.3.6).\n- Look for `install.python_packages(requirements=...)` calls in build definitions that take paths from untrusted input.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-untrusted-build-input","not-using-python-packages-requirements"],"who_is_affected":"Teams that use envd to build sandboxes and pass requirements file paths into install.python_packages, especially where the build input can be influenced by someone outside the team. The risk depends on the envd process having read access to the files, and the advisory notes the race needs concurrent filesystem changes. Teams that do not use the Python package install helper with requirements paths can likely skip it.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.00084,"input_tokens":5577,"output_tokens":565,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-128079':13A,21A '-2026':12A,20A '-22':24B '-367':26B '/time-of-use':127C '48w5':17A '5rpr':18A '9d575b3':139C,298C 'access':338C 'add':116C,190C,225C 'address':140C 'advisori':526C 'affect':497C,512C,521C 'appear':71B,102C 'arbitrari':486C 'attack':421C 'base':335C,388C,404C 'be783264fdd79ad7262cea0485b7d449ca514f80':291C 'behavior':510C 'build':32B,41B,57B,63B,73B,77B,91C,104C,108C,175C,219C,426C,450C,478C 'build-context':218C 'build-step':76B,107C,477C 'caus':442C 'chang':263C,316C 'check':51B,126C,192C,222C,234C,269C,323C 'code':487C 'commit':111C,138C,224C,290C 'comparison':241C 'compil':232C 'compile-tim':231C 'complet':205C,276C 'concept':301C 'concurr':261C,435C 'condit':306C 'confirm':518C 'contain':118C,191C,221C,240C,268C,284C,293C,322C,374C,504C,516C 'content':65B,96C,166C,464C 'context':64B,92C,220C,359C,384C,451C 'continu':380C 'could':86C,101C,264C 'creat':366C 'cve':11A,19A 'cwe':23B,25B 'debug':474C 'demonstr':396C,414C 'depend':68B,99C,460C,473C 'describ':324C 'detail':154C 'determin':163C 'determinist':346C 'differ':340C,375C 'direct':170C 'directori':150C,360C,364C,369C 'directory-root':149C 'disclosur':4A,418C,491C 'distinct':398C 'earlier':502C 'earliest':520C 'embed':169C 'end':411C,413C 'end-to-end':410C 'enforc':283C 'entri':69B,100C 'envd':1A,22A,27B,33B,81C,155C,443C,458C 'escap':196C 'establish':485C 'everi':493C 'execut':488C 'expos':471C 'f576c92':112C,212C,295C 'file':3A,36B,53B,60B,88C,137C,146C,158C,272C,311C,417C,446C,463C,494C 'filepath.evalsymlinks':236C 'filesystem':152C,252C,262C,286C,314C,326C,439C 'first':289C 'fix':206C,277C,294C,297C,343C 'follow':237C 'frontend':226C 'ghsa':15A 'ghsa-jv6m-48w5-5rpr':14A 'guarante':355C 'handl':153C,361C 'host':2A,39B,95C,161C,180C,214C,416C,506C 'host-sid':179C 'howev':242C 'impact':419C 'includ':208C,344C 'independ':257C 'influenc':424C 'inform':468C 'initi':292C 'input':58B,427C 'instal':174C 'install.python':83C 'intend':449C 'interpret':66B,97C 'introduc':185C 'invalid':266C 'issu':482C,517C 'jv6m':16A 'lack':216C 'later':332C 'left':121C 'let':55B 'log':74B,105C,475C 'may':337C,441C,469C 'metadata':79B,110C,480C 'modifi':436C 'move':362C 'object':253C,341C,353C 'object-pin':352C 'open':54B,134C,144C,274C,320C,336C,357C 'origin':372C,383C,515C 'os.open':256C 'os.openroot':279C 'outsid':61B,89C,447C 'packag':28B,84C 'pars':467C 'patch':530C 'path':7A,44B,117C,195C,227C,440C 'pathnam':247C,260C,312C,334C,373C,387C,403C 'pathname-bas':333C,386C,402C 'permiss':455C 'pin':251C,354C 'pip':173C 'plus':46B 'process':459C 'proof':299C 'python':29B 'race':48B,129C,142C,203C,432C 'rang':529C 'rather':248C 'read':34B,59B,87C,156C,183C,215C,381C,390C,405C,445C,509C 'reader':379C,389C 'regress':347C,394C 'releas':113C,522C 'relev':305C,438C 'remain':198C,496C 'replac':368C,392C 'requir':6A,35B,85C,136C,145C,157C,182C,310C,376C,466C,508C 'requirements-fil':309C 'requirements-read':507C 'residu':431C 'resolut':132C,244C,315C 'resolv':258C 'resourc':288C 'return':245C 'root':151C,378C,400C 'root.open':281C 'sandbox':31B 'sandbox-build':30B 'secur':304C 'security-relev':303C 'set':524C 'side':181C 'static':194C 'step':78B,109C,176C,479C 'subject':452C 'subsequ':255C 'summari':80C 'symlink':50B,131C,243C 'test':348C,395C 'therefor':265C 'time':124C,233C,329C 'time-of-check':123C 'toctou':10A,128C,202C,296C,500C 'travers':8A,45B,287C 'under':351C 'unrestrict':490C 'use':235C,278C 'v0.3.38':187C 'v1.3.5':115C,189C,434C,495C 'v1.3.6':210C,532C 'valid':119C,228C,318C,328C 'variant':501C 'version':188C,503C,528C,531C 'vulner':178C,199C 'whether':164C 'whose':313C","nicknames":[],"mitigations":[],"who_affected":"Teams that use envd to build sandboxes and pass requirements file paths into install.python_packages, especially where the build input can be influenced by someone outside the team. The risk depends on the envd process having read access to the files, and the advisory notes the race needs concurrent filesystem changes. Teams that do not use the Python package install helper with requirements paths can likely skip it.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["envd"],"ptokens":["envd"],"labels":["cwe22","cwe367","envd","medium","package","pypi","python","sandboxbuilds"],"campaign_type":null,"search_a":"'-128079':13A,21A '-2026':12A,20A '48w5':17A '5rpr':18A 'cve':11A,19A 'disclosur':4A 'envd':1A,22A 'file':3A 'ghsa':15A 'ghsa-jv6m-48w5-5rpr':14A 'host':2A 'jv6m':16A 'path':7A 'requir':6A 'toctou':10A 'travers':8A","search_b":"'-22':24B '-367':26B 'appear':71B 'build':32B,41B,57B,63B,73B,77B 'build-step':76B 'check':51B 'content':65B 'context':64B 'cwe':23B,25B 'depend':68B 'entri':69B 'envd':27B,33B 'file':36B,53B,60B 'host':39B 'input':58B 'interpret':66B 'let':55B 'log':74B 'metadata':79B 'open':54B 'outsid':61B 'packag':28B 'path':44B 'plus':46B 'python':29B 'race':48B 'read':34B,59B 'requir':35B 'sandbox':31B 'sandbox-build':30B 'step':78B 'symlink':50B 'travers':45B","search_c":"'/time-of-use':127C '9d575b3':139C,298C 'access':338C 'add':116C,190C,225C 'address':140C 'advisori':526C 'affect':497C,512C,521C 'appear':102C 'arbitrari':486C 'attack':421C 'base':335C,388C,404C 'be783264fdd79ad7262cea0485b7d449ca514f80':291C 'behavior':510C 'build':91C,104C,108C,175C,219C,426C,450C,478C 'build-context':218C 'build-step':107C,477C 'caus':442C 'chang':263C,316C 'check':126C,192C,222C,234C,269C,323C 'code':487C 'commit':111C,138C,224C,290C 'comparison':241C 'compil':232C 'compile-tim':231C 'complet':205C,276C 'concept':301C 'concurr':261C,435C 'condit':306C 'confirm':518C 'contain':118C,191C,221C,240C,268C,284C,293C,322C,374C,504C,516C 'content':96C,166C,464C 'context':92C,220C,359C,384C,451C 'continu':380C 'could':86C,101C,264C 'creat':366C 'debug':474C 'demonstr':396C,414C 'depend':99C,460C,473C 'describ':324C 'detail':154C 'determin':163C 'determinist':346C 'differ':340C,375C 'direct':170C 'directori':150C,360C,364C,369C 'directory-root':149C 'disclosur':418C,491C 'distinct':398C 'earlier':502C 'earliest':520C 'embed':169C 'end':411C,413C 'end-to-end':410C 'enforc':283C 'entri':100C 'envd':81C,155C,443C,458C 'escap':196C 'establish':485C 'everi':493C 'execut':488C 'expos':471C 'f576c92':112C,212C,295C 'file':88C,137C,146C,158C,272C,311C,417C,446C,463C,494C 'filepath.evalsymlinks':236C 'filesystem':152C,252C,262C,286C,314C,326C,439C 'first':289C 'fix':206C,277C,294C,297C,343C 'follow':237C 'frontend':226C 'guarante':355C 'handl':153C,361C 'host':95C,161C,180C,214C,416C,506C 'host-sid':179C 'howev':242C 'impact':419C 'includ':208C,344C 'independ':257C 'influenc':424C 'inform':468C 'initi':292C 'input':427C 'instal':174C 'install.python':83C 'intend':449C 'interpret':97C 'introduc':185C 'invalid':266C 'issu':482C,517C 'lack':216C 'later':332C 'left':121C 'log':105C,475C 'may':337C,441C,469C 'metadata':110C,480C 'modifi':436C 'move':362C 'object':253C,341C,353C 'object-pin':352C 'open':134C,144C,274C,320C,336C,357C 'origin':372C,383C,515C 'os.open':256C 'os.openroot':279C 'outsid':89C,447C 'packag':84C 'pars':467C 'patch':530C 'path':117C,195C,227C,440C 'pathnam':247C,260C,312C,334C,373C,387C,403C 'pathname-bas':333C,386C,402C 'permiss':455C 'pin':251C,354C 'pip':173C 'process':459C 'proof':299C 'race':129C,142C,203C,432C 'rang':529C 'rather':248C 'read':87C,156C,183C,215C,381C,390C,405C,445C,509C 'reader':379C,389C 'regress':347C,394C 'releas':113C,522C 'relev':305C,438C 'remain':198C,496C 'replac':368C,392C 'requir':85C,136C,145C,157C,182C,310C,376C,466C,508C 'requirements-fil':309C 'requirements-read':507C 'residu':431C 'resolut':132C,244C,315C 'resolv':258C 'resourc':288C 'return':245C 'root':151C,378C,400C 'root.open':281C 'secur':304C 'security-relev':303C 'set':524C 'side':181C 'static':194C 'step':109C,176C,479C 'subject':452C 'subsequ':255C 'summari':80C 'symlink':131C,243C 'test':348C,395C 'therefor':265C 'time':124C,233C,329C 'time-of-check':123C 'toctou':128C,202C,296C,500C 'travers':287C 'under':351C 'unrestrict':490C 'use':235C,278C 'v0.3.38':187C 'v1.3.5':115C,189C,434C,495C 'v1.3.6':210C,532C 'valid':119C,228C,318C,328C 'variant':501C 'version':188C,503C,528C,531C 'vulner':178C,199C 'whether':164C 'whose':313C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-10-17T05:27:15+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-jv6m-48w5-5rpr","url":"https://github.com/advisories/GHSA-jv6m-48w5-5rpr","severity":"medium","published_at":"2026-11-13T18:05:15+00:00","modified_at":"2026-11-13T18:05:16+00:00","first_seen_at":"2026-11-13T18:07:02+00:00","fetched_at":"2026-11-13T18:13:46+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-128079","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-128079","severity":null,"published_at":"2026-11-13T18:17:37+00:00","modified_at":"2026-11-13T18:17:37+00:00","first_seen_at":"2026-11-13T18:49:29+00:00","fetched_at":"2026-11-13T18:49:32+00:00","note":null}],"documents":[{"id":148199,"url":"https://api.github.com/repos/tensorchord/envd/security-advisories/GHSA-jv6m-48w5-5rpr","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":148200,"url":"https://github.com/tensorchord/envd/security/advisories/GHSA-jv6m-48w5-5rpr","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":"2026-10-17T05:27:15+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":148201,"url":"https://github.com/tensorchord/envd/pull/2112","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148202,"url":"https://github.com/tensorchord/envd/pull/2119","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148203,"url":"https://github.com/tensorchord/envd/commit/9d575b354ce17a02ef9698b6ff0d5d14296c5734","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148204,"url":"https://github.com/tensorchord/envd/commit/f576c92c1e6dcb9b00b60995534aeb2a83b0b407","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148205,"url":"https://github.com/tensorchord/envd/releases/tag/v1.3.6","title":"Release: github.com","kind":"release","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}