The packages.js template at src/pyload/webui/app/themes/modern/templates/js/packages.js:172 interpolates a stored link URL into a template literal inside single-quoted HTML and then writes the result to the DOM via $(div).html(html). No escaping runs between the API value and innerHTML. An attacker (Alice) who can submit a package link puts a single quote plus event handler into the URL, breaks out of the attribute, and executes JavaScript in every operator's browser that opens the downloads view. The theme does not set a Content Security Policy that restricts inline script or event handlers.
Sink: src/pyload/webui/app/themes/modern/templates/js/packages.js:165-188:
const html = `
<span class='child_status'>
<span style='margin-right: 2px;color: #337ab7;' class='${link.icon}'></span>
</span>
<span style='font-size: 16px; font-weight: bold;'>
<a onclick='return false' href='${link.url}'>${link.name}</a>
</span><br/>
<div class='child_secrow' ...>
<span class='child_status' ...>${link.statusmsg}</span> ${link.error}
<span class='child_status' ...>${link.format_size}</span>
<span class='child_status' ...> ${link.plugin}</span>...
</div>`;
const div = document.createElement("div");
$(div).attr("id", `file_${link.id}`);
$(div).css("padding-left", "30px");
$(div).css("cursor", "grab");
$(div).addClass("child");
$(div).html(html);
link.url flows in from /api/get_package_data, which returns the URL exactly as stored. Seven other fields on the same element (link.name, link.statusmsg, link.error, link.format_size, link.plugin, link.icon, link.id) share the same unescaped injection surface.
Source: src/pyload/core/api/__init__.py:541-600 (add_package) and the /api/add_package JSON route store the attacker-supplied links list without HTML escaping. The add_package URL sanitizer only strips http://, https://, ../,...
0.5.0a5.dev5280.5.0a5.dev5320.5.0a5.dev5350.5.0a5.dev5360.5.0a5.dev5370.5.0a5.dev5390.5.0a5.dev5400.5.0a5.dev5450.5.0a5.dev5620.5.0a5.dev564+94 moreExploitability
AV:NAC:LPR:LUI:RScope
S:CImpact
C:HI:HA:NCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N