这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged

v2.10.0 #1668

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e5bcc68
add onhype
dogancanbakir Sep 22, 2025
fa6ceaa
Merge branch 'dev' into add_onhype
dogancanbakir Oct 1, 2025
2097be5
Call ResultCallback sooner
mukesh-dream11 Oct 1, 2025
7e6ad51
Handle case when RemoveWildcard is true
mukesh-dream11 Oct 1, 2025
50bbe41
Add missing domain field
mukesh-dream11 Oct 1, 2025
648f1e1
fix pagination
dogancanbakir Oct 2, 2025
d236bba
fix lint err
dogancanbakir Oct 2, 2025
7823d41
fix typo
dogancanbakir Oct 2, 2025
1af75eb
Merge pull request #1652 from mukesh-dream11/fix-onresult
dogancanbakir Oct 2, 2025
c47f852
chore(deps): bump github.com/nwaples/rardecode/v2
dependabot[bot] Oct 11, 2025
8117b1a
add windvane
dogancanbakir Oct 16, 2025
26a221f
using json marshal
Mzack9999 Oct 19, 2025
a8e87b7
Merge pull request #1657 from projectdiscovery/1639_add_windvane
dogancanbakir Oct 20, 2025
7396f0d
Merge pull request #1647 from projectdiscovery/add_onhype
dogancanbakir Oct 20, 2025
61bc082
add api key support
dogancanbakir Oct 20, 2025
bc7edda
remove hunter
dogancanbakir Oct 20, 2025
3d6441b
Merge pull request #1662 from projectdiscovery/1661_remove_hunter
Mzack9999 Oct 20, 2025
2ba3645
Merge pull request #1660 from projectdiscovery/1659_add_api_key_support
Mzack9999 Oct 20, 2025
02ea9f8
New source: DomainsProject
tb0hdan Oct 20, 2025
c1b64d8
CR fixes
tb0hdan Oct 20, 2025
3ba0a30
Add domainsproject to sources tests
tb0hdan Oct 20, 2025
6c1e538
Merge pull request #1663 from tb0hdan/dev
dogancanbakir Nov 4, 2025
3cb054d
Add wildcard certificate detection in JSON output (#1665)
tarunKoyalwar Nov 5, 2025
d525551
refactor: use strings.Builder to improve performance
sunnyraindy Nov 10, 2025
92bd205
Merge pull request #1666 from sunnyraindy/dev
dogancanbakir Nov 12, 2025
5bcfca5
Merge branch 'main' into dev
dogancanbakir Nov 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ jobs:
FOFA_API_KEY: ${{secrets.FOFA_API_KEY}}
FULLHUNT_API_KEY: ${{secrets.FULLHUNT_API_KEY}}
GITHUB_API_KEY: ${{secrets.GITHUB_API_KEY}}
HUNTER_API_KEY: ${{secrets.HUNTER_API_KEY}}
INTELX_API_KEY: ${{secrets.INTELX_API_KEY}}
LEAKIX_API_KEY: ${{secrets.LEAKIX_API_KEY}}
QUAKE_API_KEY: ${{secrets.QUAKE_API_KEY}}
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ vendor/
.idea
.devcontainer
.vscode
dist
dist
/subfinder
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ builds:
- darwin
goarch:
- amd64
- 386
- '386'
- arm
- arm64

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ require (
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 // indirect
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/projectdiscovery/blackrock v0.0.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 h1:MYzLheyVx1tJVDqfu3YnN4jtnyALNzLvwl+f58TcvQY=
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down
8 changes: 6 additions & 2 deletions pkg/passive/sources.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/digitorus"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsdb"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsdumpster"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/domainsproject"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsrepo"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/driftnet"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/facebook"
Expand All @@ -33,10 +34,10 @@ import (
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/github"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/hackertarget"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/hudsonrock"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/hunter"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/intelx"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/leakix"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/netlas"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/onyphe"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/pugrecon"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/quake"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/rapiddns"
Expand All @@ -51,6 +52,7 @@ import (
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/virustotal"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/waybackarchive"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/whoisxmlapi"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/windvane"
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/zoomeyeapi"
mapsutil "github.com/projectdiscovery/utils/maps"
)
Expand All @@ -70,15 +72,16 @@ var AllSources = [...]subscraping.Source{
&digitorus.Source{},
&dnsdb.Source{},
&dnsdumpster.Source{},
&domainsproject.Source{},
&dnsrepo.Source{},
&driftnet.Source{},
&fofa.Source{},
&fullhunt.Source{},
&github.Source{},
&hackertarget.Source{},
&hunter.Source{},
&intelx.Source{},
&netlas.Source{},
&onyphe.Source{},
&leakix.Source{},
&quake.Source{},
&pugrecon.Source{},
Expand All @@ -95,6 +98,7 @@ var AllSources = [...]subscraping.Source{
&virustotal.Source{},
&waybackarchive.Source{},
&whoisxmlapi.Source{},
&windvane.Source{},
&zoomeyeapi.Source{},
&facebook.Source{},
// &threatminer.Source{}, // failing api
Expand Down
8 changes: 6 additions & 2 deletions pkg/passive/sources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ var (
"dnsdumpster",
"dnsdb",
"dnsrepo",
"domainsproject",
"driftnet",
"fofa",
"fullhunt",
"github",
"hackertarget",
"intelx",
"netlas",
"onyphe",
"quake",
"pugrecon",
"rapiddns",
Expand All @@ -48,8 +50,8 @@ var (
"virustotal",
"waybackarchive",
"whoisxmlapi",
"windvane",
"zoomeyeapi",
"hunter",
"leakix",
"facebook",
// "threatminer",
Expand All @@ -72,22 +74,24 @@ var (
"crtsh",
"digitorus",
"dnsdumpster",
"domainsproject",
"dnsrepo",
"driftnet",
"fofa",
"fullhunt",
"hackertarget",
"intelx",
"onyphe",
"quake",
"redhuntlabs",
"robtex",
// "riddler", // failing due to cloudfront protection
"rsecloud",
"securitytrails",
"shodan",
"windvane",
"virustotal",
"whoisxmlapi",
"hunter",
"leakix",
"facebook",
// "threatminer",
Expand Down
24 changes: 13 additions & 11 deletions pkg/resolve/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ type ResolutionPool struct {

// HostEntry defines a host with the source
type HostEntry struct {
Domain string
Host string
Source string
Domain string
Host string
Source string
WildcardCertificate bool
}

// Result contains the result for a host resolution
type Result struct {
Type ResultType
Host string
IP string
Error error
Source string
Type ResultType
Host string
IP string
Error error
Source string
WildcardCertificate bool
}

// ResultType is the type of result found
Expand Down Expand Up @@ -92,13 +94,13 @@ func (r *ResolutionPool) InitWildcards(domain string) error {
func (r *ResolutionPool) resolveWorker() {
for task := range r.Tasks {
if !r.removeWildcard {
r.Results <- Result{Type: Subdomain, Host: task.Host, IP: "", Source: task.Source}
r.Results <- Result{Type: Subdomain, Host: task.Host, IP: "", Source: task.Source, WildcardCertificate: task.WildcardCertificate}
continue
}

hosts, err := r.DNSClient.Lookup(task.Host)
if err != nil {
r.Results <- Result{Type: Error, Host: task.Host, Source: task.Source, Error: err}
r.Results <- Result{Type: Error, Host: task.Host, Source: task.Source, Error: err, WildcardCertificate: task.WildcardCertificate}
continue
}

Expand All @@ -116,7 +118,7 @@ func (r *ResolutionPool) resolveWorker() {
}

if !skip {
r.Results <- Result{Type: Subdomain, Host: task.Host, IP: hosts[0], Source: task.Source}
r.Results <- Result{Type: Subdomain, Host: task.Host, IP: hosts[0], Source: task.Source, WildcardCertificate: task.WildcardCertificate}
}
}
r.wg.Done()
Expand Down
2 changes: 1 addition & 1 deletion pkg/runner/banners.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const banner = `
const ToolName = `subfinder`

// Version is the current version of subfinder
const version = `v2.9.0`
const version = `v2.9.1-dev`

// showBanner is used to show the banner to the user
func showBanner() {
Expand Down
40 changes: 28 additions & 12 deletions pkg/runner/enumerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func (r *Runner) EnumerateSingleDomainWithCtx(ctx context.Context, domain string
gologger.Warning().Msgf("Encountered an error with source %s: %s\n", result.Source, result.Error)
case subscraping.Subdomain:
subdomain := replacer.Replace(result.Value)
// check if this subdomain is actually a wildcard subdomain
// that may have furthur subdomains associated with it
isWildcard := strings.Contains(result.Value, "*."+subdomain)

// Validate the subdomain found and remove wildcards from
if !strings.HasSuffix(subdomain, "."+domain) {
Expand All @@ -90,10 +93,20 @@ func (r *Runner) EnumerateSingleDomainWithCtx(ctx context.Context, domain string
// send the subdomain for resolution.
if _, ok := uniqueMap[subdomain]; ok {
skippedCounts[result.Source]++
// even if it is duplicate if it was not marked as wildcard before but this source says it is wildcard
// then we should mark it as wildcard
if !uniqueMap[subdomain].WildcardCertificate && isWildcard {
val := uniqueMap[subdomain]
val.WildcardCertificate = true
uniqueMap[subdomain] = val
}
continue
}

hostEntry := resolve.HostEntry{Domain: domain, Host: subdomain, Source: result.Source}
hostEntry := resolve.HostEntry{Domain: domain, Host: subdomain, Source: result.Source, WildcardCertificate: isWildcard}
if r.options.ResultCallback != nil && !r.options.RemoveWildcard {
r.options.ResultCallback(&hostEntry)
}

uniqueMap[subdomain] = hostEntry
// If the user asked to remove wildcard then send on the resolve
Expand All @@ -109,6 +122,7 @@ func (r *Runner) EnumerateSingleDomainWithCtx(ctx context.Context, domain string
if r.options.RemoveWildcard {
close(resolutionPool.Tasks)
}

wg.Done()
}()

Expand All @@ -125,9 +139,22 @@ func (r *Runner) EnumerateSingleDomainWithCtx(ctx context.Context, domain string
// Add the found subdomain to a map.
if _, ok := foundResults[result.Host]; !ok {
foundResults[result.Host] = result
if r.options.ResultCallback != nil {
r.options.ResultCallback(&resolve.HostEntry{Domain: domain, Host: result.Host, Source: result.Source, WildcardCertificate: result.WildcardCertificate})
}
}
}
}

// Merge wildcard certificate information from uniqueMap into foundResults
// This handles cases where a later source marked a subdomain as wildcard
// after it was already sent to the resolution pool
for host, result := range foundResults {
if entry, ok := uniqueMap[host]; ok && entry.WildcardCertificate && !result.WildcardCertificate {
result.WildcardCertificate = true
foundResults[host] = result
}
}
}
wg.Wait()
outputWriter := NewOutputWriter(r.options.JSON)
Expand Down Expand Up @@ -162,17 +189,6 @@ func (r *Runner) EnumerateSingleDomainWithCtx(ctx context.Context, domain string
numberOfSubDomains = len(uniqueMap)
}

if r.options.ResultCallback != nil {
if r.options.RemoveWildcard {
for host, result := range foundResults {
r.options.ResultCallback(&resolve.HostEntry{Domain: host, Host: result.Host, Source: result.Source})
}
} else {
for _, v := range uniqueMap {
r.options.ResultCallback(&v)
}
}
}
gologger.Info().Msgf("Found %d subdomains for %s in %s\n", numberOfSubDomains, domain, duration)

if r.options.Statistics {
Expand Down
35 changes: 20 additions & 15 deletions pkg/runner/outputter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,25 @@ type OutputWriter struct {
}

type jsonSourceResult struct {
Host string `json:"host"`
Input string `json:"input"`
Source string `json:"source"`
Host string `json:"host"`
Input string `json:"input"`
Source string `json:"source"`
WildcardCertificate bool `json:"wildcard_certificate,omitempty"`
}

type jsonSourceIPResult struct {
Host string `json:"host"`
IP string `json:"ip"`
Input string `json:"input"`
Source string `json:"source"`
Host string `json:"host"`
IP string `json:"ip"`
Input string `json:"input"`
Source string `json:"source"`
WildcardCertificate bool `json:"wildcard_certificate,omitempty"`
}

type jsonSourcesResult struct {
Host string `json:"host"`
Input string `json:"input"`
Sources []string `json:"sources"`
Host string `json:"host"`
Input string `json:"input"`
Sources []string `json:"sources"`
WildcardCertificate bool `json:"wildcard_certificate,omitempty"`
}

// NewOutputWriter creates a new OutputWriter
Expand Down Expand Up @@ -117,7 +120,7 @@ func writeJSONHostIP(input string, results map[string]resolve.Result, writer io.
data.IP = result.IP
data.Input = input
data.Source = result.Source

data.WildcardCertificate = result.WildcardCertificate
err := encoder.Encode(&data)
if err != nil {
return err
Expand All @@ -130,7 +133,7 @@ func writeJSONHostIP(input string, results map[string]resolve.Result, writer io.
func (o *OutputWriter) WriteHostNoWildcard(input string, results map[string]resolve.Result, writer io.Writer) error {
hosts := make(map[string]resolve.HostEntry)
for host, result := range results {
hosts[host] = resolve.HostEntry{Domain: host, Host: result.Host, Source: result.Source}
hosts[host] = resolve.HostEntry{Domain: host, Host: result.Host, Source: result.Source, WildcardCertificate: result.WildcardCertificate}
}

return o.WriteHost(input, hosts, writer)
Expand Down Expand Up @@ -175,6 +178,7 @@ func writeJSONHost(input string, results map[string]resolve.HostEntry, writer io
data.Host = result.Host
data.Input = input
data.Source = result.Source
data.WildcardCertificate = result.WildcardCertificate
err := encoder.Encode(data)
if err != nil {
return err
Expand Down Expand Up @@ -223,11 +227,12 @@ func writeSourcePlainHost(_ string, sourceMap map[string]map[string]struct{}, wr
for host, sources := range sourceMap {
sb.WriteString(host)
sb.WriteString(",[")
sourcesString := ""
var sourcesString strings.Builder
for source := range sources {
sourcesString += source + ","
sourcesString.WriteString(source)
sourcesString.WriteRune(',')
}
sb.WriteString(strings.Trim(sourcesString, ", "))
sb.WriteString(strings.TrimSuffix(sourcesString.String(), ","))
sb.WriteString("]\n")

_, err := bufwriter.WriteString(sb.String())
Expand Down
Loading
Loading