|
7 | 7 | "github.com/stretchr/testify/require" |
8 | 8 | ) |
9 | 9 |
|
| 10 | +// TestManagerValidate verifies the Manager's Validate method with various scope configurations, |
| 11 | +// including URL pattern matching and host-based DNS validation for different scope types (dn, rdn, fqdn). |
10 | 12 | func TestManagerValidate(t *testing.T) { |
11 | 13 | t.Run("url", func(t *testing.T) { |
12 | 14 | manager, err := NewManager([]string{`example`}, []string{`logout\.php`}, "dn", false) |
@@ -72,9 +74,80 @@ func TestManagerValidate(t *testing.T) { |
72 | 74 | }) |
73 | 75 | } |
74 | 76 |
|
| 77 | +// TestGetDomainRDNandDN verifies the extraction of root domain name (RDN) and |
| 78 | +// effective top-level domain plus one label (eTLD+1) from a hostname. |
75 | 79 | func TestGetDomainRDNandDN(t *testing.T) { |
76 | 80 | rdn, dn, err := getDomainRDNandRDN("test.projectdiscovery.io") |
77 | 81 | require.Nil(t, err, "could not get domain rdn and dn") |
78 | 82 | require.Equal(t, "projectdiscovery.io", rdn, "could not get correct rdn") |
79 | 83 | require.Equal(t, "projectdiscovery", dn, "could not get correct dn") |
80 | 84 | } |
| 85 | + |
| 86 | +// TestNoScopeWithOutOfScope verifies that when noScope is enabled, host-based |
| 87 | +// DNS validation is bypassed while URL pattern matching (inScope/outOfScope rules) |
| 88 | +// continues to function correctly. It tests scenarios with only outOfScope patterns |
| 89 | +// and with both inScope and outOfScope patterns to ensure proper filtering behavior. |
| 90 | +func TestNoScopeWithOutOfScope(t *testing.T) { |
| 91 | + t.Run("noScope with outOfScope rules", func(t *testing.T) { |
| 92 | + // Create manager with noScope=true and outOfScope patterns |
| 93 | + outOfScopePatterns := []string{ |
| 94 | + `logout\.php`, |
| 95 | + `/admin/`, |
| 96 | + `\.js$`, |
| 97 | + `^https?://[^/]+/\?lang=[a-z]{2}`, |
| 98 | + } |
| 99 | + manager, err := NewManager(nil, outOfScopePatterns, "rdn", true) |
| 100 | + require.NoError(t, err, "could not create scope manager with noScope and outOfScope") |
| 101 | + |
| 102 | + // Test 1: URL from different domain should be allowed (noScope ignores DNS) |
| 103 | + parsed, _ := urlutil.Parse("https://completely-different.com/index.php") |
| 104 | + validated, err := manager.Validate(parsed.URL, "original.com") |
| 105 | + require.NoError(t, err, "could not validate cross-domain URL with noScope") |
| 106 | + require.True(t, validated, "cross-domain URL should be allowed with noScope") |
| 107 | + |
| 108 | + // Test 2: URL matching outOfScope pattern should be rejected |
| 109 | + parsed, _ = urlutil.Parse("https://completely-different.com/logout.php") |
| 110 | + validated, err = manager.Validate(parsed.URL, "original.com") |
| 111 | + require.NoError(t, err, "could not validate outOfScope URL") |
| 112 | + require.False(t, validated, "outOfScope pattern should still be applied with noScope") |
| 113 | + |
| 114 | + // Test 3: Normal URLs should be allowed |
| 115 | + parsed, _ = urlutil.Parse("https://any-site.com/products/item123") |
| 116 | + validated, err = manager.Validate(parsed.URL, "original.com") |
| 117 | + require.NoError(t, err, "could not validate normal URL") |
| 118 | + require.True(t, validated, "normal URLs should be allowed") |
| 119 | + }) |
| 120 | + |
| 121 | + t.Run("noScope with both inScope and outOfScope", func(t *testing.T) { |
| 122 | + // Test combining noScope with both inScope and outOfScope |
| 123 | + inScopePatterns := []string{`/api/`, `/products/`} |
| 124 | + outOfScopePatterns := []string{`/api/internal/`, `\.css$`} |
| 125 | + |
| 126 | + manager, err := NewManager(inScopePatterns, outOfScopePatterns, "fqdn", true) |
| 127 | + require.NoError(t, err, "could not create manager with both scope types") |
| 128 | + |
| 129 | + // Should be allowed: matches inScope, doesn't match outOfScope |
| 130 | + parsed, _ := urlutil.Parse("https://external.com/api/users") |
| 131 | + validated, err := manager.Validate(parsed.URL, "original.com") |
| 132 | + require.NoError(t, err, "could not validate API endpoint") |
| 133 | + require.True(t, validated, "API endpoint should be allowed") |
| 134 | + |
| 135 | + // Should be rejected: matches both inScope and outOfScope (outOfScope wins) |
| 136 | + parsed, _ = urlutil.Parse("https://external.com/api/internal/secrets") |
| 137 | + validated, err = manager.Validate(parsed.URL, "original.com") |
| 138 | + require.NoError(t, err, "could not validate internal API") |
| 139 | + require.False(t, validated, "internal API should be excluded by outOfScope") |
| 140 | + |
| 141 | + // Should be rejected: doesn't match inScope |
| 142 | + parsed, _ = urlutil.Parse("https://external.com/about/company") |
| 143 | + validated, err = manager.Validate(parsed.URL, "original.com") |
| 144 | + require.NoError(t, err, "could not validate about page") |
| 145 | + require.False(t, validated, "about page should be rejected (not in inScope)") |
| 146 | + |
| 147 | + // Should be rejected: matches outOfScope |
| 148 | + parsed, _ = urlutil.Parse("https://external.com/styles/main.css") |
| 149 | + validated, err = manager.Validate(parsed.URL, "original.com") |
| 150 | + require.NoError(t, err, "could not validate CSS file") |
| 151 | + require.False(t, validated, "CSS files should be excluded") |
| 152 | + }) |
| 153 | +} |
0 commit comments