CVE-2026-10783
Description
Gradio's Audio Cache Key Handler uses weak hashing, allowing different audio metadata to share cache directories, potentially leading to incorrect audio playback.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Gradio's Audio Cache Key Handler uses weak hashing, allowing different audio metadata to share cache directories, potentially leading to incorrect audio playback.
Vulnerability
A security flaw exists in the save_audio_to_cache function within Gradio's Audio Cache Key Handler, specifically affecting versions prior to the patch in [3]. The function generates cache keys based solely on the audio data's raw bytes, ignoring crucial metadata such as sample rate, format, and shape.
Exploitation
An attacker with local access can exploit this vulnerability by providing audio data with identical raw bytes but different metadata (e.g., different sample rates or formats) to the save_audio_to_cache function. This manipulation causes these distinct audio outputs to resolve to the same cache directory, as demonstrated in [2]. The attack requires local access and is indicated to have high complexity and be difficult to exploit.
Impact
Successful exploitation allows an attacker to cause non-equivalent audio outputs to share a cache namespace. This can lead to incorrect audio files being served or played back, potentially resulting in a denial-of-service or unexpected behavior for users interacting with the affected audio components.
Mitigation
A patch, referenced as PR #13394 [3], has been developed to fix this issue by including audio metadata in the cache key. Users are recommended to deploy this patch. The exact fixed version and release date are not explicitly stated in the provided references, but the patch was proposed on May 16, 2026.
AI Insight generated on Jun 4, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: =6.14.0
Patches
11c609af6918bFix audio cache keys to include metadata (#13394)
3 files changed · +57 −1
.changeset/lucky-hands-notice.md+5 −0 added@@ -0,0 +1,5 @@ +--- +"gradio": patch +--- + +fix:Fix audio cache keys to include metadata
gradio/processing_utils.py+12 −1 modified@@ -183,7 +183,18 @@ def save_img_array_to_cache( def save_audio_to_cache( data: np.ndarray, sample_rate: int, format: str, cache_dir: str ) -> str: - temp_dir = Path(cache_dir) / hash_bytes(data.tobytes()) + audio_metadata = { + "cache_schema": "audio-cache-v1", + "dtype": str(data.dtype), + "format": format, + "sample_rate": int(sample_rate), + "shape": data.shape, + } + audio_hash = hashlib.sha256() + audio_hash.update(hash_seed) + audio_hash.update(json.dumps(audio_metadata, sort_keys=True).encode("utf-8")) + audio_hash.update(data.tobytes()) + temp_dir = Path(cache_dir) / audio_hash.hexdigest() temp_dir.mkdir(exist_ok=True, parents=True) filename = str((temp_dir / f"audio.{format}").resolve()) audio_to_file(sample_rate, data, filename, format=format)
test/test_processing_utils.py+40 −0 modified@@ -204,6 +204,46 @@ def test_audio_to_file(self): assert os.path.exists("test_audio_to_file") os.remove("test_audio_to_file") + def test_save_audio_to_cache_uses_audio_metadata_in_cache_key( + self, gradio_temp_dir + ): + data = np.array([0, 1, 2, 3], dtype=np.int16) + data_with_different_dtype = np.array([0, 1, 2, 3], dtype=np.uint16) + data_with_different_shape = np.array([[0, 1], [2, 3]], dtype=np.int16) + + with patch("gradio.processing_utils.audio_to_file"): + path_8000 = processing_utils.save_audio_to_cache( + data, 8000, "wav", cache_dir=gradio_temp_dir + ) + path_16000 = processing_utils.save_audio_to_cache( + data, 16000, "wav", cache_dir=gradio_temp_dir + ) + path_mp3 = processing_utils.save_audio_to_cache( + data, 8000, "mp3", cache_dir=gradio_temp_dir + ) + path_uint16 = processing_utils.save_audio_to_cache( + data_with_different_dtype, 8000, "wav", cache_dir=gradio_temp_dir + ) + path_stereo = processing_utils.save_audio_to_cache( + data_with_different_shape, 8000, "wav", cache_dir=gradio_temp_dir + ) + + assert Path(path_8000).parent != Path(path_16000).parent + assert Path(path_8000).parent != Path(path_mp3).parent + assert Path(path_8000).parent != Path(path_uint16).parent + assert Path(path_8000).parent != Path(path_stereo).parent + + def test_save_audio_to_cache_accepts_numpy_sample_rate(self, gradio_temp_dir): + data = np.array([0, 1, 2, 3], dtype=np.int16) + with patch("gradio.processing_utils.audio_to_file"): + path_py_int = processing_utils.save_audio_to_cache( + data, 8000, "wav", cache_dir=gradio_temp_dir + ) + path_np_int = processing_utils.save_audio_to_cache( + data, np.int64(8000), "wav", cache_dir=gradio_temp_dir + ) + assert Path(path_py_int).parent == Path(path_np_int).parent + def test_convert_to_16_bit_wav(self): # Generate a random audio sample and set the amplitude audio = np.random.randint(-100, 100, size=(100), dtype="int16")
Vulnerability mechanics
Root cause
"The audio cache key generation in `save_audio_to_cache` incorrectly uses only the raw audio bytes, ignoring critical metadata."
Attack vector
An attacker with local access must trigger the `save_audio_to_cache` function with audio data that has identical raw bytes but different metadata, such as sample rate, format, dtype, or shape. This manipulation causes different audio outputs to resolve to the same cache directory. The vulnerability has high complexity and is difficult to exploit, but a public exploit is available [ref_id=1].
Affected code
The vulnerability resides in the `save_audio_to_cache` function within `gradio/processing_utils.py`. Specifically, lines 182-190 are affected, where the cache directory is derived solely from `data.tobytes()` [ref_id=1].
What the fix does
The patch modifies the `save_audio_to_cache` function to include audio metadata, such as sample rate and format, in the cache key generation. This ensures that audio outputs with different metadata, even if they share identical raw bytes, will be stored in distinct cache directories. This prevents non-equivalent audio outputs from overwriting each other or being misinterpreted due to shared cache namespaces [patch_id=4721335].
Preconditions
- inputLocal access is required to trigger the vulnerability.
Reproduction
import tempfile from pathlib import Path from unittest.mock import patch
import numpy as np
from gradio import processing_utils
data = np.array([0, 1, 2, 3], dtype=np.int16)
with tempfile.TemporaryDirectory() as cache_dir: # Patch audio_to_file so this demonstrates the cache-key behavior only. # No ffmpeg/ffprobe installation is needed for the reproduction. with patch("gradio.processing_utils.audio_to_file"): path_8000 = processing_utils.save_audio_to_cache( data, 8000, "wav", cache_dir=cache_dir ) path_16000 = processing_utils.save_audio_to_cache( data, 16000, "wav", cache_dir=cache_dir ) path_mp3 = processing_utils.save_audio_to_cache( data, 8000, "mp3", cache_dir=cache_dir )
print("8000 Hz wav:", path_8000) print("16000 Hz wav:", path_16000) print("8000 Hz mp3:", path_mp3) print("same cache directory for different sample rates:", Path(path_8000).parent == Path(path_16000).parent) print("same cache directory for different formats:", Path(path_8000).parent == Path(path_mp3).parent) [ref_id=1]
Generated on Jun 4, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6News mentions
0No linked articles in our index yet.