Commit 03b57e0
fix(docker): replace PyPI opencv wheel with ffmpeg-free build [security] (#569)
## Summary
Mirrors
[Unstructured-IO/unstructured#4336](Unstructured-IO/unstructured#4336)
in this repo so the `quay.io/unstructured-io/unstructured-api` image no
longer ships the 14 ffmpeg 5.1.x CVEs bundled in PyPI `opencv-python`
wheels.
After `uv sync`, the Dockerfile now:
- Downloads the architecture-specific `opencv-contrib-python-headless`
wheel (built with `WITH_FFMPEG=OFF` + `ENABLE_CONTRIB=1` +
`ENABLE_HEADLESS=1`) from the upstream `Unstructured-IO/unstructured`
GitHub release (`opencv-4.12.0.88`)
- SHA-256-verifies against the hashes published by the upstream
`build-opencv-wheels.yml` workflow
- Uninstalls any installed PyPI opencv variants and installs the
verified wheel with `--no-deps`
The contrib-headless variant is a strict superset of the `cv2` API
exposed by `opencv-python`, `opencv-python-headless`, and
`opencv-contrib-python`, so a single wheel transparently replaces
whichever variant is present.
## One deviation from upstream
Upstream uninstalls all four opencv variants in a single `uv pip
uninstall …` call because their image pulls all four transitively (via
`unstructured-paddleocr`). Our `uv.lock` currently only resolves
`opencv-python`, so a single combined uninstall would fail on the three
that aren't installed. Replaced with a per-package loop using `|| true`
— same end state, robust if transitive deps change.
## Version / Changelog
- Bumps service version `0.1.3` → `0.1.4`
- `CHANGELOG.md` entry under `0.1.4` → Security
- No `uv lock` changes needed; the lockfile still resolves
`opencv-python 4.13.0.92`, and we overlay the 4.12.0.88 contrib-headless
wheel only at image build time (upstream 4.13.0.92 has no sdist on PyPI,
which is why the build-from-source workflow is pinned to 4.12.0.88).
## Test plan
- [ ] `make docker-build` succeeds on `amd64` and `arm64`; the opencv
replacement step resolves the architecture-specific wheel and the
SHA-256 check passes
- [ ] `docker run … python -c "import cv2; print(cv2.__version__)"`
prints `4.12.0.88` inside the built image
- [ ] `make docker-test` passes against the rebuilt image
- [ ] Container scan of the rebuilt image no longer flags the 14 ffmpeg
CVEs called out by upstream PR #4336
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Medium risk because it changes a core binary dependency (`opencv`) at
image build time via an external wheel download and forced
uninstall/reinstall, which could impact image build reliability or
runtime CV2 behavior across architectures.
>
> **Overview**
> Updates the Docker build to **remove vulnerable ffmpeg-bundled PyPI
OpenCV wheels** by downloading an arch-specific, SHA-256-verified
`opencv-contrib-python-headless` wheel built with `WITH_FFMPEG=OFF`,
uninstalling any installed OpenCV variants, and reinstalling the
verified wheel.
>
> Bumps the service version to `0.1.4` and adds a `CHANGELOG.md`
security entry documenting the OpenCV/ffmpeg CVE mitigation.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7e23afc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent e7e87ec commit 03b57e0
3 files changed
Lines changed: 47 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
1 | 7 | | |
2 | 8 | | |
3 | 9 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
78 | 118 | | |
79 | 119 | | |
80 | 120 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
0 commit comments