TLS Certificate Grab
The TLS Certificate Grab module opens a single TLS handshake on every open port that speaks TLS but not HTTP, and captures the certificate the server presents along with the negotiated posture.
It fills a real gap. The HTTP probe only grabs certificates on the five HTTPS ports it dials, so a certificate sitting on SMTPS 465, IMAPS 993, POP3S 995, LDAPS 636, FTPS 990 or any odd TLS port the port scan found was never seen. Those ports were discovered open, labelled from a static IANA table, and never inspected again.
It runs as GROUP 3.6, after port scanning and before the HTTP probe, so hostnames found inside a certificate can become probe targets in the same scan. It is on by default and deliberately quiet: one round trip per already-open port.
What tlsx is
The module wraps tlsx, an open-source TLS grabber from ProjectDiscovery, the same authors as nuclei, httpx, naabu, katana and subfinder, several of which RedAmon already uses.
tlsx performs the TLS handshake and reports what it saw: the full certificate chain detail, the negotiated version and cipher, and optional fingerprints. RedAmon runs it as a pinned container image through the filtered Docker broker, exactly like every other ProjectDiscovery tool in the pipeline, so it inherits the same sandboxing and image allow-listing.
One consequence worth knowing up front: tlsx is written in Go, and Go's TLS client has dropped RC4 and 3DES. A server offering only weak ciphers will refuse to complete a handshake with it, which shapes what the cipher checks can and cannot see. See Results that look wrong but are not.
What one tlsx answer gives RedAmon
When RedAmon uses tlsx to query an IP, a single answer gives it material for all of this:
✅ Learning what the service really is. Port 465 is officially registered as "urd", but the certificate shows it is a mail server.
✅ Finding hidden hostnames. Certificates often list names that DNS never published. The ones that belong to the target's domain become new targets in the same scan.
✅ Spotting certificate problems. An expired certificate, a self-signed one, a name that doesn't match the server, or a wildcard covering far too many hosts.
✅ Catching outdated encryption. A server still negotiating TLS 1.0 or 1.1 comes up straight away.
✅ Discovering shared infrastructure. Every certificate has a unique fingerprint, so two IPs presenting the same one are the same deployment, whatever their DNS says.
✅ Recognising a CDN from the certificate issuer, even on ports that don't speak HTTP.
✅ Checking for subdomain takeover. If the certificate names the host, the provider is still serving the real customer. A provider's default certificate, or no certificate at all, points to a host someone else could claim.
✅ Mapping virtual hosts. The names found become candidates to ask a shared server for each site it hosts.
✅ Fingerprinting the TLS stack with JARM, when you turn it on, to link unrelated IPs back to the same platform.
The answer itself costs one handshake per port. Only JARM and the two enumeration options, all off by default, make tlsx send more. Some of the modules the answer feeds, such as virtual host enumeration, then send their own traffic.
How each one works
Learning what the service really is
The port scan names every open port from the IANA registration table, which is a guess about what should listen there, not what does. Port 465 is registered as urd, yet in practice it is almost always SMTPS. The certificate answers the question directly, because it was issued for the real service.
RedAmon records the answer as tls_service_hint on the Service node, alongside the negotiated TLS version and cipher. It never renames the service: the service name is part of that node's identity, so changing urd to smtps would create a second node and orphan the one the port scan made. The observed value sits next to the registered one instead.
Finding hidden hostnames
A certificate's Subject Alternative Name (SAN) list names every host it is valid for. It routinely includes hosts that never appeared in DNS enumeration: internal names, staging names, and names retired from DNS but still on the certificate.
The SAN list is written by the machine being scanned, so RedAmon treats it as untrusted input. A hostile server could list a third party's hostname and trick the scanner into attacking it. Each name has to pass five filters, in this order, before it becomes a target:
- It must equal the project domain or end with
.<domain>. Every other name is recorded as an external domain, so you can see it, and is never scanned. - It must not be excluded by the Rules of Engagement.
- It must be a syntactically valid hostname. This also blocks a newline hidden inside a name, which would split one entry into two in the newline-delimited target files other tools read.
- At most 200 names are kept. The cap is applied before any DNS lookup, so a certificate naming hundreds of hosts cannot stall the scan with hundreds of DNS timeouts.
- A name resolving to a private or loopback address is dropped, which stops the scanner being redirected into internal space. A name that does not resolve at all is kept: it is in scope and cannot point inward, it simply will not answer.
Names that pass join the target list before the HTTP probe runs, so the probe, the crawler and every later module treat them as discovered hosts. In the graph they gain a COVERS_HOST edge from the certificate. With no root domain to test against, as in an IP-mode scan, nothing is promoted at all.
Spotting certificate problems
RedAmon reads the certificate's own data and recomputes each verdict rather than trusting the flags tlsx reports:
| Finding | How RedAmon decides |
|---|---|
| Expired | the not_after date is compared with the current time. tlsx omits its own expired field when it is false, so its absence says nothing |
| Self-signed | the subject and the issuer are the same entity |
| Hostname mismatch | checked only when RedAmon connected with a hostname. On a bare IP, tlsx reports a mismatch for every correctly configured server, because a certificate names hosts and never IPs, so that flag is discarded |
| Overbroad wildcard | a wildcard certificate naming more than 20 hosts, where a single leaked private key would expose all of them |
Wildcard names match exactly one label, as browsers do: *.example.com covers app.example.com but not a.app.example.com. These findings are raised from data already in memory, and they sit behind the Security Checks master toggle.
Catching outdated encryption
The handshake reports the TLS version and cipher the server agreed to. A negotiated SSL 2.0, SSL 3.0, TLS 1.0 or TLS 1.1 raises Weak TLS Version Negotiated. A negotiated cipher containing RC4, 3DES, DES, NULL, EXPORT, MD5 or an anonymous key exchange raises Weak TLS Cipher Negotiated, and Enumerate weak ciphers adds Weak TLS Cipher Supported for weak ciphers the server still accepts.
A single handshake shows only what the server chose, and a server can negotiate TLS 1.3 with a modern client while still accepting TLS 1.0 from an old one. Enumerate supported TLS versions reconnects once per version to catch that, and raises Weak TLS Version Supported. The limit described in What tlsx is applies: Go's TLS client cannot negotiate RC4 or 3DES, so a server offering only those fails the handshake instead of producing a finding. Weak version detection is unaffected.
Discovering shared infrastructure
A certificate's SHA-256 fingerprint identifies that exact certificate and no other. RedAmon uses it as the Certificate node's identity, so every IP presenting the same certificate links to one shared node through HAS_CERTIFICATE, however unrelated their DNS looks.
The same key is used by every scanner that writes certificates (httpx, tlsx, Censys, FOFA, GVM), so they converge on one node instead of creating duplicates. A re-issued certificate keeps its name but gets a new fingerprint, so it stays a separate node. The Red Zone Shared Infrastructure view groups the hosts each certificate covers, which reveals deployments that DNS alone does not.
Recognising a CDN
The certificate issuer often names the CDN outright. RedAmon matches the issuer against a table of known CDN certificate authorities and, on a match, marks the IP as a CDN edge with cdn_source: tls_certificate.
This fills a real gap: the port scanner only attributes a CDN when its own fingerprinting recognises one, and the HTTP-based check needs an HTTP response, so neither works on a non-HTTP TLS port. The certificate only ever fills a blank value, never overriding the port scanner's own attribution. JARM is deliberately not used here: a JARM-to-CDN table is only as good as the hashes in it, and there is no verified source to build one from.
Checking for subdomain takeover
A takeover happens when a subdomain still points at a cloud or SaaS provider that no longer serves the organisation, so anyone can claim the resource. The certificate answers what the takeover module otherwise has to infer from weak signals, and it works even when the host has no CNAME record.
The module reads the best certificate available for the host, from tlsx first, falling back to the one the HTTP probe captured on port 443:
| What the certificate shows | What RedAmon concludes |
|---|---|
| No certificate data was collected | unknown. The host is not treated as evidence either way |
| A handshake was attempted and failed | consistent with an abandoned target: a signal for takeover |
| A valid certificate that names the host | the provider is serving the legitimate customer. The candidate is settled, and the AI check that would otherwise separate a real takeover page from a firewall block page is skipped entirely |
| The provider's default certificate, not naming the host | the provider edge is answering but not for this customer: the host is claimable |
It is on by default and controlled by the takeoverCertValidationEnabled project setting.
Mapping virtual hosts
One IP address frequently serves many sites, and the server decides which one to return from the name the client asks for (SNI). Without the right name you only ever see the default site.
Every hostname found in a certificate on an IP becomes a candidate for virtual host and SNI enumeration against that same IP. The enumeration then asks the shared frontend for each name in turn and records the sites that answer. tlsx contributes names from non-HTTP ports and bare IPs that the HTTP probe never reached.
Fingerprinting the TLS stack with JARM
JARM sends ten deliberately varied handshakes and hashes how the server responds to them. The hash describes the server's TLS software and configuration rather than its certificate, so unrelated IPs running the same stack share one JARM hash: a common load balancer, a shared hosting platform, or command-and-control infrastructure.
It is off by default, costs about ten extra handshakes per target, and is forced off in stealth mode. When enabled, jarm, ja3 and ja3s are stored on the Certificate node. RedAmon does not group IPs by JARM automatically: the hashes are recorded so you, or the agent through a graph query, can compare them across hosts.
Settings

