{"id":"PYSEC-2026-2397","summary":"beets has a Cross-site Scripting vulnerability","details":"During code logic analyis, an area that may lead to unintended behavior under specific conditions was discovered. \n\n## Overview\n- Verified Version: `80cd21554124da07d17a4f962c7d770a4f70d0f2`\n- Vulnerability Type: Stored XSS\n- Affected Location: `beetsplug/web/templates/index.html:42`\n- Trigger Scenario: Metadata fields such as `title`, `lyrics`, or `comments` are rendered with raw template interpolation and inserted into DOM via `.html(...)`.\n\n## Root Cause\nThe bundled web UI uses Underscore template interpolation mode `\u003c%= ... %\u003e` for untrusted metadata fields. In this runtime, `\u003c%= ... %\u003e` is raw insertion and HTML escaping is only performed by `\u003c%- ... %\u003e`. Rendered output is then inserted with `.html(...)`, allowing attacker-controlled markup to become active DOM.\n\n## Source-to-Sink Chain\n1. Source (attacker-controlled input)\n- Item metadata values (for example `title`, `lyrics`, `comments`) can contain attacker HTML payload.\n\n2. Data flow\n- Templates in `beetsplug/web/templates/index.html:42-46,87-91` render metadata with `\u003c%= ... %\u003e`.\n- Underscore runtime defines `\u003c%= ... %\u003e` as raw interpolation (`beetsplug/web/static/underscore.js:890-907`).\n\n3. Sink (security-sensitive action)\n- Frontend inserts rendered template output into DOM via `$(this.el).html(this.template(this.model.toJSON()));` in `beetsplug/web/static/beets.js:182,208,220`.\n\n## Exploitation Preconditions\n1. Victim opens the web UI page that renders attacker-controlled metadata.\n2. Metadata includes executable HTML/JS payload.\n\n## Risk\nStored payload executes in the web UI context and can perform actions available to that origin.\n\n## Impact\nAttacker can run arbitrary JavaScript in the victim browser, exfiltrate viewable data, and perform UI-driven actions as the victim session.\n\n## Remediation\n1. Replace raw interpolation `\u003c%= ... %\u003e` with escaped output `\u003c%- ... %\u003e` for untrusted fields.\n2. Avoid `.html(...)` for untrusted template output; use text-safe rendering.\n3. Sanitize metadata values on ingest and before rendering, including attribute contexts.","aliases":["CVE-2026-42052","GHSA-3gxm-wfjx-m847"],"modified":"2026-07-13T16:31:38.628627327Z","published":"2026-07-13T15:02:54.913237Z","references":[{"type":"WEB","url":"https://github.com/beetbox/beets/security/advisories/GHSA-3gxm-wfjx-m847"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-42052"},{"type":"PACKAGE","url":"https://github.com/beetbox/beets"},{"type":"WEB","url":"https://github.com/beetbox/beets/releases/tag/v2.10.0"},{"type":"WEB","url":"https://lists.debian.org/debian-lts-announce/2026/06/msg00030.html"},{"type":"PACKAGE","url":"https://pypi.org/project/beets"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-3gxm-wfjx-m847"}],"affected":[{"package":{"name":"beets","ecosystem":"PyPI","purl":"pkg:pypi/beets"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.10.0"}]}],"versions":["1.0.0","1.0b1","1.0b10","1.0b11","1.0b12","1.0b13","1.0b14","1.0b15","1.0b2","1.0b3","1.0b4","1.0b5","1.0b6","1.0b7","1.0b8","1.0b9","1.0rc1","1.0rc2","1.1.0","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.3.10","1.3.11","1.3.12","1.3.13","1.3.14","1.3.15","1.3.16","1.3.17","1.3.18","1.3.19","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.3.7","1.3.8","1.3.9","1.4.0","1.4.1","1.4.2","1.4.3","1.4.4","1.4.5","1.4.6","1.4.7","1.4.8","1.4.9","1.5.0","1.6.0","1.6.1","2.0.0","2.1.0","2.2.0","2.3.0","2.3.1","2.4.0","2.5.0","2.5.1","2.6.0","2.6.1","2.6.2","2.7.0","2.7.1","2.8.0","2.9.0"],"database_specific":{"source":"https://github.com/pypa/advisory-database/blob/main/vulns/beets/PYSEC-2026-2397.yaml"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X"}]}