Spring AI 2.0.1: 7 CVEs Fixed, 80+ Changes, Tool Call Limits & Audio Streaming

Spring AI 2.0.1 patches seven critical CVEs, adds tool call limits and OpenAI audio streaming, updates Google GenAI with image generation, and includes breaking changes like Redis module rename and OpenAI strict mode default off across 80+ issues and PRs.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Spring AI 2.0.1: 7 CVEs Fixed, 80+ Changes, Tool Call Limits & Audio Streaming

Security Fixes

Spring AI 2.0.1 addresses seven CVEs:

CVE-2026-47851 — Uncontrolled recursion in PDF document reader via attacker-controlled PDF outline tree.

CVE-2026-47852 — Predictable cache directory path allows replacement of local ONNX models.

CVE-2026-59279 — Repeated initialization requests cause unbounded persistent session allocation.

CVE-2026-59294 — Path traversal in ResourceCacheService enables arbitrary file write.

CVE-2026-59308 — Semantic cache bypasses cross-tenant isolation due to SHA-256 truncation.

CVE-2026-59319 — RediSearch tag injection in RedisChatMemoryRepository leads to cross-session data leakage.

CVE-2026-59318 — Global resolver fallback in DefaultToolCallingManager can be exploited via prompt injection to invoke undeclared tools.

Upgrade Notes (Breaking Changes)

Most applications only need to bump the version to 2.0.1, but the following changes require attention:

Deprecated Mistral AI chat models removed (#6772). Switch to currently supported model names if referencing deprecated constants.

Redis chat memory auto-configuration module renamed (#6416) to align with spring-ai-autoconfigure-* naming. Update artifact ID in build files:

OpenAI tool calling strict mode default changed to false (#6755). Previously, generated schemas omitted optional fields from required, causing 400 errors under strict mode. Now strict mode is off by default, matching OpenAI API defaults. Enable explicitly if your schema complies.

Media builder uses typed data overloads (#6481). The generic data(Object) is replaced with data(byte[]), data(String), data(URI), data(URL), data(Resource). Code calling .data(...) with static type Object will not compile; narrow the type first.

DeepSeekApi refactored (#6428) for consistency with other API clients.

Couchbase vector store now reuses Spring Boot managed Couchbase client (#6583), respecting declared cluster configuration instead of creating its own client.

New Features

Tool Call Limits

An unbounded agentic loop is a costly failure mode. ToolCallingAdvisor now supports a per-request tool call limit, throwing ToolCallLimitExceededException when exceeded. The exception handling path returns a single Generation, keeping error structure consistent with normal responses. Tool resolution fallback is now configurable: decide whether to fail fast or fall back when a tool name cannot be resolved.

OpenAI Audio

OpenAiAudioSpeechModel

supports audio streaming output and adds an instructions option to control voice style. Transcription configuration options and response content are expanded, covering more OpenAI API capabilities.

Google GenAI

Added ToolChoice support to force, disable, or let the model decide tool calls. Image generation is now available via the standard ImageModel abstraction.

Document Reading

PagePdfDocumentReader

supports page range selection, allowing partial ingestion of large documents. TokenTextSplitter validates builder parameters upfront instead of throwing cryptic errors later.

AWS Region Resolution

Two long-standing issues resolved: Spring AI now follows AWS SDK default region resolution rules and no longer prints confusing WARN logs during region resolution. Bedrock region configuration via environment variables or profiles now behaves consistently with other AWS stack components.

Optimizations

1. Redis Chat Memory Module Rename (detailed)

Artifact: spring-ai-autoconfigure-model-chat-memory-redisspring-ai-autoconfigure-model-chat-memory-repository-redis Config prefix: spring.ai.chat.memory.redis.*spring.ai.chat.memory.repository.redis.* Smooth transition: old module and config prefix delegate to new ones; migration recommended before future removal.

2. Tool Call Limits Defaults

DefaultToolCallingManager

now enforces a default per-tool limit of 40 calls ( DEFAULT_MAX_CALLS_PER_TOOL) and a total limit of 150 calls ( DEFAULT_MAX_TOTAL_TOOL_CALLS). Previously there were no limits. Most apps won't notice; adjust via ToolCallingManager.builder().maxCallsPerTool(...) / .unlimitedCallsPerTool() or spring.ai.tools.limits.* properties.

3. ToolCallingAdvisor Token Usage Accumulation

Previously only the last model call's Usage was exposed. Now token usage across all internal model calls in the tool loop is accumulated. Tests asserting exact token counts will see higher values; no API changes required.

4. OpenAI Strict Mode Default Off (detailed)

OpenAiChatModel

no longer defaults to strict(true). The JsonSchemaGenerator represents optional fields by omitting them from required, but OpenAI strict mode requires optional fields to be nullable and still present in required, causing 400 errors for any tool with optional parameters. To re-enable strict mode:

OpenAiChatOptions options = OpenAiChatOptions.builder()
    .strict(true)
    .build();

When enabled, optional parameters are automatically made nullable and added back to required to satisfy strict schema conventions.

5. OpenAI Audio Streaming Behavior Change

OpenAiAudioSpeechModel.stream(TextToSpeechPrompt)

previously buffered the entire response and emitted a single Flux element. Now it requests stream_format=audio and emits true chunked streams. Code using blockFirst() to get the full audio will only receive the first chunk; concatenate all chunks instead.

6. TranscriptionModel Extends StreamingTranscriptionModel

Streaming transcription becomes a first-class capability for all transcription models. Default implementation returns a Flux throwing UnsupportedOperationException, so existing custom implementations compile unchanged. To support real streaming, override stream(AudioTranscriptionPrompt).

7. Media.Builder.data(Object) Split into Typed Overloads

As noted in upgrade notes, the single data(Object) method is replaced by typed overloads for byte[], String, URI, URL, Resource. Call sites with static type Object must be narrowed to a concrete type.

8. Tool Resolution Fallback Default Off

Previously, when a tool call was not attached to the request, DefaultToolCallingManager fell back to the application-level ToolCallbackResolver (all ToolCallback beans) to resolve and execute the tool. From 2.0.1, only tools explicitly attached to the request (via .tools(...), .defaultTools(...), or ToolCallingChatOptions.toolCallbacks(...)) are executable. To restore old behavior, set:

spring.ai.tools.resolution.fallback.enabled=true

Or when building ToolCallingManager directly:

ToolCallingManager toolCallingManager = ToolCallingManager.builder()
    .toolCallbackResolver(toolCallbackResolver)
    .resolutionFallbackEnabled(true) // default is false
    .build();
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

RedissecurityOpenAISpring AICVEbreaking changestool callingaudio streaming2.0.1Google GenAI
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.