Geolocation
runZero resolves a geographic location for every asset it has enough information about, and those locations drive the World Map, inventory search, and exports. This page covers the sources runZero uses for asset geolocation, how it interprets your location tags, and the order in which it applies the sources.
Where locations come from
runZero builds asset locations from five independent sources during each analysis pass. It records every location with its provenance, so you can trace each pin on the World Map back to the attribute, integration, or tag that produced it.
| Source | Description |
|---|---|
attribute-coord | Paired numeric latitude/longitude attributes from integrations or imports. |
attribute-ip | Egress / public IP addresses resolved through MaxMind GeoLite2. |
attribute-text | Discrete country / city attributes, plus free-form snmp.sysLocation-style strings. |
cloud-region | AWS, Azure, GCP, OCI, IBM Cloud, and DigitalOcean region codes resolved to a region centroid. |
geolite-isp | GeoIP lookup of the asset's primary scanned IP through MaxMind GeoLite2. |
manual | User-supplied geo* asset tags. |
An asset can carry locations from more than one source at a time. For example, a cloud workload may have a cloud-region location from its AWS region, an attribute-ip location from its public NAT address, and a manual location set by a tag. All three appear as separate pins on the World Map, each labelled with its source.
When multiple sources agree on the same coordinate, runZero de-duplicates the entry.
GeoIP lookups against MaxMind
runZero ships with the MaxMind GeoLite2 City and ASN databases and uses them to resolve any public IP address it observes for an asset into a latitude, longitude, country, subdivision (state/province), city, postal code, timezone, continent, ASN number, and ASN organization name.
GeoIP lookups reject private RFC1918 and RFC6598 addresses, so a private IP never produces a location.
Primary and hinted external IPs
When runZero scans an asset, it records the public IP it observed for that asset. It looks up the primary scanned address directly against GeoLite2, which produces a location with source geolite-isp.
When passive sources or integrations report additional public addresses for the same asset (for example, a secondary NAT address or an alternate egress on a multi-homed device), runZero looks those up too. It records the resulting locations alongside the primary, so an asset visible at two different egress points appears in both places on the World Map.
Egress and public-IP attributes from integrations
Many integrations report the public, external, or NAT IP address an asset was observed from. runZero ingests these and resolves each one through GeoLite2, which produces both a city-level location and an ASN annotation for the pin.
The egress IP pipeline reads these attributes:
| Attribute | Set by |
|---|---|
externalIP |
CrowdStrike, SentinelOne |
publicIP |
Azure (VM/database/load balancer), Microsoft Defender for Endpoint, AWS |
publicIPs |
AWS |
natIP |
Google Cloud Platform |
wanIPAddresses |
Google Workspace |
discover.externalIP |
CrowdStrike |
runZero also writes the full set of unique public IPs seen across these attributes back to the asset as an egressIPs attribute, so you can query the underlying values directly.
Cloud region codes
When an integration provides a cloud region code (for example, AWS us-east-1, Azure eastus, or GCP europe-west4), runZero maps the code to the published centroid of that region. This gives the asset a country, subdivision (where applicable), city, and continent without a GeoIP lookup.
The cloud region pipeline reads from attributes including region, cloud.region, aws.region, azure.region, azure.location, gcp.region, gcp.zone, oci.region, availabilityZone, availability_zone, zone, placement.region, and placement.availabilityZone. runZero ignores unknown values (for example, a generic region=Northeast tag).
Discrete country and city attributes
Some integrations report location as separate country (or countryCode) and city fields. runZero pairs them and resolves the combination to the matching GeoNames city centroid. If only a city is present, runZero uses the highest-population match worldwide.
The country fields runZero reads are: country, countryCode, country_code, host.country, host.countryCode, host.location.country, host.location.countryCode, discover.country, discover.countryCode, custom.country, and site.country.
The city fields runZero reads are: city, host.city, host.location.city, discover.city, custom.city, and site.city.
Free-form location strings
runZero parses free-form location strings from SNMP and integrations on a best-effort basis. The parser strips address noise (house numbers, suite/floor markers, PO boxes, postal codes, and street suffixes like St, Ave, and Blvd) and matches the remaining trailing tokens against the bundled GeoNames tables.
The free-form attributes runZero reads are: location, host.location, site.location, custom.location, location.address, snmp.sysLocation, and shodan.snmp.location.
The best-effort approach is deliberate: SNMP sysLocation has no standardized format, and many devices report a campus or rack identifier rather than an address. When the parser cannot anchor the string to a known city, region, or country, it records no location.
Manually setting an asset location
To pin an asset to a specific geographic location, set one of the geo* tags below. Each tag has a fixed shape, and its value tells runZero where the asset is. The location appears on the World Map, in exports, and in queries the next time runZero recalculates metrics for the asset.
Manual geo* tags do not take effect immediately. runZero picks them up the next time it recalculates metrics for the asset, which happens automatically during normal task processing (scans, integration syncs, and scheduled metrics tasks). To apply the change right away, go to Dashboard > Recalculate metrics.
The short version: set one tag, and use
/to separate fields.geoCity = Austin/TX/US geoCity = Springfield/IL/US geoLatLng = 30.2672/-97.7431
Available tags
| Tag | Shape | Example |
|---|---|---|
geoLatLng |
lat/lng |
geoLatLng = 30.2672/-97.7431 |
geoContinent |
continent name or two-letter alias (EU, NA, …) |
geoContinent = Europe |
geoCountry |
country (see Country values) | geoCountry = US |
geoRegionCountry |
region/country |
geoRegionCountry = TX/US |
geoRegion |
region/country or a single token (state, country, or continent) |
geoRegion = Texas |
geoState |
alias of geoRegion |
geoState = TX/US |
geoProvince |
alias of geoRegion |
geoProvince = Ontario |
geoCity |
city/country or city/region/country |
geoCity = Austin/US |
You only need to set one tag per asset. If you set more than one, runZero uses whichever tags match their shape. runZero silently ignores tags whose values do not match their expected shape; it will not guess.
When to use which tag
- Use
geoLatLngif you have exact coordinates from a CMDB, building floor plan, or GPS source. - Use
geoContinentwhen you only know the continent. - Use
geoCountrywhen you only know the country. - Use
geoRegionCountrywhen you know the country and the state/province/region but not the city. - Use
geoRegion(or its synonymsgeoState/geoProvince) when you want runZero to accept any plausible region-ish value: aregion/countrypair, a unique state name (Texas,Ontario,Bavaria), a country code, or a continent. - Use
geoCityin every other case. The two-field form is enough for major cities; use the three-field form to disambiguate names likeSpringfield,Portland, orCambridge.
Field separator
The separator between fields is always a forward slash (/). The characters -, ., ,, and _ are not field separators, because they appear inside real city and region names: Winston-Salem, St. Louis, Stratford-upon-Avon, St-Lawrence.
geoCity = Austin/US ✓ city/country
geoCity = Austin TX US ✗ no separators
geoCity = Austin-TX-US ✗ hyphen is part of names, not a separator
geoCity = Austin,TX,US ✗ comma is part of names, not a separator
If you set a tag through the UI or API and the value contains spaces, runZero stores those spaces as underscores. The parser treats _ and a space the same inside a field, so geoCity = San Francisco/CA/US and geoCity = San_Francisco/CA/US parse identically.
Country values
Any of these forms work for the country field:
| Form | Examples |
|---|---|
| ISO 3166-1 alpha-2 | US, DE, GB, JP |
| ISO 3166-1 alpha-3 | USA, DEU, GBR, JPN |
| English name | United States, Germany, Japan |
| Common alias | UK and Britain (both normalize to GB) |
Country values are case-insensitive. When runZero recognizes an alias, it normalizes it to the ISO alpha-2 code shown on the map.
Region values
Region values are state, province, or admin region names. runZero recognizes both short codes and full names for the countries below; for other countries, runZero accepts the GeoNames admin1 code directly (often a numeric value like 02 or 16).
| Country | Examples of accepted region values |
|---|---|
| United States | TX, Texas, CA, California |
| Canada | ON, Ontario, BC, British Columbia, Québec |
| Australia | NSW, New South Wales, VIC, Victoria |
| United Kingdom | England, Scotland, Wales, Northern Ireland |
| Ireland | Connacht, Leinster, Munster, Ulster |
| New Zealand | Auckland, Canterbury, Wellington |
If runZero does not recognize the region, the asset still resolves at the country level. The region tag adds information but never blocks resolution.
City matching and GeoNames
runZero matches cities and regions against the bundled GeoNames data. The matcher is fuzzy: St. Louis, St Louis, St-Louis, Saint Louis, and saint_louis all resolve to the same record. The map and exports show the canonical GeoNames spelling, so your tag values do not need perfect formatting to look right.
When a city name is ambiguous (Springfield, Cambridge, Portland), use the three-field form to disambiguate:
geoCity = Springfield/IL/US ✓ disambiguated
geoCity = Springfield/MO/US ✓ different city
geoCity = Springfield/US ⚠ resolves to whichever Springfield is largest
Examples
Pinning a corporate office:
geoCity = Austin/TX/US
A device with exact coordinates:
geoLatLng = 30.2672/-97.7431
A subnet known to be in Germany, city unknown:
geoCountry = DE
A device in a known region, city unknown:
geoRegionCountry = Bayern/DE
What happens if the value is wrong?
Each tag has a fixed shape and a strict matcher. When the value does not fit the shape, or names a place that runZero’s bundled GeoNames data does not recognize, the tag produces no manual location and no manual pin appears on the map for that asset.
This is intentional. To debug:
- Confirm the field separator is
/, not-,., or,. - Confirm the country value resolves (try the ISO alpha-2 code).
- For
geoCity, try the three-field form to disambiguate the city. - As a last resort, use
geoLatLngwith explicit coordinates.
Searching by location in the asset inventory
The asset inventory supports a geo keyword (with synonyms geo_within and geo_radius) that matches assets whose geolocation falls inside a circular area:
geo:<lat>,<lon>[,<radius>]
<lat>and<lon>are decimal degrees (30.2672,-97.7431).<radius>is optional and defaults to 50 km. Supply a number followed bykm,mi, orm(for example25km,15mi,5000m). runZero treats plain numbers as kilometres.- runZero clamps the radius between 1 metre and 1,000 km.
Examples:
geo:30.2672,-97.7431 # within 50 km of downtown Austin
geo:30.2672,-97.7431,25km # within 25 km
geo:52.5200,13.4050,100mi # within 100 miles of Berlin
geo_within:51.5074,-0.1278,5km # synonym
The match is true if any location source on the asset falls inside the circle, so a workload with both a cloud region centroid and a public IP egress in the same metro area matches the same geo: query.
The same geo: keyword is available on the services inventory.
When locations are refreshed
runZero recalculates asset locations on every analysis pass. The new locations from each source replace the ones recorded before, so stale data (for example, a cloud-region attribute that an integration stopped reporting) disappears automatically on the next pass.
If you change a geo* tag value, the new location appears on the next analysis pass and not before.