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

  1. Replace the hostname with a literal IP address or CIDR range (e.g. 203.0.113.0/24)
  2. If DNS must be used, accept that resolution is fixed at startup and restart on DNS changes
  3. 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

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


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/834f85d307e0be83. Report an issue: GitHub.