spring-projects/spring-security · warning
Hostname '%s' resolved to %s will be used on IP address matc
Error message
Hostname '%s' resolved to %s will be used on IP address matching
What it means
IpInetAddressMatcher.matches CIDR/IP address patterns. In parse(), if the configured address contains letters (i.e. it is a hostname, not an IP), it is resolved via InetAddress.getByName and a warning is logged because hostname resolution happens once at matcher construction; DNS changes afterwards are ignored, which can surprise developers.
Source
Thrown at core/src/main/java/org/springframework/security/util/matcher/IpInetAddressMatcher.java:77
String[] parts = Objects.requireNonNull(StringUtils.split(ipAddress, "/"));
requiredAddress = parts[0];
nMaskBits = Integer.parseInt(parts[1]);
}
else {
requiredAddress = ipAddress;
nMaskBits = -1;
}
this.requiredAddress = InetAddressParser.parseAddress(requiredAddress);
this.nMaskBits = nMaskBits;
Assert.isTrue(this.requiredAddress.getAddress().length * 8 >= this.nMaskBits, () -> String
.format("IP address %s is too short for bitmask of length %d", requiredAddress, this.nMaskBits));
}
private static InetAddress parse(String address) {
try {
InetAddress result = InetAddress.getByName(address);
if (address.matches(".*[a-zA-Z\\-].*$") && !address.contains(":")) {
logger.warn("Hostname '" + address + "' resolved to " + result.toString()
+ " will be used on IP address matching");
}
return result;
}
catch (UnknownHostException ex) {
throw new IllegalArgumentException(String.format("Failed to parse address '%s'", address), ex);
}
}
@Override
public boolean matches(@Nullable InetAddress toCheck) {
if (toCheck == null) {
return false;
}
if (this.nMaskBits < 0) {
return toCheck.equals(this.requiredAddress);
}
byte[] remAddr = toCheck.getAddress();View on GitHub (pinned to 96852e8860)
Solutions
- Replace the hostname with a literal IP address or CIDR range (e.g. 203.0.113.0/24)
- If DNS must be used, accept that resolution is fixed at startup and restart on DNS changes
- Implement a custom WebMatcher/authorization rule that re-resolves the hostname per request
Example fix
// before
.access("hasIpAddress('myapp.example.com')")
// after
.access("hasIpAddress('203.0.113.10')") // or CIDR: '203.0.113.0/24' Defensive patterns
Strategy: validation
Validate before calling
// Validate IP matcher inputs before configuring
String v = "myapp.example.com";
if (v.matches(".*[a-zA-Z\\-].*") && !v.contains(":")) {
throw new IllegalArgumentException("Use an IP/CIDR, not a hostname: " + v);
} Type guard
boolean isIpOrCidr(String s) {
return !s.matches(".*[a-zA-Z\\-].*") || s.contains(":"); // reject hostnames, allow IPv6
} Prevention
- Use literal IPs or CIDR ranges in hasIpAddress and IP matchers
- Remember hostname resolution is one-time at startup; document DNS freeze semantics
- Wrap dynamic-DNS clients with a custom matcher that re-resolves per request
When it happens
Trigger: An IP matcher is created (e.g. requestMatchers for hasIpAddress, or IP authorization rules) with a hostname like 'example.com' instead of an IP/CIDR, and it resolves successfully at construction time.
Common situations: Writing hasIpAddress('myhost.example.org') instead of an IP or CIDR; config with DNS names in allow/deny lists; environments where the resolved IP changes (dynamic DNS, load balancers).
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Cannot apply {configurer} to already built object
- managerPassword is required if managerDn is supplied
- org.springframework.security.config.annotation.method.config
- The Filter class {registeredFilter.getName()} does not have
- The Filter class {filter.getClass().getName()} does not have
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/834f85d307e0be83.
Report an issue: GitHub.