fix(gpu): forward -e env and --project on governed Forge/Modal runs - #652
Open
jqueguiner wants to merge 1 commit into
Open
fix(gpu): forward -e env and --project on governed Forge/Modal runs#652jqueguiner wants to merge 1 commit into
jqueguiner wants to merge 1 commit into
Conversation
`openrunner gpu run --provider forge -e KEY=VALUE app.py` silently dropped the environment: run_engine_serverside_sync() took no env at all, so an App whose local_entrypoint read os.environ["OPENRUNNER_API_KEY"] died with KeyError on the governed path while the same command with a client-side FORGE_TOKEN worked. --project was accepted and ignored the same way. Plumb env end-to-end (CLI -> SDK runner -> API /gpu/engine/run -> executor) and pass --project along as OPENRUNNER_PROJECT for run attribution. Caller env is untrusted, so: - the API validates it (POSIX name syntax, 64 vars, 8 KiB per value, no NUL) and rejects reserved names (engine tokens, EXECUTOR_SECRET, loader and interpreter hooks such as LD_PRELOAD/PYTHONPATH/PATH/BASH_ENV); - the executor merges it *under* the org's credentials, so it can never swap the engine token or aim the engine client at another control plane, and it drops EXECUTOR_SECRET from the child environment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
openrunner gpu run --provider forge -e KEY=VALUE app.pysilently drops the environment.run_engine_serverside_sync()takes noenvparameter, so nothing the caller passes with-ereaches the engine client. An App whoselocal_entrypointreads the environment dies immediately:The same command with a client-side
FORGE_TOKENworks —run_forge_sync()does forwardenv=env_dict. So the governed path, which the docs recommend, is the one that breaks, and it fails with no hint that-ewas ignored.--projecthad the same shape of bug: accepted by the function signature, never used.Fix
Plumb
envend-to-end: CLI →run_engine_serverside_sync→engine_run_stream→POST /gpu/engine/run→ engine-executor → the engine-client subprocess.--projectis passed along asOPENRUNNER_PROJECT(an explicit-e OPENRUNNER_PROJECT=...still wins).Security
Caller env is untrusted input that ends up next to a decrypted org credential, so it is constrained on both sides:
FORGE_TOKEN,FORGE_API_URL,MODAL_TOKEN_*),EXECUTOR_SECRET, and loader/interpreter hooks (LD_PRELOAD,LD_LIBRARY_PATH,LD_AUDIT,PATH,PYTHONPATH,PYTHONSTARTUP,PYTHONHOME,BASH_ENV,ENV,IFS). Denial is case-insensitive.spec["env"](creds), so credentials always win even if validation is ever bypassed, and dropsEXECUTOR_SECRETfrom the child environment.FORGE_API_URLmatters most here: without the deny + ordering, a caller could point the forge client at their own control plane and capture the org's token — the exact thing the governed path exists to prevent.Tests
sdk/tests/test_gpu/test_engine_serverside.py— env + project forwarded, explicitOPENRUNNER_PROJECTwins, empty env when none given.src/api/tests/test_gpu_engine_env.py(new, 21 cases) — happy path, every reserved name, bad names, limits, NUL.