OpenCut ships rapidly. We actively support the latest minor (1.32.x) and the one immediately preceding it (1.31.x). Older minors receive security-only backports for 90 days after they're superseded.
| Version | Supported | Security fixes until |
|---|---|---|
| 1.32.x | ✅ Active | — |
| 1.31.x | ✅ Previous | +90 days after 1.32 |
| 1.30.x | +30 days after 1.32 | |
| ≤ 1.29 | ❌ End of life | n/a |
Version numbers ship in opencut/__init__.py and are kept in sync by scripts/sync_version.py.
Please do not open public GitHub issues for security problems.
Email matt@mavenimaging.com with:
- A description of the issue — what you see, what you expected.
- Reproducer steps, ideally as a minimal request / script / config.
- The commit SHA +
__version__you tested against. - Your assessment of severity (low / medium / high / critical) and why.
We acknowledge reports within 72 hours and aim to land a fix or mitigation within:
- Critical — 72 hours (RCE, auth bypass, data exfiltration, sandbox escape)
- High — 7 days (privilege escalation, unauthenticated DoS on a production endpoint)
- Medium — 30 days (authenticated DoS, information disclosure, supply-chain risk)
- Low — 90 days (hardening suggestions, theoretical concerns)
We don't run a paid bounty programme, but we credit reporters in CHANGELOG.md and the release notes unless you prefer to remain anonymous.
opencut/backend (Flask API, job system, CLI, MCP server)extension/com.opencut.panel/CEP panel (HTML/JS/ExtendScript)extension/com.opencut.uxp/UXP panel (HTML/JS)installer/(C# WPF Windows installer)scripts/build + utility scriptstests/fuzz/harness targets
- Third-party dependencies (report upstream). We monitor
pyproject.toml/requirements.txtvia Dependabot. - User-supplied plugins loaded via
~/.opencut/plugins/— plugins run with the host's trust, so audit before installing. - Social-engineering / phishing attacks against maintainers.
- Reports that require pre-existing local code execution (e.g. "an attacker with shell access can edit
~/.opencut/settings.json").
OpenCut's security model leans on a handful of intentional choices:
- CSRF on every mutation.
@require_csrfdecorator on allPOST/PUT/PATCH/DELETEroutes. Token rotates per server start, delivered viaGET /health, sent asX-OpenCut-Tokenheader. - Path validation. All file-accepting routes pass user-supplied paths through
security.validate_path()/validate_filepath()/validate_output_path(). Realpath resolution, null-byte rejection, symlink-out-of-allowlist defence. - SSRF defence. Outbound URL validators (
_validate_webhook_url,_validate_download_url) reject localhost, loopback, private IPs, link-local, reserved ranges. - Rate-limit categories. Four-way classification (
gpu_heavy/cpu_heavy/io_bound/light) bounds concurrent work per category — seecore/rate_limit_categories.py. - Scripting console sandbox. Dunder builtins stripped,
__import__/exec/eval/compile/open/os/sys/subprocessblocked in AST. Context keys containing__rejected. - Fuzz harness for parsers (
tests/fuzz/) — SRT / VTT /.cube/ voice-grammar parsers are expected to be total. - Atomic writes for user-data files via
tempfile + os.replace.
Operators running OpenCut in a shared-network environment should:
- Bind to
127.0.0.1only (default) — the service is single-user. Non-loopback binds requireOPENCUT_ALLOW_REMOTE=1. - Use the persistent local auth token when binding non-loopback.
Setting
OPENCUT_ALLOW_REMOTE=1automatically issues a token under~/.opencut/auth.json(POSIX: mode0600). Every non-loopback request must includeX-OpenCut-Auth: <token>. Loopback peers (127.0.0.1,::1) still bypass the token to keep the single-user workflow snappy. - Read or rotate the token explicitly:
The
opencut-server --print-auth # print the persisted token opencut-server --rotate-auth # generate a fresh token, then exit
GET /auth/infoendpoint returns metadata only — it never includes the token value. Treat~/.opencut/auth.jsonlike an SSH private key; never check it into source control. - Set
SENTRY_DSNso crashes route to a tracker you control. - Set
PLAUSIBLE_HOST+PLAUSIBLE_DOMAIN(optional) for usage telemetry. - Configure
OPENCUT_TEMP_CLEANUP_*to fit the expected workload. - Use the bundled FFmpeg or build FFmpeg explicitly — distro builds can lag on CVE fixes.
- Keep
~/.opencut/plugins/empty until you've audited each plugin manifest.
Default deployment: a single user, on their workstation, talking to
127.0.0.1:5679. The Adobe Premiere CEP/UXP panel sits on the same
machine. We deliberately do not require an API key in that path
because the token would be visible to anything that can read the panel
preferences anyway.
When the operator opts into OPENCUT_ALLOW_REMOTE=1 (e.g. remote
render host on a private VLAN), the threat surface changes:
- Anyone who can hit the bind address can issue render jobs, read media
paths, or call shell-adjacent endpoints (FFmpeg invocations, OS
shell-out for
open/Finder integration). - CSRF alone is not enough — CSRF protects browser sessions, not API clients on the same network.
The local auth token closes that gap: non-loopback callers must include
the token in the X-OpenCut-Auth header (a ?auth= query string is
also accepted for tools that can't set headers). /health and
/auth/info remain exempt so panels can bootstrap connectivity and
render a "Authentication required" hint.
Generate a CycloneDX SBOM from the pinned dependencies:
python scripts/sbom.pyThe script writes dist/opencut-sbom.cyclonedx.json (or .xml with --format xml).