Remove unsafe-inline from CSP script-src by externalising template JS #48
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
All UI JavaScript in FenLiu lives in inline
<script>blocks across 6 Jinja2 templates. This forces'unsafe-inline'inContent-Security-Policy: script-src, which negates most XSS protection: an attacker who can inject arbitrary HTML can also run arbitrary inline JavaScript.The fix is to move each inline script block to a dedicated external file under
src/fenliu/static/assets/and remove'unsafe-inline'fromscript-src.Affected templates (6):
dashboard.html,hashtag_streams.html,queue_preview.html,settings.html,topical_tags.html,stats.htmlUnaffected (no inline scripts):
review.html,login.html,change_password.html,post_details.html,setup.html,partials/header.htmlExploration findings
5 templates use
{{ api_key }}directly inside the<script>block. Moving to an external file requires an alternative injection mechanism. Solution:<meta name="fenliu-api-key" content="{{ api_key }}">in the<head>; external JS readsdocument.querySelector('meta[name="fenliu-api-key"]')?.content. Meta tags are data, not executable code — CSPscript-srcdoes not apply.stats.htmlinjects 4 chart-data arrays via| tojsondirectly into Chart.js constructor calls. Solution: a<script type="application/json" id="chart-data">JSON island.type="application/json"marks the block as non-executable data; CSP ignores it. External JS parses it withJSON.parse(document.getElementById('chart-data').textContent).Inline
onclickattributes in several templates reference template variables (e.g.onclick="fetchStream({{ stream.id }}, this)"). These are also blocked by CSP withoutunsafe-inline. Solution:data-*attributes + event delegation in external JS.Dynamically-generated HTML strings in
settings.htmlandqueue_preview.htmlbuild rows withonclickattributes in JS template literals. These must also switch todata-*attributes + event delegation.Chart.js is loaded from
cdn.jsdelivr.netinstats.htmlbut that host is absent from the currentscript-src. It must be added at the same time as'unsafe-inline'is dropped.Plan of attack
'unsafe-inline'is absent fromscript-src(TDD RED)<script>block tostatic/assets/<page>.js, applying the three strategies above<script>, add<script src="/static/assets/<page>.js" defer>, convert inline event handlers todata-*attributesmiddleware.py: drop'unsafe-inline'fromscript-src, addhttps://cdn.jsdelivr.net