Skip to content

Commit 5d6d243

Browse files
h0tak88rclaude
andcommitted
feat(scans): Run Nuclei Template scans only live DB hosts, no httpx
The global nuclei button now pulls liveOnly=true from the DB and targets each host by its stored scheme-prefixed URL (https://host), so nuclei runs the template directly with no httpx re-probing step. Errors clearly when there are no live hosts yet. Modal copy + started log updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1cc341e commit 5d6d243

2 files changed

Lines changed: 10 additions & 12 deletions

File tree

internal/api/ui/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ <h2 class="view-title" id="report-template-modal-title"> Edit Template</h2>
793793
<div id="nuclei-modal" class="auth-gate" style="display:none; z-index: 1000;" aria-modal="true" role="dialog">
794794
<div class="auth-card" style="max-width: 600px; width: 90%; max-height: 85vh; display: flex; flex-direction: column;">
795795
<h2 class="auth-title" style="margin-bottom: 8px;">Run Global Nuclei Scan</h2>
796-
<p class="auth-sub" style="margin-bottom: 20px;">Enter a Nuclei template path/ID, OR paste raw YAML template code.</p>
796+
<p class="auth-sub" style="margin-bottom: 20px;">Runs against <strong>all live hosts in the database</strong> (their stored <code>https://</code> URLs) — no httpx re-probing. Enter a Nuclei template path/ID, OR paste raw YAML template code.</p>
797797

798798
<div style="display: flex; flex-direction: column; flex: 1; min-height: 0;">
799799
<textarea id="nuclei-template-input" class="search-input auth-input"

internal/api/ui_api.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -671,19 +671,17 @@ func apiRunGlobalNuclei(c *gin.Context) {
671671
limit := 10000
672672
totalSubs := 0
673673
for offset := 0; ; offset += limit {
674-
subs, _, err := db.ListAllSubdomainsPaginated("", "", "", 0, false, limit, offset)
674+
// liveOnly=true: only pull hosts already probed live via httpx. Each is
675+
// written as its stored scheme-prefixed URL (https://host), so nuclei runs
676+
// the template directly against it and never re-probes (no httpx step).
677+
subs, _, err := db.ListAllSubdomainsPaginated("", "", "", 0, true, limit, offset)
675678
if err != nil || len(subs) == 0 {
676679
break
677680
}
678681
for _, s := range subs {
679-
// For subdomains already probed live, use the stored scheme-prefixed
680-
// URL (https://host) so nuclei skips its own httpx probing. Unprobed
681-
// hosts fall back to the bare name (nuclei resolves the scheme itself).
682-
target := s.Subdomain
683-
if s.IsLive {
684-
if u := s.BestURL(); u != "" {
685-
target = u
686-
}
682+
target := s.BestURL()
683+
if target == "" {
684+
target = s.Subdomain
687685
}
688686
if target != "" {
689687
tmpFile.WriteString(target + "\n")
@@ -694,10 +692,10 @@ func apiRunGlobalNuclei(c *gin.Context) {
694692
tmpFile.Close()
695693

696694
if totalSubs == 0 {
697-
return fmt.Errorf("no subdomains found for global nuclei scan")
695+
return fmt.Errorf("no live hosts found in the database — run a scan/httpx first so there are live URLs to test")
698696
}
699697

700-
stdLog(scanID, "[INFO] Loaded %d targets for scan", totalSubs)
698+
stdLog(scanID, "[INFO] Loaded %d live host(s) from the database (httpx skipped)", totalSubs)
701699

702700
var templatePath string
703701
var cleanupTemplate func()

0 commit comments

Comments
 (0)