Known Issues
This page lists confirmed defects in the v1.0.0 source that make behavior differ from the design, and what to do until they are fixed.
Security and Availability
| Issue | Location | Impact | Workaround |
|---|---|---|---|
| Nil pointer panic when Redis fails during scoring | instance.go:156 |
dynamicScore returns nil, err; Check only logs the error, then reads score.IsBlock |
Use gin.Recovery() with Gin; net/http drops that connection |
| Proxy headers are trusted for the client IP | device.go getClientIP |
Forging X-Forwarded-For and similar headers bypasses rate limits, Block, and Deny, or impersonates an Allow-listed IP |
Have the front proxy overwrite or strip the headers; see Client IP Resolution |
Blocks become permanent when BlockTimeMin / BlockTimeMax is 0 |
block.go Add |
Unset values make block records never expire | Set both to positive values |
Designed Features That Never Run
| Feature | Location | Reason |
|---|---|---|
HighRiskCountry scoring |
geo.go:248 |
History parsing stores the country code in Country, but the comparison reads CountryCode, which is always empty |
Automatic Block.Add on a high score |
score.go:196 |
The condition is > 100, but calcScore already caps the total at 100 |
Escalating to Deny after BlockToBan requests while blocked |
instance.go:141 |
device.Is.Block returns 403 one step earlier, so the check never runs |
too_frequent_requests |
score.go:546 |
Needs 16 intervals while the list keeps at most 10; ScoreFrequencyRequest also has no default |
ScoreNormal |
type.go |
The field exists but nothing reads it |
Other Behavior Defects
| Issue | Location | Impact |
|---|---|---|
| Email CC is never delivered | deny.go:157 |
smtp.SendMail receives only To as recipients; CC appears only in the header |
Geo detection off when only CountryDB is set |
score.go:441 |
calcGeo requires CityDB |
| Debug string printed on every request | score.go:457 |
With GeoLite2 on, the location and key go through the standard log.Print, bypassing Logger |
Defaults written back into Config on the request path |
instance.go, score.go, geo.go |
Concurrent requests write the same fields, which go test -race reports as a data race |
| False rapid-move flag when alternating private and public IPs | geo.go |
Private records sit at (0, 0); see Geo Detection |
LoginFailure / NotFound404 count the request twice |
score.go |
Both run device identification again, so one request counts twice per minute |
Reproduction: Panic on Redis Outage
package main
import (
"fmt"
"net/http/httptest"
"strconv"
"time"
"github.com/alicebob/miniredis/v2"
golangIPSentry "github.com/pardnchiu/golang-ip-sentry"
)
func main() {
mr, err := miniredis.Run()
if err != nil {
panic(err)
}
port, _ := strconv.Atoi(mr.Port())
sentry, err := golangIPSentry.New(golangIPSentry.Config{
Redis: golangIPSentry.Redis{Host: mr.Host(), Port: port},
Parameter: golangIPSentry.Parameter{BlockTimeMin: time.Minute, BlockTimeMax: time.Hour},
})
if err != nil {
panic(err)
}
mr.Close()
defer func() { fmt.Println("recovered:", recover()) }()
r := httptest.NewRequest("GET", "https://example.com/", nil)
sentry.Check(r, httptest.NewRecorder())
}
Actual output:
recovered: runtime error: invalid memory address or nil pointer dereference