The screenshot shows every setting at its default value.
The section lives in the project settings, under the recon pipeline. Every value is stored per project. The form shows the on/off toggle in the section header and ten settings under it. Seven more settings are not in the form; they are covered in Settings not shown in the form.
Quick reference
| Setting | Default | Form range | Passed to tlsx as |
|---|---|---|---|
| Enabled (header toggle) | on | on / off | runs the phase at all |
| Feed SAN hostnames back into the scan | on | on / off | RedAmon only |
| Include HTTP/HTTPS ports | off | on / off | RedAmon only (target list) |
| Concurrency | 50 | 1 to 300 | -c |
| Handshake timeout (s) | 5 | 1 to 60 | -timeout |
| Max targets | 2000 | 1 to 100000 | RedAmon only (target list) |
| Max SAN hostnames injected | 200 | 0 to 10000 | RedAmon only |
| JARM / JA3 fingerprints | off | on / off | -jarm -ja3 |
| Enumerate supported TLS versions | off | on / off | -ve |
| Enumerate weak ciphers | off | on / off | -ce -ct weak -cec <n> |
| Reverse-PTR SNI for bare IPs | off | on / off | -rps |
Whatever you set, every run also passes -json -silent -duc -tps -se -hash sha256: JSON output, no banner, no update check, a status line even for failed handshakes, the certificate serial number, and the SHA-256 fingerprint. tlsx's output filters (-ex, -ss, -mm, -re, -un) are never passed, because they would silently drop every healthy host from the results.
Enabled
The toggle in the section header. Default: on.
When it is on, the grab runs as GROUP 3.6 in both domain-mode and IP-mode scans.
When it is off, no tlsx container starts and tlsx writes no Certificate nodes. Nothing is read from the non-HTTP TLS ports. The features that use certificates keep working on the certificates the HTTP probe captured on its HTTPS ports: the TLS findings, the takeover evidence, the virtual host candidates and the SAN feedback. They simply have fewer certificates to work with.
Three things to know:
- The form hides every other setting while this is off, but two of them still apply. Feed SAN hostnames back into the scan and Max SAN hostnames injected also control the names taken from the HTTP probe's certificates, so their last saved values keep being used.
- Passive presets switch it off, because a handshake is a packet sent to the target. They are Full Pipeline - Passive Only, OSINT Investigator, DNS & Email Security, JS Secret Miner and Supply Chain Audit.
- Partial recon ignores it. Running the TLS Certificate Grab node on its own from the workflow graph always runs tlsx, because you asked for it explicitly.
Coverage
Feed SAN hostnames back into the scan
Default: on.
Every name listed in a certificate's Subject Alternative Name list, plus its subject common name, is offered back to the scan as a possible new target. Only names that pass the five checks described in Finding hidden hostnames become targets. Names outside the project domain are recorded as external domains and never scanned.
The merge runs twice in a domain-mode scan:
- Right after the grab, with the names tlsx found. This is why the grab runs before the HTTP probe: the new names are probed, crawled and scanned in the same run.
- Right after the HTTP probe, with the names from both the HTTP probe's certificates and tlsx's. This pass is what lets the HTTP probe's certificates feed the scan even when tlsx is off. Names already added in the first pass are not duplicated.
When it is off, no name from a certificate is added as a target for the HTTP probe, the crawler or the vulnerability scanners. Two things still happen, because neither is a new target:
- In-scope names are still written to the graph as
Subdomainnodes linked from the certificate byCOVERS_HOST. - The names are still tried as virtual host candidates against the same IP that presented the certificate.
In an IP-mode scan this setting has no effect: there is no project domain to test a name against, so nothing is ever added.
Turn it off when a scan must stay strictly on the hosts you listed.
Include HTTP/HTTPS ports
Default: off.
When it is off, tlsx skips the ports the HTTP probe already covers:
- the HTTPS ports 443, 8443, 4443, 9443 and 8843, where the HTTP probe already reads the certificate;
- the plain HTTP ports 80, 8080, 8000, 8888, 8008, 3000, 5000 and 9000, which normally do not speak TLS at all.
Skipping them avoids paying a second handshake for a certificate RedAmon already has.
Turn it on when you want tlsx's view of the web ports too:
- The self-signed check. The HTTP probe does not return a certificate's issuer, so for its certificates RedAmon cannot tell whether they are self-signed. tlsx returns the issuer, so the check works.
- The deeper probes on web ports. JARM and the two enumeration options only run on ports tlsx scans, so this is how you enumerate TLS versions on port 443.
- HTTPS ports with no web service. Some servers complete TLS on 443 but return nothing the HTTP probe accepts as a website; tlsx still reads their certificate.
The cost is one extra handshake per web port. Plain HTTP ports will usually fail the handshake, and their Service nodes are then marked tls_probe_failed.
Performance and limits
Concurrency
Default: 50. Form range: 1 to 300. Passed as -c.
The number of handshakes tlsx runs at the same time. tlsx's own default is 300; RedAmon uses 50 to be gentler on the target.
Concurrency changes how fast and how noisy the run is, not what it finds, with one exception: a target that rate-limits or drops bursts of connections will fail some handshakes, and those ports are recorded as tls_probe_failed instead of returning a certificate. If you see many failures on a host you know serves TLS, lower this value.
Stealth mode forces it to 5.
Handshake timeout (s)
Default: 5. Form range: 1 to 60. Passed as -timeout.
How long tlsx waits for one connection and handshake before giving up on that attempt. tlsx then retries once (see tlsxRetries below), so a target that never answers can take about twice this long.
Raise it for slow, distant or rate-limited hosts. Lower it to get through a large address space faster, at the risk of missing slow servers.
Size it against the run ceiling. The whole tlsx run is killed after 900 seconds (tlsxRunTimeout), and a killed run records no results at all, not the ones gathered so far. The worst case, when no target answers, is roughly:
targets x timeout x (retries + 1) / concurrency
With the defaults that is 2000 x 5 x 2 / 50 = 400 seconds, which fits. Under stealth mode's concurrency of 5, the same 2000 targets could need 4000 seconds, so keep Max targets low, or raise tlsxRunTimeout, when scanning in stealth mode.
Max targets
Default: 2000. Form range: 1 to 100000.
A hard cap on the number of ip:port targets sent to tlsx in one run. It protects against a port scan that reported thousands of open ports.
- It counts targets, not IPs. One IP with ten TLS ports uses ten. With
tlsxMaxHostnamesPerIpabove 1, every hostname on every port counts separately. - The target list is sorted by IP and then by port before it is cut, so the same scan always keeps the same targets. The log prints
target cap reachedwhen it applies. 0makes the backend scan nothing, but the form cannot save it: the minimum is 1, and an empty field falls back to 2000. To stop the grab, use the Enabled toggle instead.
Max SAN hostnames injected
Default: 200. Form range: 0 to 10000.
The most names from certificates that one merge pass adds as targets. It exists because a single certificate can name hundreds of hosts, and each name costs a DNS lookup on the scan's critical path, before the HTTP probe starts.
- It applies to each of the two merge passes described under Feed SAN hostnames back into the scan.
- It is applied after the domain, Rules of Engagement and syntax checks, and before the DNS check. Names are sorted alphabetically first, so the kept set is the same on every run.
- A name the DNS check later drops does not free its slot for the next one. That is deliberate: a bounded number of DNS lookups matters more than filling the quota exactly.
- Typing
0in the form saves 200, because the form treats 0 as an empty field. To add no names at all, turn off Feed SAN hostnames back into the scan instead.
Deeper probes (louder OPSEC)
All four are off by default. The first three make tlsx open more connections per target, which is more visible to the other side. Stealth mode forces those three off. It does not force off Reverse-PTR SNI for bare IPs, which sends DNS queries rather than connections to the target.
JARM / JA3 fingerprints
Passed as -jarm -ja3. Cost: about 10 extra handshakes per target.
- JARM sends ten deliberately different handshakes to the server and hashes how it answers them. The hash describes the server's TLS software and configuration, not its certificate, so unrelated IPs running the same stack share the same JARM hash: a common load balancer, a shared hosting platform, or command-and-control infrastructure.
- JA3 is a fingerprint of the handshake the client sends. On its own it mainly describes tlsx itself, so JARM is the useful per-server signal.
The hashes are stored as jarm and ja3 on the Certificate node. RedAmon does not pass -ja3s, so the node's ja3s property stays empty. RedAmon does not group IPs by JARM, and does not use it to recognise CDNs; the hashes are there for you, or the agent, to compare with a graph query.
JARM's ten-handshake pattern is well known and easy for a defender to spot, which is why it is off by default and forced off in stealth mode.
Enumerate supported TLS versions
Passed as -ve. Cost: one extra connection per TLS version, per target.
A normal handshake only tells you the version the server chose. A server can pick TLS 1.3 for a modern client and still accept TLS 1.0 from an old one. This option reconnects once per version to list every version the server accepts.
The list is stored as tls_versions_supported on the Service node. Any weak version in it (SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1) raises Weak TLS Version Supported, on top of any Weak TLS Version Negotiated from the normal handshake.
Enumerate weak ciphers
Passed as -ce -ct weak -cec 10. Cost: extra connections per target.
Asks the server, cipher by cipher, which weak cipher suites it still accepts. Accepted ones are stored as tls_ciphers_weak on the Service node and raise Weak TLS Cipher Supported. The number of cipher checks run at once against one target is tlsxCipherConcurrency (10 by default).
tlsx can only test ciphers its TLS library can offer, and Go's standard library no longer offers RC4 or 3DES. A server that accepts only those ciphers fails the handshake, and no weak cipher is reported for it. See Results that look wrong but are not.
Reverse-PTR SNI for bare IPs
Passed as -rps. Cost: one reverse-DNS query per bare IP.
When RedAmon has no hostname for an IP, it sends tlsx the bare IP, and the server returns its default certificate. With this option on, tlsx first looks up the IP's reverse-DNS (PTR) name and presents it as the SNI. On a shared frontend that can be the difference between the default certificate and the certificate of the site that really lives there.
It only helps when the PTR record names the real site. Many PTR records name the hosting provider instead, such as a generic cloud host name.
RedAmon still records the target as a bare IP, so it does not raise a hostname mismatch finding for it, whatever name tlsx derived.
Settings not shown in the form
These have no field in the project form. They can be set through a recon preset or the project API.
| Setting | Default | Passed to tlsx as | What it does |
|---|---|---|---|
tlsxMaxHostnamesPerIp | 1 | target list | When RedAmon knows several hostnames for one IP, how many to try on each port, each presented as its own SNI. Names are sorted alphabetically and the first ones are used. A frontend can present a different certificate for each name, and RedAmon keeps every distinct certificate it gets. Every hostname on every port counts toward Max targets. |
tlsxRetries | 1 | -retry | Extra attempts after a failed connection. tlsx's own default is 3; RedAmon uses 1 to stay quiet. |
tlsxRunTimeout | 900 | RedAmon only | The ceiling for the whole tlsx run, in seconds. A run that exceeds it is killed and records no results. See Handshake timeout for how to size it. |
tlsxScanMode | auto | -sm | Which TLS implementation tlsx uses: ctls (Go's standard library), ztls (the zcrypto library) or auto, which lets tlsx choose. With auto, RedAmon passes nothing. |
tlsxCipherConcurrency | 10 | -cec | How many cipher checks run at once against one target. Used only when Enumerate weak ciphers is on. |
tlsxDelay | empty | -delay | A pause between connections on each tlsx worker, written as a duration such as 200ms or 1s. Empty means no pause. Stealth mode does not set it for you. |
tlsxDockerImage | projectdiscovery/tlsx:latest | container image | The tlsx image to run. The container is started through the Docker broker, so a replacement image has to be one the broker allows. |
Where tlsx is used in the recon pipeline
The grab itself is one phase, but the certificate it captures is read in many places. This is the full list.
Producing the data
| Point | What happens |
|---|---|
| GROUP 3.6, domain mode | Runs after the port scan and before the HTTP probe. |
| GROUP 3.6, IP mode | Same phase in the IP-targeting pipeline. |
| Partial recon | The grab can be re-run on its own from the workflow graph, taking targets from the existing graph or from IPs and ports you type in. |
Consuming the data, in the same scan
| Point | What it uses the certificate for |
|---|---|
| SAN hostname feedback | In-scope SAN names are merged into the target list so the HTTP probe, the crawler and everything downstream treat them as discovered hosts. |
| Virtual host / SNI enumeration | SAN names become SNI candidates, so a shared frontend can be asked for each certificate it holds. |
| Subdomain takeover scoring | A certificate naming the host is evidence the provider is serving the real customer; its absence raises the takeover score. |
| TLS hygiene checks | Six checks derive findings from certificate data already in memory, at zero extra network cost. They read tlsx's certificates when present and the HTTP probe's 443 certificates otherwise. |
| CDN attribution | The issuer is matched against known CDN certificate authorities to classify the IP. |
| Service enrichment | The negotiated version, cipher and a service hint are added to the existing Service node as advisory properties. |
Consuming the data, after the scan
| Point | What it uses the certificate for |
|---|---|
| Attack Surface Graph | Certificate nodes, their link to the IP, and their COVERS_HOST edges are browsable and queryable. |
| Red Zone shared infrastructure | Certificates are clustered by SAN overlap to reveal hosts that share a deployment. |
| Report | A TLS Certificate Posture section summarises the population and lists the worst offenders first. |
| Export and import | Certificates survive a graph export and restore with their identity intact. |
What lands in the graph
| Node / edge | Meaning |
|---|---|
Certificate | issuer, subject, SAN list, validity dates, serial, SHA-256 fingerprint, and posture booleans (expired, self-signed, mismatched, wildcard, revoked, untrusted). With the deeper probes on, also JARM and JA3. |
(IP)-[:HAS_CERTIFICATE]->(Certificate) | the certificate observed on that host |
(Certificate)-[:COVERS_HOST]->(Subdomain) | each in-scope hostname the certificate names, which makes the SAN list traversable in the graph |
Service TLS properties | tls, negotiated version and cipher, a service hint, and the supported-version list when enumeration is on |
Certificates are identified by their fingerprint, not by their subject name. Two scanners that observe the same certificate converge on one node, and two different certificates that happen to share a common name stay separate, which matters because a re-issued certificate and its predecessor usually share a name.
Scope containment
A certificate's SAN list is chosen by the machine being scanned, so it is treated as untrusted input. This is the important one: a hostile host could otherwise list any name it liked and have your scanner attack it.
Before a SAN hostname becomes a scan target it must:
- Pass the apex allow-list: it equals the project domain or ends with
.<domain>. Foreign names are recorded but never scanned. - Pass the Rules of Engagement exclusion list.
- Be a syntactically valid hostname.
- Resolve to a routable address. A name resolving to a private or loopback address is dropped, which blocks an SSRF-style redirect of the scanner into internal space.
The number of injected names is capped, and the whole path fails closed when there is no in-scope apex to test against. That is why an IP-mode scan produces no COVERS_HOST edges at all: there is no root domain to test a name against, so nothing is promoted.
What it does not do
- It never re-grabs certificates on ports the HTTP probe already covers, unless you ask it to, so there are no duplicate handshakes.
- It never renames a service. The service name is part of that node's identity, so a "correction" would orphan the node the port scan created and silently duplicate the service. TLS detail is added alongside it instead.
- It never promotes a hostname it cannot place inside your scope.
Results that look wrong but are not
No COVERS_HOST edges in IP mode. Expected. SAN promotion fails closed without a root domain to test against, and an IP-mode scan has none. Scan by domain and the edges appear.
Findings are empty although certificates are present. The six TLS checks sit behind the Security Checks master toggle. With it off you get certificates and zero findings, which looks identical to a broken check.
A weak cipher is never reported. tlsx cannot negotiate one. A server offering only 3DES fails the handshake outright, a server offering both negotiates the strong one, and the weak-cipher enumeration can only enumerate what it is able to negotiate. Weak version detection is unaffected and works normally.
A service is named urd on port 465. That is the IANA registration for the port. The service hint carries the observed value, smtps, without overwriting the name. This is the static-label problem the module exists to solve, visible in one row.
A certificate names hosts but the scan did not probe them. Check whether they were in scope. Foreign names are recorded so you can see them, and deliberately not scanned.
Partial recon
TLS Certificate Grab can be run on its own from the workflow graph, with the play button on its node or the Run partial recon button in its settings panel. It reads IPs and their open ports from the existing graph, optionally merged with IPs and ports you type in, grabs the certificates, and merges the results back through the same code path the full pipeline uses.
This is the quickest way to refresh certificate data after a re-issue, or to grab certificates on a host you added by hand, without re-running a whole scan.
Verifying it end to end
The repository ships a purpose-built target that exercises every branch of this module against real TLS handshakes rather than fixtures:
cd testing/guinea_pigs/tls_target && docker compose up -d --build
It serves four certificates on four non-HTTP ports: a self-signed multi-SAN certificate including one deliberately out-of-scope name, an expired one, one served over TLS 1.0 only, and an overbroad wildcard naming 23 hosts. Point an IP-mode project at 192.88.98.10 with ports 993,636,995,465 and you should see four certificates, four services with their hints, and eight findings.
The target's README.md documents what each port proves and why. It serves no HTTP at all on purpose, so every certificate in the graph after a run demonstrably came from this module.