77 "log/slog"
88 "os"
99 "os/exec"
10+ "os/user"
1011 "strconv"
1112 "strings"
1213 "syscall"
@@ -84,16 +85,48 @@ func (m *MacOSNetJail) Execute(command []string, extraEnv map[string]string) err
8485 env = append (env , fmt .Sprintf ("%s=%s" , key , value ))
8586 }
8687
88+ // When running under sudo, restore essential user environment variables
89+ if sudoUser := os .Getenv ("SUDO_USER" ); sudoUser != "" {
90+ if user , err := user .Lookup (sudoUser ); err == nil {
91+ // Set HOME to original user's home directory
92+ env = append (env , fmt .Sprintf ("HOME=%s" , user .HomeDir ))
93+ // Set USER to original username
94+ env = append (env , fmt .Sprintf ("USER=%s" , sudoUser ))
95+ // Set LOGNAME to original username (some tools check this instead of USER)
96+ env = append (env , fmt .Sprintf ("LOGNAME=%s" , sudoUser ))
97+ m .logger .Debug ("Restored user environment" , "home" , user .HomeDir , "user" , sudoUser )
98+ }
99+ }
100+
87101 cmd .Env = env
88102 cmd .Stdout = os .Stdout
89103 cmd .Stderr = os .Stderr
90104 cmd .Stdin = os .Stdin
91105
92- // Set group ID using syscall (like httpjail does)
93- cmd .SysProcAttr = & syscall.SysProcAttr {
94- Credential : & syscall.Credential {
95- Gid : uint32 (m .groupID ),
96- },
106+ // Drop privileges to original user if running under sudo
107+ if sudoUID := os .Getenv ("SUDO_UID" ); sudoUID != "" {
108+ if sudoGID := os .Getenv ("SUDO_GID" ); sudoGID != "" {
109+ uid , err := strconv .Atoi (sudoUID )
110+ if err != nil {
111+ m .logger .Warn ("Invalid SUDO_UID, subprocess will run as root" , "sudo_uid" , sudoUID , "error" , err )
112+ } else {
113+ // Use original user ID but KEEP the jail group for network isolation
114+ cmd .SysProcAttr = & syscall.SysProcAttr {
115+ Credential : & syscall.Credential {
116+ Uid : uint32 (uid ),
117+ Gid : uint32 (m .groupID ), // Keep jail group, not original user's group
118+ },
119+ }
120+ m .logger .Debug ("Dropping privileges to original user with jail group" , "uid" , uid , "jail_gid" , m .groupID )
121+ }
122+ }
123+ } else {
124+ // Set group ID using syscall (original behavior for non-sudo)
125+ cmd .SysProcAttr = & syscall.SysProcAttr {
126+ Credential : & syscall.Credential {
127+ Gid : uint32 (m .groupID ),
128+ },
129+ }
97130 }
98131
99132 // Start and wait for command to complete
@@ -334,4 +367,4 @@ func (m *MacOSNetJail) cleanupTempFiles() {
334367 if m .mainRulesPath != "" {
335368 os .Remove (m .mainRulesPath )
336369 }
337- }
370+ }
0 commit comments