SonarSource/sonarqube · error · IllegalArgumentException
Invalid URL: loopback, wildcard, link-local, site-local…
Error message
Invalid URL: loopback, wildcard, link-local, site-local, multicast, cloud metadata addresses and addresses of the SonarQube server itself are not allowed for webhooks.
What it means
Thrown by WebhookSupport.checkUrlPattern (via WebhookAddressValidator.INVALID_ADDRESS_MESSAGE) when the resolved webhook host points to a blocked address: loopback, wildcard, link-local, site-local, multicast, cloud metadata, or the SonarQube server itself. This SSRF protection applies when sonar.validate.webhooks (or the configured property) is enabled, which is the default.
Solutions
- Use a public HTTPS URL for the webhook receiver, or a DNS name that resolves to a public address.
- If internal webhooks are intentionally required, set sonar.validate.webhooks=false in sonar.properties (understand the SSRF trade-off) and restart.
- Expose the internal receiver through a public reverse proxy/relay instead.
Example fix
// before curl -u $TOKEN -X POST "$SONAR/api/webhooks/create?name=ci&url=http://localhost:9001/hook" // blocked // after # allow internal (trusted network) by disabling validation in sonar.properties: # sonar.validate.webhooks=false curl -u $TOKEN -X POST "$SONAR/api/webhooks/create?name=ci&url=https://ci.example.com/sonarqube/hook"
Defensive patterns
Strategy: validation
Validate before calling
InetAddress addr = InetAddress.getByName(host);
if (addr.isLoopbackAddress() || addr.isAnyLocalAddress() || addr.isLinkLocalAddress()
|| addr.isSiteLocalAddress() || addr.isMulticastAddress()
|| host.equals("169.254.169.254")) {
throw new IllegalArgumentException("Webhook URL points to a blocked/internal address");
} Try / catch
try {
createWebhook(name, url);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("not allowed for webhooks")) {
throw new ConfigurationException("Use a public webhook URL or disable sonar.validate.webhooks for trusted internal networks");
}
} Prevention
- Point webhooks at public endpoints; expose internal receivers through a public proxy.
- Document why sonar.validate.webhooks is disabled if you must disable SSRF protection.
- Resolve the hostname in staging to confirm it is not loopback/link-local/site-local.
When it happens
Trigger: Creating/updating a webhook whose URL host resolves to 127.0.0.1/localhost, 0.0.0.0, 169.254.x.x (including the 169.254.169.254 cloud metadata endpoint), 10.x/172.16-31.x/192.168.x addresses, multicast ranges, or the SonarQube server's own address.
Common situations: Pointing webhooks at an internal CI listener (e.g. http://localhost:9001/hook) in a containerized/on-prem setup; administrators disabling the validation property to allow internal hosts when they control the network; Kubernetes setups where the internal service IP is site-local.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Address contains invalid character: 0x%02x
- Authentication is not enforced, and permissions assigned to…
- Default Administrator credentials are still being used…
- ############################################################…
- Failed to setup SSL context on ES client
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/8dccfdf82c7e9f10.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/WebhookSupport.java:68
userSession.checkEntityPermission(ProjectPermission.ADMIN, projectDto);
}
void checkPermission() {
userSession.checkPermission(GlobalPermission.ADMINISTER);
}
void checkUrlPattern(String url, String message, Object... messageArguments) {
try {
HttpUrl okUrl = HttpUrl.parse(url);
if (okUrl == null) {
throw new IllegalArgumentException(String.format(message, messageArguments));
}
InetAddress address = InetAddress.getByName(okUrl.host());
if (configuration.getBoolean(SONAR_VALIDATE_WEBHOOKS_PROPERTY)
.orElse(SONAR_VALIDATE_WEBHOOKS_DEFAULT_VALUE)
&& WebhookAddressValidator.isBlockedAddress(address, networkInterfaceProvider)) {
throw new IllegalArgumentException(WebhookAddressValidator.INVALID_ADDRESS_MESSAGE);
}
} catch (UnknownHostException e) {
// if a host can not be resolved the deliveries will fail - no need to block it from being set
// this will only happen for public URLs
} catch (SocketException e) {
throw new IllegalStateException("Can not retrieve a network interfaces", e);
}
}
}
View on GitHub (pinned to 184c821202)