Skip to content

VNX-66: Improper Handling of File Names that Identify Virtual Resources

An uploaded file is stored under the name the client sent, so a name such as CON, NUL, AUX, COM1 or LPT1 opens a Windows device instead of a file. Stripping directories with basename or GetFileName does not prevent it.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-66
Severity Medium
SARIF level warning
Kind sast
Languages C#, Go, Java, Python
CWE CWE-66
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 filename virtual-resource windows upload cwe-66
Source internal/sast/rules/vnx-66.rego

Overview

VNX-66 maps to CWE-66: Improper Handling of File Names that Identify Virtual Resources. It reports a client-supplied upload file name used as the on-disk file name, on the write line or through a variable assigned from it in the 15 lines above.

Why This Matters

On Windows, CON, PRN, AUX, NUL, COM1-COM9 and LPT1-LPT9 name devices in every directory, with or without an extension. An upload called aux.png or con.txt does not create a file: the write blocks the worker, vanishes into NUL, or goes to a serial port. Path.GetFileName, basename and FilenameUtils.getName remove directories but leave the device name intact.

What Gets Flagged

f = request.files["document"]
f.save(os.path.join(UPLOAD_DIR, f.filename))
file.transferTo(new File(dir, file.getOriginalFilename()));
var path = Path.Combine(_env.WebRootPath, "uploads", file.FileName);

string filename = Path.GetFileName(FileUpload1.FileName);
FileUpload1.SaveAs(Server.MapPath("~/uploads/") + filename);
dst, err := os.Create(filepath.Join("uploads", header.Filename))

Not flagged: a name passed through secure_filename or a sanitize function, a generated name on the write line (UUID, GUID, GetRandomFileName, a hash or timestamp), a project that checks names against the reserved device list, a name that is only logged or stored as data, and test code.

Remediation

  1. Store uploads under a generated name (a UUID plus a validated extension) and keep the original name as metadata.
  2. If the original name must be used, run it through werkzeug.utils.secure_filename or an equivalent that rejects reserved device names, and reject names whose stem is CON, PRN, AUX, NUL, COM1-COM9 or LPT1-LPT9.

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

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

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