Fjern inline onsubmit med innholdstekst (XSS i JS-attributt)
Jinja escaper for HTML, men nettleseren dekoder attributtverdien før JS-parseren ser den, så en tittel med ' kunne bryte ut av strengen. Bekreftelser går nå via data-confirm og én delt handler i base.html. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
This commit is contained in:
parent
227faff373
commit
4794db76b0
4 changed files with 22 additions and 5 deletions
|
|
@ -32,5 +32,13 @@
|
|||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<script>
|
||||
// Bekreftelsesdialoger via data-attributt i stedet for inline onsubmit, slik at
|
||||
// tekst fra innhold (titler, brukernavn) aldri havner i en JS-kontekst.
|
||||
document.addEventListener("submit", function (ev) {
|
||||
var msg = ev.target.dataset && ev.target.dataset.confirm;
|
||||
if (msg && !confirm(msg)) ev.preventDefault();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@
|
|||
<li>
|
||||
<img src="{{ url_for('admin.media', post_id=post.id, filename=name) }}" alt="" loading="lazy">
|
||||
<code></code>
|
||||
<form method="post" action="{{ url_for('admin.delete_image', post_id=post.id) }}" class="inline"
|
||||
onsubmit="return confirm('Slette {{ name }}?')">
|
||||
<form method="post" action="{{ url_for('admin.delete_image', post_id=post.id) }}" class="inline" data-confirm="Slette {{ name }}?">
|
||||
<input type="hidden" name="csrf" value="{{ csrf }}">
|
||||
<input type="hidden" name="filename" value="{{ name }}">
|
||||
<button type="submit" class="link danger">Slett</button>
|
||||
|
|
@ -68,8 +67,7 @@
|
|||
</details>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{{ url_for('admin.delete', post_id=post.id) }}" class="danger-zone"
|
||||
onsubmit="return confirm('Slette hele innlegget «{{ post.title }}»?')">
|
||||
<form method="post" action="{{ url_for('admin.delete', post_id=post.id) }}" class="danger-zone" data-confirm="Slette hele innlegget «{{ post.title }}»?">
|
||||
<input type="hidden" name="csrf" value="{{ csrf }}">
|
||||
<button type="submit" class="link danger">Slett innlegget</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<label>Nytt passord <input type="password" name="password" minlength="8" required autocomplete="new-password"></label>
|
||||
<button type="submit">Sett passord</button>
|
||||
</form>
|
||||
<form method="post" class="inline" onsubmit="return confirm('Slette brukeren {{ u.username }}? Innleggene beholdes i git.')">
|
||||
<form method="post" class="inline" data-confirm="Slette brukeren {{ u.username }}? Innleggene beholdes i git.">
|
||||
<input type="hidden" name="csrf" value="{{ csrf }}">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="user_id" value="{{ u.id }}">
|
||||
|
|
|
|||
|
|
@ -146,3 +146,14 @@ def test_subpath_mount(tmp_path):
|
|||
assert 'href="theme/style.css"' in html
|
||||
assert re.search(r'href="admin/"', html)
|
||||
assert client.get("/blog/theme/style.css").status_code == 200
|
||||
|
||||
|
||||
def test_no_inline_js_with_content(client, cfg):
|
||||
"""Titler med anførselstegn skal ikke havne i en JS-kontekst (XSS)."""
|
||||
post_id = _create_post(client)
|
||||
token = csrf(client)
|
||||
title = "Ola's \"test\" <b>"
|
||||
r = client.post(f"/admin/edit/{post_id}", data={"csrf": token, "title": title, "body": "x", "action": "save"})
|
||||
html = client.get(r.headers["Location"]).text
|
||||
assert "onsubmit" not in html and "onclick" not in html
|
||||
assert "Ola's" in html
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue