← Back to Feed CACHED · 2026-10-06 23:48:14 · CACHE_KEY CVE-2026-58447
CVE-2026-58447 · CWE-639 · Disclosed 2026-06-30

Invidious cross-user playlist video deletion via missing ownership check in remove_video action

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Someone can erase songs from your neighbor's mixtape, but it's a mixtape at a garage sale nobody attends

CVE-2026-58447 is a Broken Object Level Authorization (BOLA) flaw in Invidious, an open-source, self-hosted alternative frontend to YouTube written in Crystal. The POST /playlist_ajax?action=remove_video endpoint validates that the *requesting user* owns the playlist_id parameter, but then executes DELETE FROM playlist_videos WHERE index = $1 using a globally-scoped integer index pulled from the query string — without confirming that index belongs to the caller's playlist. Any authenticated user can grab a victim's video indexId values from the unauthenticated GET /api/v1/playlists/:plid JSON response, convert the hex value to a decimal Int64, and POST it to permanently delete that entry from the victim's playlist. Affected versions: all Invidious releases through 2.20260626.0. Fixed in commit 77ad416 (PR #5790), which adds AND plid = $2 to the SQL predicate.

The vendor CVSS v3.1 score of 6.5 MEDIUM is technically defensible for the BOLA pattern itself — network-reachable, low-complexity, requires only low-privilege auth, pure integrity impact. But the score wildly over-represents enterprise risk. Invidious is a hobbyist privacy tool with roughly 6 surviving public instances serving ~52,000 total users worldwide and an unknown but very small number of self-hosted instances. The worst-case impact is playlist vandalism — a user's curated video list loses entries, with no notification. There is zero path to system compromise, data exfiltration, privilege escalation, or lateral movement. For a team managing 10,000 enterprise hosts, this CVE is noise.

"Playlist griefing bug in a hobbyist YouTube proxy — irrelevant to enterprise patching queues"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain an account on the target Invidious instance

The attacker registers or already possesses a valid user account on the target Invidious instance. Registration policies vary by instance — some allow open signup, others require invitation or disable registration entirely. The attacker needs a valid session cookie and CSRF token.
Conditions required:
  • Target instance has open registration or attacker already has credentials
  • Invidious instance is running a version ≤ 2.20260626.0
Where this breaks in practice:
  • Many instances disable open registration entirely
  • Enterprise environments almost never run Invidious — this is hobbyist software
  • The 6 surviving public instances serve a combined ~52K users total
STEP 02

Enumerate victim playlist video indexes

The attacker identifies a target user's public or unlisted playlist and calls GET /api/v1/playlists/:plid — an unauthenticated endpoint that returns full playlist metadata including per-video indexId values in hexadecimal. These index values are globally unique database row identifiers, not scoped to any playlist.
Conditions required:
  • Target playlist must be public or unlisted (not private)
  • Attacker must know or discover the victim's playlist ID
Where this breaks in practice:
  • Private playlists are not enumerable via the API
  • Playlist IDs follow the IVPL prefix convention but are not sequentially guessable
Detection/coverage: Unusual volume of /api/v1/playlists/ GET requests from a single session could be logged, but no known scanner or IDS signature exists for this pattern.
STEP 03

Convert indexId and craft deletion request

The attacker converts the hex indexId to a decimal Int64 value and constructs a POST /playlist_ajax?action=remove_video request. The request body includes the attacker's *own* playlist_id (which passes the ownership check) and the *victim's* index value as the set_video_id parameter, along with a valid CSRF token from the attacker's session.
Conditions required:
  • Valid CSRF token from attacker's session
  • Attacker owns at least one playlist (to supply a passing playlist_id)
Where this breaks in practice:
  • Requires understanding the hex-to-Int64 conversion — documented in the issue report but not trivial for casual users
  • No weaponized tooling (e.g., Metasploit module, nuclei template) exists for this CVE
STEP 04

Video deleted from victim's playlist

The server executes DELETE FROM playlist_videos WHERE index = $1 with the victim's index value. Because the SQL has no AND plid = $2 clause, the row is deleted regardless of which playlist it belongs to. The victim receives no notification — the video simply disappears from their playlist. The deletion is permanent and not reversible through the UI.
Conditions required:
  • Vulnerable Invidious version is running
Where this breaks in practice:
  • Impact is limited to playlist integrity — no system compromise, no data exfiltration, no privilege escalation
  • Deleted content is a *reference* to a YouTube video, not the video itself — the victim can re-add it
Detection/coverage: No detection tooling exists. Instance administrators could audit playlist_videos table deletion logs in PostgreSQL if log_statement = 'mod' is enabled.
03 · Compensating Control

1
LOW 2.5→LOW 2.0
Disable open registration on the Invidious instance — Set registration_enabled: false in config.yml. This prevents new attacker accounts from being created, limiting the attack surface to existing users. Since this is a LOW-severity finding, there is no noisgate mitigation SLA — proceed directly to remediation within 365 days.
2
LOW 2.5→IGNORE 0.0
SEVERITY REDUCED
Rebuild Invidious from master branch post-commit 77ad416 — The fix is a one-line SQL change adding AND plid = $2 to the playlist video deletion query. Pull the latest master, rebuild the Docker image or binary, and redeploy. No tagged release exists yet, so building from source is required. Per the noisgate remediation SLA for LOW findings, treat this as backlog hygiene with no hard deadline.
3
LOW 2.5→LOW 1.5
Set playlists to private by default — Advise users to mark playlists as private. The attack requires enumerating indexId values from the public playlist API — private playlists are not exposed via GET /api/v1/playlists/:plid. This breaks step 2 of the attack path.
What doesn't work
  • WAF rules — the malicious request is a normal-looking POST to a legitimate endpoint with valid CSRF tokens. No WAF signature can distinguish it from legitimate playlist editing.
  • Network segmentation — the attack originates from an authenticated user session within the application. Network-level controls don't help.
  • Rate limiting — a single request deletes a single video entry. The attacker doesn't need high request volume.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not listed in CISA KEV. No mentions in threat intelligence feeds, GreyNoise, or campaign reporting. The target population (~6 public instances, unknown small number of self-hosted) makes mass exploitation economically irrational.
Proof-of-conceptDe facto PoC exists in the bug report. Issue #5777 by researcher geo-chen contains detailed step-by-step reproduction including the hex-to-Int64 conversion and exact HTTP request format. No standalone exploit repo found on GitHub, no pocindex.io entry, no Nuclei template, no ExploitDB or Metasploit module.
EPSS score0.00389 (~96th percentile low — only ~0.4% probability of exploitation in the next 30 days). Consistent with a niche open-source project with no weaponized tooling.
KEV statusNot listed. No federal agency usage of Invidious is known or plausible.
CVSS vectorsv3.1: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N (6.5 Medium) — v4.0: CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N (7.1 High). The I:H rating is generous — 'high integrity impact' here means deleting a playlist entry, not corrupting a database or signing key.
Affected versionsAll Invidious releases through 2.20260626.0. The project uses date-based versioning (YYYY.MMDD.patch).
Fixed versionCommit 77ad416, merged via PR #5790. No tagged release yet — operators must build from master post-commit.
Exposure footprintMinimal. The official instance list shows 6 public HTTPS instances globally with ~52,000 combined registered users. Self-hosted instances are untracked but the project's niche appeal (privacy-focused YouTube proxy) and YouTube's aggressive IP blocking have severely contracted the ecosystem.
Disclosure timelineReported 2026-06-15 by geo-chen via GitHub issue. Fix merged 2026-06-26. CVE published 2026-06-30. 11-day fix turnaround.
Reporting researchergeo-chen — filed Issue #5777 with full reproduction steps and root-cause analysis pointing to the unscoped SQL DELETE in PlaylistVideos.delete().

Sources.

  1. GitHub Issue #5777 — Original vulnerability report by geo-chen
  2. GitHub PR #5790 — Fix adding playlist ownership check to SQL DELETE
  3. GitHub Commit 77ad416 — The actual code fix
  4. OpenCVE — CVE-2026-58447 detail page
  5. SentinelOne Vulnerability Database — CVE-2026-58447
  6. Invidious Official Instance List — current health and user counts
  7. Invidious Documentation — Self-hosting and configuration
05 · The Call

Final Verdict
↓ DOWNGRADED to LOW (2.5/10)

Why this verdict

  • Blast radius is trivial. The maximum impact is deletion of playlist video *references* (not the videos themselves) from another user's curated list. There is no path to system compromise, privilege escalation, data exfiltration, lateral movement, or denial of service. The victim can re-add the video. This is vandalism, not a security breach.
  • Near-zero enterprise footprint. Invidious is a hobbyist privacy tool for watching YouTube without tracking. It is not enterprise software. No Fortune 500 or mid-market company lists Invidious in their asset inventory. If it appears on your network, it's shadow IT on a developer's Docker host — not a managed service.
  • Role multiplier: no high-value role applies. Invidious is not identity infrastructure, not a CA, not a hypervisor, not CI/CD, not a backup system, not a database engine, not a network edge appliance, not a kernel-mode agent, not SIEM, not OT/ICS. It is a consumer-grade web application for watching YouTube videos. 0% of installs occupy any high-value role. The deployment-role floor does not activate.
  • Authentication required. The attacker must hold a valid account on the specific Invidious instance. Many instances disable open registration. This is a meaningful friction gate for the ~6 remaining public instances.
  • No weaponized tooling. No Metasploit module, no Nuclei template, no standalone exploit script. The PoC requires manual hex-to-Int64 conversion and CSRF token extraction. EPSS is 0.00389 — bottom of the barrel.
  • Vendor MEDIUM is a CVSS artifact. The 6.5 score mechanically follows from AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H — but I:H ('high integrity impact') was designed for scenarios like unauthorized database modification or file system tampering, not deleting a line from a playlist. The CVSS framework lacks granularity to express 'trivial data modification in a non-critical application.'

Why not higher?

The vendor MEDIUM (6.5) and the CVSS v4.0 HIGH (7.1) reflect the *mechanical BOLA pattern* — and if Invidious were enterprise software managing regulated data, those scores would be appropriate. But it isn't. The affected asset class has zero enterprise deployment, zero high-value-role overlap, and the impact ceiling is playlist vandalism with no system-level consequences. Upgrading past LOW would misallocate patch engineering time away from actual threats.

Why not lower?

IGNORE would be appropriate only if the software literally cannot appear in a managed environment. It *can* — a developer or privacy-conscious team might self-host an instance, and the BOLA is real and trivially exploitable by any co-user. If you discover Invidious in your fleet, this bug should be patched as backlog hygiene, making LOW the correct floor rather than IGNORE.

06 · Verification

Crowdsourced verification payload.

Run this on the host where your Invidious instance is deployed, or any host with network access to the instance's API. Requires curl and jq. Invoke as: bash check_cve_2026_58447.sh https://your-invidious-instance.example.com. No authentication required — the script checks the application version only.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-58447 — Invidious BOLA playlist deletion check
# Checks whether the running Invidious instance is vulnerable based on
# the reported software version from the /api/v1/stats endpoint.
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

INSTANCE_URL="${1:-}"

if [[ -z "$INSTANCE_URL" ]]; then
  echo "Usage: $0 <invidious-instance-url>"
  echo "Example: $0 https://inv.nadeko.net"
  exit 2
fi

# Strip trailing slash
INSTANCE_URL="${INSTANCE_URL%/}"

# Fetch version from stats API
RESPONSE=$(curl -sf --max-time 10 "${INSTANCE_URL}/api/v1/stats" 2>/dev/null) || {
  echo "UNKNOWN — could not reach ${INSTANCE_URL}/api/v1/stats"
  exit 2
}

VERSION=$(echo "$RESPONSE" | jq -r '.software.version // empty' 2>/dev/null)

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN — could not parse version from stats API response"
  exit 2
fi

echo "Detected Invidious version: $VERSION"

# Vulnerable versions: <= 2.20260626.0
# Version format: MAJOR.YYYYMMDD.PATCH
# Extract date component
DATE_PART=$(echo "$VERSION" | grep -oP '\d{8}' | head -1)

if [[ -z "$DATE_PART" ]]; then
  # Non-standard version string — check for known fix commit hash in build
  BRANCH=$(echo "$RESPONSE" | jq -r '.software.branch // empty' 2>/dev/null)
  echo "Non-standard version format. Branch: ${BRANCH:-unknown}"
  echo "UNKNOWN — cannot determine patch status from version '$VERSION'"
  exit 2
fi

DATE_INT=$((10#$DATE_PART))

if [[ $DATE_INT -le 20260626 ]]; then
  echo "VULNERABLE — version $VERSION is <= 2.20260626.0 (CVE-2026-58447)"
  echo "Fix: rebuild from master branch post-commit 77ad416"
  exit 1
else
  echo "PATCHED — version $VERSION post-dates the fix (2026-06-26)"
  exit 0
fi