Skip to content

VNX-276: Incorrect Default Permissions

Detects files and directories given a world-writable mode by a call the umask does not filter: chmod-family calls in C, C++, Python, Go, PHP, JavaScript/TypeScript, Ruby, Java and Rust, chmod/install -m/mkdir -m/COPY --chmod in shell scripts, Makefiles and Dockerfiles, mode: in Ansible tasks, and chmod commands run through system/exec/subprocess.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-276
Severity Medium
SARIF level warning
Kind sast
Languages C, C++, Python, Go, PHP, JavaScript / TypeScript, Ruby, Java, Rust, Shell, Dockerfile, YAML
CWE CWE-276
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 default-permissions world-writable chmod file-permissions cwe-276
Source internal/sast/rules/vnx-276.rego

Overview

VNX-276 maps to CWE-276: Incorrect Default Permissions. When a program or its installer gives what it installs a mode that lets others write, any local user (or any process in the container) can replace the code, configuration or data the program later trusts.

A mode is world-writable when it grants others write: an octal mode ending in 2, 3, 6 or 7 (0777, 0o666, 777), S_IWOTH/S_IRWXO, os.ModePerm, perms::all, or symbolic o+w/a+w/a+rwx. The rule reports such a mode passed to a call that sets permissions directly, bypassing the umask:

Language Calls
C, C++ chmod, fchmod, lchmod, fchmodat, std::filesystem::permissions
Python os.chmod, os.fchmod, Path.chmod
Go os.Chmod, (*os.File).Chmod
PHP chmod(), $fs->chmod()
JavaScript, TypeScript fs.chmod, chmodSync, fchmod, fchmodSync, fs/promises chmod (numeric or string modes)
Ruby File.chmod, FileUtils.chmod, FileUtils.chmod_R, and FileUtils.mkdir/mkdir_p/install with mode: (they chmod after creating, so the umask does not apply)
Java Files.setPosixFilePermissions with rwxrwxrwx or OTHERS_WRITE, File.setWritable(true, false)
Rust fs::Permissions::from_mode, PermissionsExt::set_mode (they feed fs::set_permissions; OpenOptions/DirBuilder .mode() is umask-filtered and not reported)
Ansible mode: '0777', mode: 0666, mode: a+w and mode=0777 in file/copy/template tasks
Shell, Makefile, PKGBUILD, Dockerfile chmod, install -m (also after -o/-g), mkdir -m, COPY --chmod, RUN ["chmod", ...]

A chmod 777-style command run through system, exec, subprocess, exec.Command, Runtime.exec or backticks is reported too, and so is a mode held in a variable that was assigned a world-writable literal a few lines above, or in a constant declared once for the file (const socketMode = 0o777, #define MODE 0777, SOCKET_MODE = 0o777). A call whose arguments run onto the next lines is read to its closing parenthesis, and a mode spelled as a string (octdec('0777'), int("777", 8)) counts.

What Gets Flagged

os.chmod(upload_dir, 0o777)                                   # FLAGGED
os.chmod(config_file, current | stat.S_IWOTH)                 # FLAGGED
subprocess.run(["chmod", "-R", "777", build_dir], check=True) # FLAGGED
chmod($target, 0777);   // FLAGGED
FileUtils.mkdir_p("tmp/uploads", mode: 0o777)   # FLAGGED
fs::set_permissions(sock, fs::Permissions::from_mode(0o777))?;   // FLAGGED
- ansible.builtin.file:
    path: /var/www/uploads
    state: directory
    mode: '0777'                                         # FLAGGED
install:
	chmod 777 $(DESTDIR)/var/lib/app     # FLAGGED
RUN chmod -R 777 /app                       # FLAGGED
COPY --chmod=777 entrypoint.sh /entrypoint.sh   # FLAGGED

What Is Not Flagged

  • Modes passed to creation calls that the umask filters: open(p, O_CREAT, 0666), mkdir(d, 0777), os.makedirs(d, 0o777), os.WriteFile(p, b, 0666), fs.writeFileSync(p, d, { mode: 0o666 }), PHP mkdir($d, 0777, true).
  • Sticky shared directories: chmod 1777 /tmp/shared, a+rwxt.
  • Computed or masked modes: 0777 - umask(), st.st_mode & ~S_IWOTH, fi.Mode() &^ 0o022, 0o777 & ~umask, and a mode variable masked after it is assigned (mode &= ~old_umask;).
  • Group-only or owner-only changes: chmod +x, g+rwX, g=u, u+w, +w (no who: the umask decides).
  • A tree made writable only to be removed: os.chmod(path, 0o777); func(path) in an rmtree onerror handler, or a walk that chmods before os.RemoveAll.
  • Reading permissions: (st.permissions() & fs::perms::others_write) != fs::perms::none.
  • Test code (including test.sh and .bats scripts), comments and log strings.

Not covered: modes held in shell variables, Kotlin and C# APIs, Kubernetes defaultMode, and chmod in YAML CI steps.

Remediation

Give write access to the owner, and to a group if several accounts must write, never to everyone. For a shared drop directory use the sticky bit.

chmod 0755 /var/www/uploads
chmod 0640 /etc/app/app.conf
install -m 0644 app.conf /etc/app/app.conf
chmod 1777 /srv/drop   # shared, but users cannot delete each other's files

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-276
// nosec vnx-276

Or record an ignore rule: vulnetix ignore add --rule vnx-276 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-276.rego, cli/internal/sast/docs/vnx-276.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.