@@ -287,68 +287,16 @@ pub fn run(sandbox_id: Option<&str>, workspace_id: &str, name: Option<&str>, cmd
287287 eprintln ! ( "{} {}" , "sandbox:" . dark_grey( ) , sid) ;
288288 eprintln ! ( "{} {}" , "workspace:" . dark_grey( ) , workspace_id) ;
289289
290- spawn_child_with_sandbox_env ( & sid, workspace_id, & sandbox_jwt, & sandbox_refresh, & api. api_url , cmd) ;
291- }
292-
293- /// Allow-list of parent environment variables to forward to a
294- /// `sandbox run` child. Anything outside this set is dropped, so the
295- /// child can't accidentally read the user's API key, AWS creds, or any
296- /// other secret the parent shell happens to expose.
297- ///
298- /// Public so the unit test can assert against the exact set.
299- pub ( crate ) const SANDBOX_ENV_ALLOWLIST : & [ & str ] = & [
300- "PATH" ,
301- "HOME" ,
302- "USER" ,
303- "LOGNAME" ,
304- "SHELL" ,
305- "TERM" ,
306- "LANG" ,
307- "LC_ALL" ,
308- "LC_CTYPE" ,
309- "TZ" ,
310- "TMPDIR" ,
311- ] ;
312-
313- /// Names of the auth env vars injected into the child. The CLI reads
314- /// `HOTDATA_SANDBOX_TOKEN` and treats it as the only valid bearer when
315- /// set (see `api::ApiClient::new`). Kept as a constant alongside the
316- /// allow-list so a future audit can compare both at a glance.
317- #[ allow( dead_code) ] // Referenced from the audit test below.
318- pub ( crate ) const SANDBOX_AUTH_ENV : & [ & str ] = & [
319- "HOTDATA_SANDBOX" ,
320- "HOTDATA_WORKSPACE" ,
321- "HOTDATA_API_URL" ,
322- "HOTDATA_SANDBOX_TOKEN" ,
323- "HOTDATA_SANDBOX_REFRESH_TOKEN" ,
324- ] ;
325-
326- fn spawn_child_with_sandbox_env (
327- sandbox_id : & str ,
328- workspace_id : & str ,
329- sandbox_jwt : & str ,
330- sandbox_refresh : & str ,
331- api_url : & str ,
332- cmd : & [ String ] ,
333- ) {
334- let mut command = std:: process:: Command :: new ( & cmd[ 0 ] ) ;
335- command. args ( & cmd[ 1 ..] ) ;
336-
337- // Scrub: start from a clean environment and explicitly re-add
338- // only what the child legitimately needs.
339- command. env_clear ( ) ;
340- for key in SANDBOX_ENV_ALLOWLIST {
341- if let Ok ( val) = std:: env:: var ( key) {
342- command. env ( key, val) ;
343- }
344- }
345- command. env ( "HOTDATA_SANDBOX" , sandbox_id) ;
346- command. env ( "HOTDATA_WORKSPACE" , workspace_id) ;
347- command. env ( "HOTDATA_API_URL" , api_url) ;
348- command. env ( "HOTDATA_SANDBOX_TOKEN" , sandbox_jwt) ;
349- command. env ( "HOTDATA_SANDBOX_REFRESH_TOKEN" , sandbox_refresh) ;
350-
351- match command. status ( ) {
290+ let status = std:: process:: Command :: new ( & cmd[ 0 ] )
291+ . args ( & cmd[ 1 ..] )
292+ . env ( "HOTDATA_SANDBOX" , & sid)
293+ . env ( "HOTDATA_WORKSPACE" , workspace_id)
294+ . env ( "HOTDATA_API_URL" , & api. api_url )
295+ . env ( "HOTDATA_SANDBOX_TOKEN" , & sandbox_jwt)
296+ . env ( "HOTDATA_SANDBOX_REFRESH_TOKEN" , & sandbox_refresh)
297+ . status ( ) ;
298+
299+ match status {
352300 Ok ( s) => std:: process:: exit ( s. code ( ) . unwrap_or ( 1 ) ) ,
353301 Err ( e) => {
354302 eprintln ! ( "error: failed to execute '{}': {e}" , cmd[ 0 ] ) ;
@@ -411,34 +359,4 @@ mod tests {
411359 ) ;
412360 }
413361
414- #[ test]
415- fn sandbox_env_allowlist_excludes_sensitive_parent_state ( ) {
416- // The allowlist must not leak the parent's auth credentials or
417- // the parent's active-sandbox state into a child that's
418- // supposed to be running under the freshly-minted sandbox JWT.
419- let forbidden = [
420- "HOTDATA_API_KEY" ,
421- "AWS_ACCESS_KEY_ID" ,
422- "AWS_SECRET_ACCESS_KEY" ,
423- "OPENAI_API_KEY" ,
424- "GH_TOKEN" ,
425- "GITHUB_TOKEN" ,
426- ] ;
427- for k in forbidden {
428- assert ! (
429- !SANDBOX_ENV_ALLOWLIST . contains( & k) ,
430- "{k} must not be forwarded to sandbox child"
431- ) ;
432- }
433- }
434-
435- #[ test]
436- fn sandbox_auth_env_set_is_self_consistent ( ) {
437- // Anything the parent injects must also be the set the child's
438- // ApiClient knows to read (HOTDATA_SANDBOX_TOKEN in particular).
439- assert ! ( SANDBOX_AUTH_ENV . contains( & "HOTDATA_SANDBOX_TOKEN" ) ) ;
440- assert ! ( SANDBOX_AUTH_ENV . contains( & "HOTDATA_SANDBOX_REFRESH_TOKEN" ) ) ;
441- assert ! ( SANDBOX_AUTH_ENV . contains( & "HOTDATA_SANDBOX" ) ) ;
442- assert ! ( SANDBOX_AUTH_ENV . contains( & "HOTDATA_WORKSPACE" ) ) ;
443- }
444362}
0 commit comments