VNX-243: Creation of chroot Jail Without Changing Working Directory
A chroot() call (C/C++, Python os.chroot, Go syscall/unix.Chroot, Rust fs::chroot, Ruby Dir.chroot) is not followed in the same function by a chdir, so the working directory stays outside the jail.
| Field | Value |
|---|---|
| Rule ID | VNX-243 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Go, Python, Ruby, Rust |
| CWE | CWE-243 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | chroot cwe-243 sandbox |
| Source | internal/sast/rules/vnx-243.rego |
Overview
VNX-243 maps to CWE-243: Creation of chroot Jail Without Changing Working Directory. It reports a chroot call that is not followed, in the same function and within 20 lines, by a change of working directory: C/C++ chroot(), Python os.chroot() (or chroot imported from os), Go syscall.Chroot()/unix.Chroot(), Rust fs::chroot()/nix::unistd::chroot() and Ruby Dir.chroot(), with no chdir()/fchdir(), os.chdir(), os.Chdir(), std::env::set_current_dir() or Dir.chdir after it.
Why This Matters
chroot() changes what / means but not the current directory. A process whose working directory is still outside the new root can open ../../etc/shadow and leave the jail with relative paths.
Not reported: a chdir after the chroot, the chdir(dir); chroot(".") idiom and chdir(dir); chroot(dir) with the same argument, method calls and wrappers (o->chroot(), my_chroot()), prototypes, comments and string literals. A chdir before the chroot to a different directory does not count, nor does a chdir after it to a relative literal path (chdir("work") moves relative to the old directory, which is still outside the jail). A Go SysProcAttr Chroot field for a child process is not judged.
What Gets Flagged
if (chroot(dir) != 0) {
perror("chroot");
return -1;
}
setuid(65534);
os.chroot(jail)
os.setuid(65534)
Remediation
if (chroot(dir) != 0 || chdir("/") != 0)
return -1;
if err := unix.Chroot(dir); err != nil {
return err
}
return os.Chdir("/")
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-243
// nosec vnx-243
Or record an ignore rule: vulnetix ignore add --rule vnx-243 --reason "...". See Suppressing findings.