Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions cmd/dnsx/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Import necessary packages
package main

import (
"flag"
"fmt"
"strings"
"github.com/projectdiscovery/dnsx" // Assuming this package handles DNS queries
)
Comment on lines +4 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Incorrect import path for dnsx package.

The import "github.com/projectdiscovery/dnsx" does not match the internal library structure. Based on the codebase, the dnsx library is located at libs/dnsx and should be imported as "github.com/projectdiscovery/dnsx/libs/dnsx".

Suggested fix
 import (
     "flag"
     "fmt"
     "strings"
-    "github.com/projectdiscovery/dnsx" // Assuming this package handles DNS queries
+    "github.com/projectdiscovery/dnsx/libs/dnsx"
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/dnsx/main.go` around lines 4 - 9, The import path for the dnsx package is
incorrect; update the import statement in the import block to use the correct
module path "github.com/projectdiscovery/dnsx/libs/dnsx" so references to the
dnsx package (e.g., usages of package symbol dnsx in main.go) resolve to the
internal library; ensure the import alias remains dnsx and run `go build` to
verify there are no unresolved references.


// Function to check for wildcard DNS
func checkWildcard(domain string) bool {
// Common subdomains to check for wildcard
subdomains := []string{"www", "ftp", "mail", "api", "test"}

for _, subdomain := range subdomains {
query := subdomain + "." + domain
result := dnsx.Query(query) // Assuming dnsx.Query performs DNS queries
if strings.Contains(result, "NXDOMAIN") {
return false
}
}
return true
}
Comment on lines +12 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the dnsx package API to confirm available methods

echo "=== Checking dnsx package exports ==="
ast-grep --pattern 'func ($CLIENT *DNSX) Query$_($$$) ($$$) {
  $$$
}'

echo ""
echo "=== Checking existing wildcard implementation ==="
cat internal/runner/wildcard.go

Repository: projectdiscovery/dnsx

Length of output: 1873


🏁 Script executed:

#!/bin/bash
# Search for dnsx methods and functions more broadly

echo "=== Searching for dnsx.Query usage in codebase ==="
rg "dnsx\.Query" --type go -A 2 -B 2

echo ""
echo "=== Searching for dnsx method definitions ==="
rg "func \(.*\*DNSX\) Query" --type go -A 5

echo ""
echo "=== Finding dnsx package location and structure ==="
fd -e go -path "*dnsx*" | head -20

echo ""
echo "=== Check if dnsx.Query function exists (package-level) ==="
rg "^func Query\(" --type go -B 2 -A 5

Repository: projectdiscovery/dnsx

Length of output: 2456


🏁 Script executed:

#!/bin/bash
# Verify the exact content of the problematic function in cmd/dnsx/main.go

echo "=== Content of cmd/dnsx/main.go around the checkWildcard function ==="
head -30 cmd/dnsx/main.go

Repository: projectdiscovery/dnsx

Length of output: 927


dnsx.Query() does not exist and return type is incorrect — code will not compile.

Three critical issues prevent compilation and function:

  1. Non-existent API: dnsx.Query(query) is not a valid package-level function. The dnsx package exposes QueryOne() and QueryMultiple() as methods on a *DNSX instance only.

  2. Type mismatch: These methods return (*retryabledns.DNSData, error), not a string. You cannot call strings.Contains() on this type.

  3. Logic differs from existing implementation: The existing IsWildcard() method in internal/runner/wildcard.go uses random subdomain queries and A-record comparison, which is more reliable than probing known subdomains. The hardcoded subdomain approach can produce false positives for domains that legitimately host www/ftp/mail/api/test subdomains.

Reuse the existing IsWildcard() implementation or adapt it for this context.

Corrected approach (requires further adaptation)
-func checkWildcard(domain string) bool {
-    subdomains := []string{"www", "ftp", "mail", "api", "test"}
-
-    for _, subdomain := range subdomains {
-        query := subdomain + "." + domain
-        result := dnsx.Query(query)
-        if strings.Contains(result, "NXDOMAIN") {
-            return false
-        }
-    }
-    return true
-}
+func checkWildcard(dnsxClient *dnsx.DNSX, domain string) bool {
+    randomSub := xid.New().String() + "." + domain
+    result, err := dnsxClient.QueryOne(randomSub)
+    if err != nil || result == nil {
+        return false
+    }
+    return len(result.A) > 0
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/dnsx/main.go` around lines 12 - 24, The checkWildcard function is using a
non-existent dnsx.Query and treating its return as a string; replace this by
reusing or adapting the existing IsWildcard logic from
internal/runner/wildcard.go: create/obtain a *dnsx.DNSX instance and call its
QueryOne/QueryMultiple methods (they return (*retryabledns.DNSData, error)),
handle the error, extract A-records from the returned *retryabledns.DNSData and
compare results (or use the random-subdomain + A-record comparison used in
IsWildcard) instead of probing fixed subdomains; update checkWildcard to return
false on query errors and to perform proper DNS data comparison per IsWildcard.


func main() {
autoWildcard := flag.Bool("auto-wildcard", false, "Enable automatic wildcard detection")
flag.Parse()

domains := flag.Args()
for _, domain := range domains {
if *autoWildcard && checkWildcard(domain) {
fmt.Printf("[INFO] Wildcard detected for domain: %s\n", domain)
continue // Skip the wildcard domain
}
fmt.Printf("Checking domain: %s\n", domain)
}
}
Comment on lines +26 to +38
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how other commands in this repo initialize the dnsx client
ast-grep --pattern 'dnsx.New($$$)'

Repository: projectdiscovery/dnsx

Length of output: 47


🏁 Script executed:

cat -n cmd/dnsx/main.go | head -60

Repository: projectdiscovery/dnsx

Length of output: 1407


🏁 Script executed:

fd -t f -name "*.go" cmd/ | head -20

Repository: projectdiscovery/dnsx

Length of output: 295


🏁 Script executed:

rg "dnsx\." --type go -A 3 -B 1 | head -100

Repository: projectdiscovery/dnsx

Length of output: 5154


🏁 Script executed:

rg "func.*Query" libs/dnsx/ --type go -B 2 -A 5

Repository: projectdiscovery/dnsx

Length of output: 931


🏁 Script executed:

cat -n cmd/dnsx/main.go

Repository: projectdiscovery/dnsx

Length of output: 1407


🏁 Script executed:

rg "^func Query" libs/dnsx/ --type go

Repository: projectdiscovery/dnsx

Length of output: 47


🏁 Script executed:

rg "dnsx\.Query\(" . --type go

Repository: projectdiscovery/dnsx

Length of output: 164


DNSX client must be initialized and proper query methods used.

The code calls the non-existent dnsx.Query() function. The dnsx package requires:

  1. Creating a DNSX client instance via dnsx.New() with options
  2. Calling query methods on that client (e.g., QueryMultiple(), QueryOne()), not module-level functions
  3. Handling the returned error from DNS operations

Additionally, add error handling for empty domain arguments (when flag.Args() returns nil/empty slice).

The -auto-wildcard flag format is correct per Go conventions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/dnsx/main.go` around lines 26 - 38, The main function currently assumes a
module-level dnsx.Query; replace that with a dnsx client: instantiate a client
via dnsx.New(...) before looping over domains, then call
client.QueryOne()/client.QueryMultiple() (or the appropriate client method) and
handle the returned (result, error) values; also add a guard after domains :=
flag.Args() to return a logged error if domains is empty/nil, and ensure
checkWildcard(domain) errors are handled if it can return an error. Update
references in the loop to use the new client instance and propagate/log DNS
errors instead of ignoring them.

26 changes: 26 additions & 0 deletions test/wildcard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"testing"
"github.com/projectdiscovery/dnsx"
)
Comment on lines +1 to +6
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Test file cannot access checkWildcard — package structure is incorrect.

In Go, packages are determined by directory, not by package declaration alone. This test file in test/wildcard_test.go is a separate package from cmd/dnsx/main.go, even though both declare package main. The unexported function checkWildcard is inaccessible from here.

Additionally:

  • The dnsx import is unused and should be removed.
  • CI runs go test ./... which won't compile this test together with cmd/dnsx/main.go.

To fix, either:

  1. Move the test to cmd/dnsx/main_test.go (same directory as the function), or
  2. Export the function and refactor into a testable package (e.g., internal/wildcard).
Option 1: Move test to cmd/dnsx/
-// File: test/wildcard_test.go
+// File: cmd/dnsx/wildcard_test.go
 package main

 import (
     "testing"
-    "github.com/projectdiscovery/dnsx"
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
package main
import (
"testing"
"github.com/projectdiscovery/dnsx"
)
package main
import (
"testing"
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/wildcard_test.go` around lines 1 - 6, The test cannot access the
unexported function checkWildcard because it's in a different package; either
move the test into the same package as checkWildcard (so the test file lives
alongside the implementation and can call checkWildcard directly) or make
checkWildcard exported (rename to CheckWildcard) and refactor it into a testable
package (e.g., an internal package) so the test can import it; also remove the
unused github.com/projectdiscovery/dnsx import from the test file.


// Test function to check the wildcard detection
func TestCheckWildcard(t *testing.T) {
tests := []struct {
domain string
expected bool
}{
{"example.com", true},
{"nonwildcard.com", false},
}

for _, tt := range tests {
t.Run(tt.domain, func(t *testing.T) {
got := checkWildcard(tt.domain)
if got != tt.expected {
t.Errorf("checkWildcard() = %v, want %v", got, tt.expected)
}
})
}
}
Comment on lines +9 to +26
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Test design issues: non-deterministic and lacks mocking.

  1. Hardcoded expectations for real domains: The test assumes example.com is a wildcard domain and nonwildcard.com is not. DNS responses for real domains can change, making this test flaky and non-reproducible.

  2. No mocking: The function (once fixed) would make real DNS queries. Unit tests should mock external dependencies to ensure deterministic results and avoid network dependency.

  3. Compilation will fail: As noted above, checkWildcard is inaccessible from this package location.

Consider refactoring checkWildcard to accept a DNS client interface that can be mocked in tests.

Suggested approach with interface for testability
// Define interface for DNS querying
type DNSQuerier interface {
    QueryOne(hostname string) (*retryabledns.DNSData, error)
}

// Refactor checkWildcard to accept interface
func checkWildcard(client DNSQuerier, domain string) bool {
    // implementation
}

// In tests, use a mock implementation
type mockDNSClient struct {
    responses map[string]*retryabledns.DNSData
}

func (m *mockDNSClient) QueryOne(hostname string) (*retryabledns.DNSData, error) {
    if resp, ok := m.responses[hostname]; ok {
        return resp, nil
    }
    return nil, errors.New("NXDOMAIN")
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/wildcard_test.go` around lines 9 - 26, Test is non-deterministic and
failing to compile because it calls checkWildcard which does real DNS queries
and is inaccessible; refactor checkWildcard to accept a DNS client interface
(e.g., type DNSQuerier with QueryOne(hostname string) (*retryabledns.DNSData,
error)) or make it exported/accessible, update function signature
checkWildcard(client DNSQuerier, domain string) and adjust callers, then rewrite
TestCheckWildcard to use a mockDNSClient implementing DNSQuerier (with a
responses map and QueryOne returning preset DNSData or NXDOMAIN) and assert
deterministic true/false outcomes instead of querying real domains.