Repository navigation
Conversation
… the daemon's whole one
…n agent token can do
Contributor
Author
Review (maintainer's agent, round 1)No blocking findings.
Notes, no change needed:
|
V3RON
added this pull request to stack #897
October 23, 2026 06:19
This was referenced Oct 23, 2026
This branch has not been deployed
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.
Summary
device.exec(HTTPPOST /v1/leases/{id}/exec, also through a gateway) lets any agent token run host tools such asxcrun simctl spawnas the daemon's user. That part is by design. Two things were not:execEnv: process.env), so any secret in it (CI tokens, cloud keys, launchd-injected values) was readable by every lease holder.Now the child starts from a short allowlist of the daemon's variables, plus the driver's own
env, minus itsunsetEnv(that layering is unchanged). The website says plainly what an agent token can do.Changes
src/daemon/exec-env.tsexecBaseEnvironment(env)keepsPATH,HOME,TMPDIR,USER,LOGNAME,SHELL,LANG, everyLC_*,TERM,DEVELOPER_DIR,ANDROID_HOME,ANDROID_SDK_ROOT,ANDROID_USER_HOME,ANDROID_AVD_HOME,ANDROID_PREFS_ROOT,ANDROID_SDK_HOME,JAVA_HOME, and drops everything else.main.tspassesexecBaseEnvironment(process.env)as the dispatcher'sexecEnv. The daemon's own driver calls are unchanged.unsetEnvcomment indispatcher.tsand thePassthroughCommandcomment insrc/core/driver.tsno longer say the base is the daemon's whole environment.using-devices/remote-agents.mdx"Running commands with exec" gets a paragraph: commands run on the worker as the daemon's user, an agent token is like shell access, agents that must not see each other's work belong on separate workers, and the list of variables a command gets.gateway/access-control.mdxadds thesimctl spawn/ shell-access sentence and points to that list.src/daemon/AGENTS.mdgets theexec-env.tsrow and a Security model bullet (a few lines re-wrapped to stay within the 150-line budget).docs/internal/flows/device-exec.mdstep 5 and its known gap now describe the allowlist.Tests
src/daemon/exec-env.test.ts(new): one table. Kept keys includeLC_CTYPEandLC_ALL. Dropped keys includeAWS_SECRET_ACCESS_KEY,GITHUB_TOKEN,NPM_TOKEN,SIMLOCK_HOME,ANDROID_SERIAL,SIMCTL_CHILD_*, and look-alikesLCX/XLC_CTYPE. Before the code existed it failed on thetoEqual.src/daemon/main.test.ts: a newstartDaemontest plantsAWS_SECRET_ACCESS_KEYandLC_CTYPEinprocess.env, leases through a fake driver, and runsdevice.execwith a scripted runner. The child's env hasLC_CTYPE, the daemon'sPATH, and the driver'sSIMLOCK_SCOPED, and lacks the secret. Before the wiring it failed onnot.toHaveProperty("AWS_SECRET_ACCESS_KEY").env/unsetEnvlayering. The dispatcher did not change there.pnpm test:changed(green on the second run; the first run had one failure insrc/cli/index.test.ts"fails at the 20 s deadline … (simlock daemon install and uninstall a LaunchAgent on macOS, and starts go through it #830)", a CLI service-start test with no path to this change, which passed alone twice and in the full second run),pnpm test:e2e e2e/device-exec.test.ts(3 passed; the real child still findsnodeonPATH), and the website build pluscheck-openapi(ok).Assumptions
main.ts), as the brief says. So the test that proves a planted secret is gone goes throughstartDaemoninmain.test.ts, not through theDispatcheralone. A test that only uses the dispatcher injects its ownexecEnv, so it cannot see the filter.adbby absolute path andxcrunthroughPATH, and setANDROID_ADB_SERVER_PORTthemselves.simctlanddevicectlneed onlyDEVELOPER_DIR. Keys likeADB_VENDOR_KEYSandANDROID_EMULATOR_HOMEare read by the adb server or the emulator, which the daemon starts with its own environment, so they are left out.Written by an agent.