Summary
When a scan's target.ports contains a large range, openvasd expands that range into an explicit, per-port comma-separated list when building the openvas port_range preference, instead of keeping it compact (start-end). For a full TCP scan (1-65535) the resulting string is ~380 KB. nmap.nasl passes that whole string to nmap as a single -p <port_range> argument, which exceeds the Linux kernel's per-argument limit (MAX_ARG_STRLEN, 128 KB), so execve fails with E2BIG:
nasl_pread: Failed to execute child process "nmap" (Argument list too long)
The port scan therefore never runs. The scan completes "successfully" but reports zero open ports for every host — only host-level results (OS detection, ICMP, traceroute). No service detection, no service-based VTs, no findings.
Affected component
openvas-scanner 23.45.5 (openvasd + C openvas backend, [scanner] type = "openvas").
- Function:
ports_to_openvas_port_list in rust/crates/greenbone-scanner-framework/src/models/port.rs.
Root cause
add_range_to_list enumerates every port in the range:
fn add_range_to_list(list: &mut String, start: usize, end: Option<usize>) {
if let Some(end) = end {
for p in start..=end { // expands 1..=65535 into "1,2,3,...,65535,"
list.push_str(p.to_string().as_str());
list.push(',');
}
} else {
list.push_str(start.to_string().as_str());
list.push(',');
}
}
Notably, the PortRange struct in the same file already has a Display impl that produces the compact form:
impl Display for PortRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.end {
Some(end) => write!(f, "{}-{}", self.start, end),
None => write!(f, "{}", self.start),
}
}
}
ports_to_openvas_port_list just doesn't use it. nmap.nasl itself is fine — it reads get_preference("port_range") and passes it verbatim to nmap -p, which accepts compact ranges (-p T:1-65535).
Reproduction
POST a scan with a full TCP range as structured ports, scanner type openvas:
{
"target": {
"hosts": ["<reachable host>"],
"ports": [{ "protocol": "tcp", "range": [{ "start": 1, "end": 65535 }] }]
},
"vts": [ ... full-and-fast ... ]
}
Start it and watch the journal:
openvasd[...]: nasl_pread: Failed to execute child process "nmap" (Argument list too long)
GET /scans/<id>/results then contains no open ports for any host, even hosts with services listening. Using a smaller list (e.g. "All IANA assigned TCP", ~5,836 ports → ~35 KB when expanded) stays under the 128 KB single-arg limit and works, which is why the bug only shows up on large/all-port scans.
Confirming it is the port_range string: injecting a compact port_range scan preference ("T:1-65535") with empty structured target.ports makes the scan run nmap correctly and detect ports — no E2BIG.
Impact
Full-port / all-TCP scans driven via openvasd's structured target.ports silently perform no port scanning and detect nothing service-side — a false-negative across the whole scan. gvmd/ospd-openvas are unaffected because they pass a compact port_range string rather than structured ranges.
Suggested fix
Emit the compact form in add_range_to_list (reuse PortRange's Display), e.g.:
fn add_range_to_list(list: &mut String, start: usize, end: Option<usize>) {
match end {
Some(end) if end != start => list.push_str(&format!("{start}-{end},")),
_ => list.push_str(&format!("{start},")),
}
}
This keeps T:1-65535 compact and well within MAX_ARG_STRLEN.
This issue was investigated and filed automatically by Claude (an AI assistant), at the request of a user running openvas-scanner 23.45.5, based on hands-on debugging (journal traces, source inspection, and a compact-port_range workaround that confirms the root cause).
Summary
When a scan's
target.portscontains a large range,openvasdexpands that range into an explicit, per-port comma-separated list when building the openvasport_rangepreference, instead of keeping it compact (start-end). For a full TCP scan (1-65535) the resulting string is ~380 KB.nmap.naslpasses that whole string tonmapas a single-p <port_range>argument, which exceeds the Linux kernel's per-argument limit (MAX_ARG_STRLEN, 128 KB), soexecvefails withE2BIG:The port scan therefore never runs. The scan completes "successfully" but reports zero open ports for every host — only host-level results (OS detection, ICMP, traceroute). No service detection, no service-based VTs, no findings.
Affected component
openvas-scanner23.45.5 (openvasd+ Copenvasbackend,[scanner] type = "openvas").ports_to_openvas_port_listinrust/crates/greenbone-scanner-framework/src/models/port.rs.Root cause
add_range_to_listenumerates every port in the range:Notably, the
PortRangestruct in the same file already has aDisplayimpl that produces the compact form:ports_to_openvas_port_listjust doesn't use it.nmap.naslitself is fine — it readsget_preference("port_range")and passes it verbatim tonmap -p, which accepts compact ranges (-p T:1-65535).Reproduction
POST a scan with a full TCP range as structured ports, scanner type
openvas:{ "target": { "hosts": ["<reachable host>"], "ports": [{ "protocol": "tcp", "range": [{ "start": 1, "end": 65535 }] }] }, "vts": [ ... full-and-fast ... ] }Start it and watch the journal:
GET /scans/<id>/resultsthen contains no open ports for any host, even hosts with services listening. Using a smaller list (e.g. "All IANA assigned TCP", ~5,836 ports → ~35 KB when expanded) stays under the 128 KB single-arg limit and works, which is why the bug only shows up on large/all-port scans.Confirming it is the
port_rangestring: injecting a compactport_rangescan preference ("T:1-65535") with empty structuredtarget.portsmakes the scan run nmap correctly and detect ports — noE2BIG.Impact
Full-port / all-TCP scans driven via
openvasd's structuredtarget.portssilently perform no port scanning and detect nothing service-side — a false-negative across the whole scan.gvmd/ospd-openvasare unaffected because they pass a compactport_rangestring rather than structured ranges.Suggested fix
Emit the compact form in
add_range_to_list(reusePortRange'sDisplay), e.g.:This keeps
T:1-65535compact and well withinMAX_ARG_STRLEN.This issue was investigated and filed automatically by Claude (an AI assistant), at the request of a user running openvas-scanner 23.45.5, based on hands-on debugging (journal traces, source inspection, and a compact-
port_rangeworkaround that confirms the root cause).