# Risk map — openai/whisper

> Canonical page: https://codevetter.com/unpack/whisper/risk-map

# Risk map — openai/whisper

Scanned commit 86098128c0b4f24f0e2aa2994de830614b474227 (2026-08-31). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Highest-risk areas are (1) the `transcribe()` seek loop — a deliberately flattened, heuristic-heavy control flow the authors flag as obscure; (2) runtime code paths that execute or load external artifacts (ffmpeg subprocess, torch.load of checkpoint files, Triton JIT source patching); and (3) fragile fallbacks — numba JIT at import, the missing `regex` dependency, and silent error swallowing in the CLI. There is also a real latent bug in `_get_audio_features` returning a TypeError object instead of raising it.
- load_audio passes the user-supplied file path to an ffmpeg subprocess (list-form argv, no shell injection, but any local path incl. URLs/devices reaches ffmpeg); a CalledProcessError surfaces as RuntimeError with stderr. — [whisper/audio.py#L42-62](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/audio.py#L42-L62)
- Checkpoint loading calls torch.load(weights_only=True) only when torch>=1.13; on older versions any local checkpoint path passed to load_model gets full pickle deserialization — arbitrary code execution risk for untrusted .pt files. — [whisper/__init__.py#L139-151](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/__init__.py#L139-L151)
- Model download integrity relies on the SHA256 embedded in the URL path segment, verified before reuse and after download — but the URL itself is plain CDN state; a bad cached file triggers re-download, not a hard failure. — [whisper/__init__.py#L54-95](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/__init__.py#L54-L95)
- The transcribe() main loop is acknowledged-fragile: an in-code comment says 'This loop is obscurely flattened to make the diff readable', and the seek is mutated by ~6 different mechanisms (segment_size fast-forward, last_timestamp seek, word-end seek, anomaly skips), making regressions easy and coverage nonexistent. — [whisper/transcribe.py#L267-280](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/transcribe.py#L267-L280) [whisper/transcribe.py#L344-471](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/transcribe.py#L344-L471)
- DecodingTask._get_audio_features returns `TypeError(...)` as a value instead of raising it — a dead-branch bug where a dtype mismatch would propagate a TypeError object as audio_features. — [whisper/decoding.py#L656-662](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L656-L662)
- triton_ops generates the median-filter kernel by string-replacing LOAD_ALL_ROWS_HERE/BUBBLESORT_HERE placeholders inside a @triton.jit function's source, then mutating kernel.src/_unsafe_update_src — brittle across Triton versions; timing.py wraps calls in try/except (RuntimeError, CalledProcessError) with slow-path fallback. — [whisper/triton_ops.py#L43-103](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/triton_ops.py#L43-L103) [whisper/timing.py#L36-54](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/timing.py#L36-L54)
- normalizers/basic.py imports the third-party `regex` package, which is absent from both pyproject dependencies and requirements.txt — importing whisper.normalizers.basic fails on a clean install unless regex arrives transitively. — [whisper/normalizers/basic.py#L4](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/normalizers/basic.py#L4) [pyproject.toml#L24-32](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/pyproject.toml#L24-L32) [requirements.txt](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/requirements.txt)
- numba is a hard dependency imported at module top of timing.py and JIT-compiles dtw_cpu/backtrace at first call — first-call latency plus platform fragility for a function used only when word_timestamps is on. — [whisper/timing.py#L7](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/timing.py#L7) [whisper/timing.py#L57-105](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/timing.py#L57-L105)
- The CLI catches all exceptions per audio file and merely prints 'Skipping ...' — a fully-failed batch still exits 0, which can silently produce empty output directories in scripted pipelines. — [whisper/transcribe.py#L613-619](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/transcribe.py#L613-L619)
- Default suppress_tokens='-1' expands to tokenizer.non_speech_tokens (music notes, brackets, symbols) plus all special/task tokens — a hard-coded suppression list that can mask legitimately-decoded characters, and any bug there degrades output quality rather than erroring. — [whisper/decoding.py#L615-642](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L615-L642) [whisper/tokenizer.py#L241-275](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/tokenizer.py#L241-L275)
- ApplyTimestampRules enforces timestamp/text alternation and monotonicity by in-place -inf masking per batch row; combined with the 'timestamp probability beats best text token' rule, subtle logic errors would produce shifted or looping timestamps rather than failures. (inferred) — [whisper/decoding.py#L441-505](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L441-L505)
- get_tokenizer/get_encoding/median_kernel are lru_cache'd singletons, so Tokenizer instances are shared process-wide; they are effectively immutable in practice, but any future mutability would leak state across calls. (inferred) — [whisper/tokenizer.py#L330-331](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/tokenizer.py#L330-L331) [whisper/tokenizer.py#L366-367](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/tokenizer.py#L366-L367) [whisper/triton_ops.py#L43-44](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/triton_ops.py#L43-L44)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
