VNX-420: Unprotected Alternate Channel
Reports a side channel left open while the main channel is protected: a Unix control socket made world-writable (chmod to a mode with the other-write bit, or umask(0) before bind with no chmod after) in C, C++, Go and Python, and a Go plaintext http.ListenAndServe on a network address running at the same time as a TLS listener (one of them in a goroutine) that does not only redirect to HTTPS.
| Field | Value |
|---|---|
| Rule ID | VNX-420 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Go, Python |
| CWE | CWE-420 |
| 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 | unprotected-alternate-channel unix-socket cwe-420 |
| Source | internal/sast/rules/vnx-420.rego |
Overview
VNX-420 maps to CWE-420: Unprotected Alternate Channel. A service that authenticates its network clients often also accepts commands on a local control socket, or keeps a plaintext port open beside its TLS one. If that second channel is open to anyone, the protection on the first is bypassed.
Reported:
- World-writable Unix control socket (C, C++, Go, Python): in a file that creates a Unix domain socket (
AF_UNIX/AF_LOCALwithbind,net.Listen("unix", ...),socket.AF_UNIX,start_unix_server), achmod/os.Chmod/os.chmodwhose mode grants other users write (0777,0666,0o666,S_IWOTH,S_IRWXO,ACCESSPERMS,os.ModePerm), or aumask(0)when the file never chmods the socket afterwards. - Go plaintext listener beside TLS:
http.ListenAndServeon a non-loopback address in a file that also callsListenAndServeTLSorServeTLS, where one of the two runs in a goroutine so both serve at once, unless the plaintext handler only redirects to HTTPS. A plaintext call on one branch of a TLS-or-plaintext configuration choice is not reported.
What Gets Flagged
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
return -1;
chmod(path, 0777); // FLAGGED
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind(SOCK)
os.chmod(SOCK, 0o666) # FLAGGED
go http.ListenAndServe(":8080", mux) // FLAGGED
log.Fatal(http.ListenAndServeTLS(":8443", crt, key, mux))
What Is Not Flagged
- Modes without the other-write bit (
0755,0660,0600,0700). - chmod in files that do not create a Unix socket.
- A plaintext listener that only redirects (
http.Redirect, aredirect*handler, autocertHTTPHandler), or one bound to loopback. - Test files and comments.
Remediation
Restrict the socket to its owner or a dedicated group and check the peer’s credentials on connect:
chmod(path, 0660);
/* getsockopt(client, SOL_SOCKET, SO_PEERCRED, &cred, &len) */
Make the plaintext port redirect only:
go http.ListenAndServe(":80", http.HandlerFunc(redirectToHTTPS))
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-420
// nosec vnx-420
Or record an ignore rule: vulnetix ignore add --rule vnx-420 --reason "...". See Suppressing findings.