fix(util): avoid UID/GID wraparound when parsing process credentials#3808
fix(util): avoid UID/GID wraparound when parsing process credentials#3808
Conversation
user.Lookup returns string UIDs. strconv.Atoi followed by uint32() truncates values > MaxUint32 (e.g. 4294967296 becomes 0), which could skip dropping privileges or apply wrong credentials. Use ParseUint with 32-bit width and add tests. Co-authored-by: Denis Gukov <fiftin@outlook.com>
There was a problem hiding this comment.
Security review (automation)
Outcome: No medium, high, or critical vulnerabilities identified in the added or modified code.
What changed: parseLinuxCredentialUint replaces strconv.Atoi + uint32() for passwd-derived UID/GID. The previous pattern could silently wrap values ≥ 2³² to 0 (root) when setting syscall.Credential. The new path uses strconv.ParseUint(s, 10, 32), which rejects out-of-range values and rejects 0, avoiding truncation/wraparound.
Prior threads: Previous automation security-review threads were cleared so this assessment is the active one.
Slack-style summary: PR3808 security pass — no exploitable issues in diff; change closes a credential truncation/wrap risk on Linux process credentials.
Sent by Cursor Automation: Find vulnerabilities


Summary
Fixes incorrect handling of UID/GID strings from
user.Lookupwhen configuring child process credentials.Bug and impact
process.useris set to a Linux account whose UID or GID string is outside theuint32range (for example4294967296), or is otherwise non-numeric.strconv.Atoisucceeds for large values, thenuint32(u)silently truncates (e.g.4294967296→0).GetSysProcAttrthen seesuid <= 0and does not setsyscall.Credential, so git/ansible children may run as the wrong user (no privilege drop). That is a security/correctness failure on systems with unusual UID assignments.Root cause
UID/GID from the password database are strings. Parsing with
strconv.Atoi+uint32()allows wraparound; the removedu <= math.MaxUint32check did not help becauseMaxUint32equalsintmax on typical 64-bit Go, so overflow already happened atAtoifor larger strings.Fix
strconv.ParseUint(s, 10, 32)so values that do not fit in 32 bits are rejected instead of truncated.parseLinuxCredentialUintwith unit tests.Validation
go test ./util/... -short