Skip to content

Commit 4d50f36

Browse files
blink-so[bot]f0ssel
andcommitted
fix: drop privileges to original user when running with sudo
When jail is executed with sudo, the subprocess now runs as the original user instead of root. This is a minimal implementation that only handles privilege dropping without environment manipulation. Changes: - Linux: Check SUDO_UID/SUDO_GID and use syscall.Credential to drop privileges - macOS: Same privilege dropping logic, preserve original group behavior for non-sudo - Added proper error handling and debug logging Now 'sudo jail -- whoami' returns the original username instead of 'root'. Co-authored-by: f0ssel <[email protected]>
1 parent 31f1722 commit 4d50f36

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

network/linux.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log/slog"
88
"os"
99
"os/exec"
10+
"strconv"
1011
"syscall"
1112
"time"
1213
)
@@ -102,6 +103,29 @@ func (l *LinuxJail) Execute(command []string, extraEnv map[string]string) error
102103
cmd.Stdout = os.Stdout
103104
cmd.Stderr = os.Stderr
104105

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+
l.logger.Warn("Invalid SUDO_UID, subprocess will run as root", "sudo_uid", sudoUID, "error", err)
112+
} else {
113+
gid, err := strconv.Atoi(sudoGID)
114+
if err != nil {
115+
l.logger.Warn("Invalid SUDO_GID, subprocess will run as root", "sudo_gid", sudoGID, "error", err)
116+
} else {
117+
cmd.SysProcAttr = &syscall.SysProcAttr{
118+
Credential: &syscall.Credential{
119+
Uid: uint32(uid),
120+
Gid: uint32(gid),
121+
},
122+
}
123+
l.logger.Debug("Dropping privileges to original user", "uid", uid, "gid", gid)
124+
}
125+
}
126+
}
127+
}
128+
105129
// Start command
106130
l.logger.Debug("Starting command", "path", cmd.Path, "args", cmd.Args)
107131
err := cmd.Start()

network/macos.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,34 @@ func (m *MacOSNetJail) Execute(command []string, extraEnv map[string]string) err
8989
cmd.Stderr = os.Stderr
9090
cmd.Stdin = os.Stdin
9191

92-
// Set group ID using syscall (like httpjail does)
93-
cmd.SysProcAttr = &syscall.SysProcAttr{
94-
Credential: &syscall.Credential{
95-
Gid: uint32(m.groupID),
96-
},
92+
// Drop privileges to original user if running under sudo
93+
if sudoUID := os.Getenv("SUDO_UID"); sudoUID != "" {
94+
if sudoGID := os.Getenv("SUDO_GID"); sudoGID != "" {
95+
uid, err := strconv.Atoi(sudoUID)
96+
if err != nil {
97+
m.logger.Warn("Invalid SUDO_UID, subprocess will run as root", "sudo_uid", sudoUID, "error", err)
98+
} else {
99+
gid, err := strconv.Atoi(sudoGID)
100+
if err != nil {
101+
m.logger.Warn("Invalid SUDO_GID, subprocess will run as root", "sudo_gid", sudoGID, "error", err)
102+
} else {
103+
cmd.SysProcAttr = &syscall.SysProcAttr{
104+
Credential: &syscall.Credential{
105+
Uid: uint32(uid),
106+
Gid: uint32(gid),
107+
},
108+
}
109+
m.logger.Debug("Dropping privileges to original user", "uid", uid, "gid", gid)
110+
}
111+
}
112+
}
113+
} else {
114+
// Set group ID using syscall (original behavior for non-sudo)
115+
cmd.SysProcAttr = &syscall.SysProcAttr{
116+
Credential: &syscall.Credential{
117+
Gid: uint32(m.groupID),
118+
},
119+
}
97120
}
98121

99122
// Start and wait for command to complete
@@ -334,4 +357,4 @@ func (m *MacOSNetJail) cleanupTempFiles() {
334357
if m.mainRulesPath != "" {
335358
os.Remove(m.mainRulesPath)
336359
}
337-
}
360+
}

0 commit comments

Comments
 (0)