## TL;DR
When nmap cannot resolve services, the port table shows unknown or ambiguous state values, and an agent skimming the text reads them as open ports. Treat only an explicit open state in the STATE column as an open port. Anything else (unknown, filtered, open|filtered, unresolvable) is not a finding. Make the agent quote the exact STATE value for every port it reports.

```text
agent hallucinated open ports from nmap output after the scan failed to resolve services
```

## Use this when
- Your agent's reported open ports include ones the raw nmap output marks as ambiguous or unknown.
- Service detection (-sV) timed out or produced empty results and the agent still listed services.
- You need a port list you can defend in a client report.

## Not for this skill when
- Nmap completed cleanly with services resolved. Then the agent's list is probably right and the issue is elsewhere.
- The scan itself failed to reach the host. That is a connectivity issue, not a hallucination issue.
- You are scanning targets outside your authorized scope. Stop.

## Steps
1. Pull the raw nmap output (not the agent's summary) and read the STATE column for every reported port. Verify: you can point to the exact line and state value for each port the agent claimed.
2. Reclassify: keep only rows where STATE is literally open. Move unknown, filtered, open|filtered, and closed rows to a separate "not confirmed" list. Verify: the confirmed list is shorter than or equal to the agent's original list.
3. For any service the agent named without a version string, check whether -sV actually returned one. Verify: no service name appears in the report without nmap having printed it.
4. Add a guard to the agent's extraction prompt: "report a port only if the STATE column reads open, and quote the STATE value". Verify: rerunning the extraction on the same output drops the phantom ports.
5. Log dropped claims with their original STATE values so the tester can decide whether a re-scan is warranted. Verify: nothing is silently discarded.

## Variant phrasings
### agent inventing open ports from failed nmap scan
Same failure, plainer phrasing.
### nmap service detection failed agent reports wrong ports
Symptom-level search.
### validate agent nmap port extraction against raw output
Workflow phrasing.

Compatibility: nmap 7.x text and grepable output. The STATE column semantics are stable across versions.

## Why it happens
Service-resolution failures leave the port table full of rows where the state is a guess or a leftover, and language models are pattern-completers: a row that looks like "port, something, http" reads as an open HTTP port. The agent never learned that nmap's STATE column is the only source of truth.

## Edge cases / pitfalls
- Greppable output (-oG) compresses states into one line per host; the same rule applies: only the open marker counts.
- UDP scans legitimately return open|filtered for many ports. Those are leads for retesting, not findings for the report.
- If the scan failed so badly that no port table exists at all, any port the agent reports is fabricated. Regenerate from an empty list and re-scan.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_kxBtI259nEafA2GekiA74g
