64 lines
2.9 KiB
Python
64 lines
2.9 KiB
Python
"""Bereinigte Darstellung von Modellausgaben (→ Konzept 4.5, Abnahmekriterium 15)."""
|
||
|
||
import pytest
|
||
|
||
from app.core.markdown import render
|
||
from app.tasks.worker import Worker
|
||
from helpers import connect_repo, create_workspace
|
||
|
||
|
||
def test_markdown_wird_gerendert():
|
||
html = render("# Titel\n\n**fett** und `code`\n\n- a\n- b\n\n|x|y|\n|-|-|\n|1|2|\n\n```\nprint(1)\n```")
|
||
for part in ("<h1>Titel</h1>", "<strong>fett</strong>", "<code>code</code>", "<li>a</li>", "<td>1</td>",
|
||
"<pre><code>print(1)"):
|
||
assert part in html
|
||
|
||
|
||
@pytest.mark.parametrize("text", [
|
||
"<script>alert(1)</script>",
|
||
'<img src="https://evil.example/x.png">',
|
||
"<a href='javascript:alert(1)'>x</a>",
|
||
'<div onclick="alert(1)">x</div>',
|
||
"<iframe src='https://evil.example'></iframe>",
|
||
])
|
||
def test_kein_roh_html(text):
|
||
html = render(text)
|
||
assert "<script" not in html and "<img" not in html and "<iframe" not in html and "<div" not in html
|
||
assert html.startswith("<p><") # nur noch als maskierter Text
|
||
|
||
|
||
def test_bilder_werden_nicht_geladen():
|
||
html = render("")
|
||
assert "<img" not in html
|
||
assert '[Bild: Diagramm – https://evil.example/leak.png?daten=geheim]' in html
|
||
|
||
|
||
def test_links_mit_sichtbarem_ziel():
|
||
html = render("[Doku](https://evil.example/a?daten=geheim) und <https://example.org>")
|
||
assert 'href="https://evil.example/a?daten=geheim"' in html and 'rel="noopener noreferrer nofollow"' in html
|
||
assert '<span class="aiw-link-target">(https://evil.example/a?daten=geheim)</span>' in html
|
||
# Ist der Text schon die URL, wird sie nicht doppelt gezeigt
|
||
assert html.count("https://example.org") == 2 # href und Linktext
|
||
long = render(f"[x](https://example.org/{'a' * 200})")
|
||
assert "…)</span>" in long
|
||
|
||
|
||
@pytest.mark.parametrize("url", ["javascript:alert(1)", "data:text/html,<b>x</b>", "/intern/pfad", "vbscript:x",
|
||
"JAVASCRIPT:alert(1)"])
|
||
def test_unsichere_links_bleiben_text(url):
|
||
html = render(f"[klick]({url})")
|
||
assert "<a " not in html
|
||
|
||
|
||
def test_chat_zeigt_bereinigte_antwort(browser, people, git_repo, db, settings, fake_provider):
|
||
anna = browser("anna")
|
||
workspace_id = create_workspace(anna, people["team_demo"])
|
||
connect_repo(anna, workspace_id, git_repo)
|
||
chat_id = int(anna.post(f"/workspaces/{workspace_id}/chats").headers["location"].rsplit("/", 1)[1])
|
||
fake_provider.reply = "**Wichtig:** <script>alert(1)</script> "
|
||
anna.post(f"/chats/{chat_id}/messages", {"content": "Hallo <b>du</b>"}, headers={"HX-Request": "true"})
|
||
Worker(db, settings).run_once()
|
||
page = anna.get(f"/chats/{chat_id}").text
|
||
assert "<strong>Wichtig:</strong>" in page and "<script>alert" not in page
|
||
assert "<script>" in page and "[Bild: x – https://evil.example/x.png]" in page
|
||
assert "Hallo <b>du</b>" in page # Nutzertext bleibt Text
|