spring-projects/spring-ai · error · SecurityException
URL is not valid under strict validation rules:
Error message
URL is not valid under strict validation rules:
What it means
Thrown as SecurityException when a String media value fails URLValidator.isValidURLStrict in mapMediaToContentBlock. The library only accepts Strings that are either strictly valid http/https URLs or base64 data; anything failing strict URL validation is treated as base64, and if decode fails or validation is intended as URL this guard fires for rejected URLs (e.g. file://, ftp://, or otherwise non-conforming strings).
Source
Thrown at models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java:550
}
else if (media.getData() instanceof String text) {
if (text.startsWith("s3://")) {
sourceBuilder.s3Location(S3Location.builder().uri(text).build()).build();
}
else if (text.startsWith("http://") || text.startsWith("https://")) {
// Not base64
if (URLValidator.isValidURLStrict(text)) {
try {
byte[] bytes = this.mediaFetcher.fetch(URI.create(text));
sourceBuilder.bytes(SdkBytes.fromByteArrayUnsafe(bytes)).build();
}
catch (SecurityException | RestClientException e) {
throw new RuntimeException("Failed to read media data from URL: " + text, e);
}
}
else {
throw new SecurityException("URL is not valid under strict validation rules: " + text);
}
}
else {
// Assume it's base64-encoded image data
sourceBuilder.bytes(SdkBytes.fromByteArray(Base64.getDecoder().decode(text)));
}
}
else if (media.getData() instanceof URL url) {
try {
String protocol = url.getProtocol();
if (!"http".equalsIgnoreCase(protocol) && !"https".equalsIgnoreCase(protocol)) {
throw new SecurityException("Unsupported URL protocol: " + protocol);
}
byte[] bytes = this.mediaFetcher.fetch(url.toURI());
sourceBuilder.bytes(SdkBytes.fromByteArrayUnsafe(bytes)).build();
}
catch (SecurityException | RestClientException | URISyntaxException e) {View on GitHub (pinned to 98a7beda4f)
Solutions
- Read the file yourself and pass base64-encoded bytes as the media data.
- Use a proper http(s):// URL that passes strict validation.
- Use a java.net.URL object via Media with URL data (which goes through the URL branch) only with http/https.
- If the string is meant to be base64, verify it decodes cleanly (no 'data:' prefix, no whitespace).
Example fix
// before
new Media(MimeTypeUtils.IMAGE_PNG, "file:///images/cat.png");
// after
byte[] bytes = Files.readAllBytes(Path.of("/images/cat.png"));
new Media(MimeTypeUtils.IMAGE_PNG, Base64.getEncoder().encodeToString(bytes)); Defensive patterns
Strategy: validation
Validate before calling
if (data != null && !URLValidator.isValidURLStrict(data) && !isBase64(data)) {
throw new IllegalArgumentException("Media string is neither a valid strict URL nor base64");
} Type guard
boolean isSafeMediaString(String s) {
return s != null && (s.startsWith("https://") || s.startsWith("http://") || s.matches("[A-Za-z0-9+/=]+"));
} Try / catch
try {
model.call(prompt);
} catch (SecurityException e) {
if (e.getMessage().startsWith("URL is not valid")) { /* use base64 instead */ }
else throw e;
} Prevention
- Read local files into memory and send base64 instead of file:// URLs
- Only use http/https URLs as String media data
- Strip whitespace and data: prefixes from base64 strings
- Unit-test media strings against strict URL validation before deployment
When it happens
Trigger: Passing a Media with String data like 'file:///etc/passwd', 'ftp://host/img.png', or any string that strict validation rejects (missing scheme, disallowed characters). The else-branch throws this SecurityException before any base64 decoding is attempted.
Common situations: Developers try to load local files via file:// URLs into Bedrock prompts; others paste URLs with spaces or non-ASCII characters that fail strict validation; SSRF hardening intentionally rejects ftp/file schemes.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Unsupported URL protocol:
- Media URL response exceeds maximum allowed size of bytes
- URL host '' resolves to a blocked internal address:
- Failed to resolve host:
- Failed to read media data from URL:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/3e9caa59dd02e799.
Report an issue: GitHub.