crowdsecurity/crowdsec · error
source is nil or not an IP
Error message
source is nil or not an IP
What it means
GeoIPEnrichSource populates a models.Source with ASN/country/coordinates GeoIP data, but only makes sense for IP-scoped sources. It refuses to run when the source pointer is nil or the source's Scope is not types.Ip. This is a defensive guard against enriching non-IP entities (e.g. range or user scopes).
Source
Thrown at pkg/appsec/challenge_alert.go:92
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
meta := make(models.Meta, 0, len(keys))
for _, k := range keys {
meta = append(meta, &models.MetaItems0{Key: k, Value: m[k]})
}
return meta
}
// GeoIPEnrichSource fills a models.Source (IP scope) with GeoIP data — ASN,
// country, coordinates, range — from the shared exprhelpers GeoIP databases.
func GeoIPEnrichSource(src *models.Source) error {
if src == nil || src.Scope == nil || *src.Scope != types.Ip {
return errors.New("source is nil or not an IP")
}
asndata, err := exprhelpers.GeoIPASNEnrich(src.IP)
if err != nil {
return err
} else if asndata != nil {
record := asndata.(*geoip2.ASN)
src.AsName = record.AutonomousSystemOrganization
src.AsNumber = fmt.Sprintf("%d", record.AutonomousSystemNumber)
}
cityData, err := exprhelpers.GeoIPEnrich(src.IP)
if err != nil {
return err
} else if cityData != nil {
record := cityData.(*geoip2.City)
src.Cn = record.Country.IsoCode
src.Latitude = float32(record.Location.Latitude)View on GitHub (pinned to 909b515798)
Solutions
- Set src.Scope to a pointer to types.Ip before calling GeoIPEnrichSource
- Ensure the models.Source is fully constructed (non-nil) before enrichment
- Guard the call site: skip GeoIP enrichment when the source scope is not IP
Example fix
// before
src := &models.Source{IP: "1.2.3.4"}
err := GeoIPEnrichSource(src)
// after
ipScope := types.Ip
src := &models.Source{IP: "1.2.3.4", Scope: &ipScope}
err := GeoIPEnrichSource(src) Defensive patterns
Strategy: validation
Validate before calling
if src == nil || src.Scope == nil || *src.Scope != types.Ip {
// skip enrichment or construct a proper IP-scoped source
return nil
}
if err := GeoIPEnrichSource(src); err != nil { ... } Type guard
func isIPSource(src *models.Source) bool {
return src != nil && src.Scope != nil && *src.Scope == types.Ip
} Try / catch
if err := GeoIPEnrichSource(src); err != nil {
log.Warnf("geoip enrichment skipped: %s", err)
} Prevention
- Always set Scope to types.Ip when building models.Source from an IP address
- Use a constructor helper for models.Source so Scope is never forgotten
- Only call enrichment on alert sources known to be IP-scoped
When it happens
Trigger: Calling GeoIPEnrichSource(src) with src == nil; or with a *models.Source whose Scope is nil; or whose *Scope is anything other than types.Ip (e.g. 'range'). Reached via AppsecEventGeneration or buildChallengeAlert when the appsec event carries a malformed/absent source.
Common situations: Custom appsec code paths building a models.Source by hand and forgetting to set Scope to Ip; a parser/evaluator emitting a challenge alert for an event that never had an IP source; refactors that changed the Source struct and left Scope unset.
Related errors
- no appsec rules in hub index
- ErrNucleiTemplateFail
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
- missing lapi client credentials
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/3e65bf0daaf1f646.
Report an issue: GitHub.