Skip to content

VNX-421: Race Condition During Access to Alternate Channel

Reports a Unix domain socket or FIFO created at a fixed path in a shared world-writable directory (/tmp, /var/tmp, /dev/shm) in C, C++, Go and Python, as a literal, a constant or a C buffer filled by snprintf, and a Windows CreateNamedPipe in a file that never passes FILE_FLAG_FIRST_PIPE_INSTANCE, where another local user can claim the channel's name first.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-421
Severity Low
SARIF level note
Kind sast
Languages C, C++, Go, Python
CWE CWE-421
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags race-during-alternate-channel unix-socket named-pipe cwe-421
Source internal/sast/rules/vnx-421.rego

Overview

VNX-421 maps to CWE-421: Race Condition During Access to Alternate Channel. A service that opens a local side channel for its own clients (a control socket, a FIFO, a named pipe) races every other local user for that channel’s name. If the name lives somewhere anyone can create files, the attacker creates it first: the service fails to bind, or its clients connect to the attacker’s endpoint and hand it their requests.

Reported:

  • C and C++: mkfifo, mkfifoat and mknod, and a sockaddr_un.sun_path filled by strcpy, strncpy, strlcpy, snprintf, memcpy or a designated initializer, with a fixed path under /tmp, /var/tmp or /dev/shm, written as a literal, a #define or a constant.
  • Go: net.Listen/net.ListenPacket("unix", ...), net.UnixAddr{Name: ...}, net.ResolveUnixAddr and syscall.Mkfifo/unix.Mkfifo with such a path, including filepath.Join("/tmp", ...) and filepath.Join(os.TempDir(), ...).
  • Python: os.mkfifo, socket .bind in a file using AF_UNIX, asyncio.start_unix_server/create_unix_server and socketserver.UnixStreamServer/UnixDatagramServer with such a path, including os.path.join(tempfile.gettempdir(), ...).
  • Windows named pipes: CreateNamedPipe, CreateNamedPipeA and CreateNamedPipeW in a file that never passes FILE_FLAG_FIRST_PIPE_INSTANCE.

What Gets Flagged

strncpy(addr.sun_path, "/tmp/backupd.sock", sizeof(addr.sun_path) - 1);   // FLAGGED
const ctlSocket = "/tmp/agent.sock"
ln, err := net.Listen("unix", ctlSocket)   // FLAGGED
server = await asyncio.start_unix_server(handler, path="/tmp/agent-async.sock")   # FLAGGED

What Is Not Flagged

  • Sockets and FIFOs in a directory only the service can write: /run/<service>/, $XDG_RUNTIME_DIR, a mkdtemp() or os.MkdirTemp result.
  • Client-side connects (net.Dial("unix", ...), socket.connect(...)).
  • Paths computed only at run time, test files, comments and string literals that are not passed to these calls.
  • CreateNamedPipe in a file that creates the first instance with FILE_FLAG_FIRST_PIPE_INSTANCE.

Remediation

Create the channel inside a directory the service owns and others cannot write:

mkdir("/run/backupd", 0700);
strncpy(addr.sun_path, "/run/backupd/control.sock", sizeof(addr.sun_path) - 1);

On Windows, create the first pipe instance with FILE_FLAG_FIRST_PIPE_INSTANCE, so the call fails if someone else already owns the name.

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

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

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