Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/common/honeypotdetector/honeypotdetector_test.go
4538 views
1
package honeypotdetector
2
3
import (
4
"fmt"
5
"sync"
6
"sync/atomic"
7
"testing"
8
9
"github.com/stretchr/testify/require"
10
)
11
12
func TestThresholdBoundary(t *testing.T) {
13
t.Parallel()
14
15
d := New(2)
16
host := "example.com"
17
18
require.False(t, d.RecordMatch(host, "t1"), "flagging should not happen at N-1 matches")
19
require.True(t, d.RecordMatch(host, "t2"), "flagging should happen at exactly N distinct template IDs")
20
require.True(t, d.IsFlagged(host))
21
22
// Once flagged, additional distinct matches should not re-trigger the boundary condition.
23
require.False(t, d.RecordMatch(host, "t3"))
24
}
25
26
func TestDeduplication(t *testing.T) {
27
t.Parallel()
28
29
d := New(2)
30
host := "example.com"
31
32
require.False(t, d.RecordMatch(host, "t1"))
33
require.False(t, d.RecordMatch(host, "t1"), "same templateID on same host must count once")
34
require.True(t, d.RecordMatch(host, "t2"))
35
require.True(t, d.IsFlagged(host))
36
}
37
38
func TestHostIsolation(t *testing.T) {
39
t.Parallel()
40
41
d := New(2)
42
43
require.False(t, d.RecordMatch("example-a.com", "t1"))
44
require.False(t, d.RecordMatch("example-b.com", "t1"))
45
require.True(t, d.RecordMatch("example-a.com", "t2"), "host A should be flagged independently")
46
47
require.True(t, d.IsFlagged("example-a.com"))
48
require.False(t, d.IsFlagged("example-b.com"))
49
}
50
51
func TestConcurrentAccess(t *testing.T) {
52
t.Parallel()
53
54
const (
55
threshold = 10
56
goroutines = 100
57
)
58
59
d := New(threshold)
60
host := "example.com"
61
62
var justFlaggedCount atomic.Int32
63
var wg sync.WaitGroup
64
wg.Add(goroutines)
65
66
for i := 0; i < goroutines; i++ {
67
i := i
68
go func() {
69
defer wg.Done()
70
if d.RecordMatch(host, fmt.Sprintf("t-%d", i)) {
71
justFlaggedCount.Add(1)
72
}
73
}()
74
}
75
76
wg.Wait()
77
78
require.True(t, d.IsFlagged(host))
79
require.Equal(t, int32(1), justFlaggedCount.Load(), "exactly one goroutine should trigger the boundary")
80
}
81
82
func TestHostNormalization(t *testing.T) {
83
t.Parallel()
84
85
d := New(2)
86
87
// Scheme + trailing slash must be stripped so these map to the same normalized host.
88
require.False(t, d.RecordMatch("https://example.com/", "t1"))
89
require.True(t, d.RecordMatch("http://example.com", "t2"))
90
require.True(t, d.IsFlagged("example.com"))
91
92
// Explicit port should keep it distinct (example.com and example.com:443 are different keys).
93
d2 := New(1)
94
require.True(t, d2.RecordMatch("example.com:443", "t1"))
95
require.True(t, d2.IsFlagged("example.com:443"))
96
require.False(t, d2.IsFlagged("example.com"), "host without explicit port must not share the same key")
97
98
// IPv6 should be canonicalized, and bracketed host:port should keep bracketed form when port is present.
99
d3 := New(1)
100
require.True(t, d3.RecordMatch("http://[2001:db8::1]/", "t1"))
101
require.True(t, d3.IsFlagged("2001:db8::1"))
102
require.True(t, d3.IsFlagged("[2001:db8::1]"))
103
104
d4 := New(1)
105
require.True(t, d4.RecordMatch("[2001:db8::1]:443", "t1"))
106
require.True(t, d4.IsFlagged("[2001:db8::1]:443"))
107
require.False(t, d4.IsFlagged("2001:db8::1"), "IPv6 with explicit port must not share the same key as IPv6 without port")
108
}
109
110