Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4076c8c
Bump vite from 6.4.1 to 6.4.2 in /docs (#1350)
dependabot[bot] Jun 20, 2026
2299c70
Bump defu from 6.1.4 to 6.1.6 in /docs (#1347)
dependabot[bot] Jun 20, 2026
e8cb5a0
Bump serialize-javascript and @rollup/plugin-terser (#1342)
dependabot[bot] Jun 20, 2026
0d7de91
Bump astro from 5.16.5 to 5.18.1 in /docs (#1334)
dependabot[bot] Jun 20, 2026
1c0b758
Bump picomatch in /docs (#1333)
dependabot[bot] Jun 20, 2026
c5b823f
Bump smol-toml from 1.5.2 to 1.6.1 in /docs (#1331)
dependabot[bot] Jun 20, 2026
ac6895c
Fix flaky version check test
sissbruecker Jun 20, 2026
3385a61
Bump devalue from 5.6.4 to 5.8.1 in /docs (#1393)
dependabot[bot] Jun 20, 2026
20e5b37
Bump cryptography from 46.0.3 to 48.0.1 (#1391)
dependabot[bot] Jun 20, 2026
9fcd256
Bump pyjwt from 2.10.1 to 2.13.0 (#1392)
dependabot[bot] Jun 20, 2026
365f8b6
Bump idna from 3.11 to 3.15 (#1390)
dependabot[bot] Jun 20, 2026
a7b61e4
Bump urllib3 from 2.6.2 to 2.7.0 (#1389)
dependabot[bot] Jun 20, 2026
3517b9d
Fix flaky version check test
sissbruecker Jun 20, 2026
e1370c5
Bump django from 6.0 to 6.0.5 (#1394)
dependabot[bot] Jun 20, 2026
e683d57
Bump bleach from 6.3.0 to 6.4.0 (#1388)
dependabot[bot] Jun 20, 2026
436daff
Bump requests from 2.32.5 to 2.33.0 (#1398)
dependabot[bot] Jun 20, 2026
632a3e8
Bump postcss from 8.5.6 to 8.5.15 (#1397)
dependabot[bot] Jun 20, 2026
32f244b
Bump js-yaml from 4.1.1 to 4.2.0 in /docs (#1396)
dependabot[bot] Jun 20, 2026
5c7d6af
Bump pygments from 2.19.2 to 2.20.0 (#1395)
dependabot[bot] Jun 20, 2026
bbba1a6
Bump yaml from 2.8.1 to 2.9.0 (#1335)
dependabot[bot] Jun 20, 2026
357ab4e
Bump rollup from 4.53.3 to 4.59.0 in /docs (#1310)
dependabot[bot] Jun 20, 2026
e520e7f
Bump svgo from 4.0.0 to 4.0.1 (#1315)
dependabot[bot] Jun 20, 2026
26b298a
Bump @hotwired/turbo from 8.0.13 to 8.0.21 (#1288)
dependabot[bot] Jun 20, 2026
68cf352
Bump postcss from 8.5.6 to 8.5.15 in /docs (#1399)
dependabot[bot] Jun 20, 2026
06562b0
Bump astro and @astrojs/starlight in /docs (#1400)
dependabot[bot] Jun 20, 2026
1456941
Bump pytest from 9.0.2 to 9.0.3 (#1401)
dependabot[bot] Jun 20, 2026
52e4a06
Use sandbox CSP for reader mode (#1402)
sissbruecker Jun 20, 2026
f32af96
Clarify auto tagging behavior in API docs (#1385)
brdns Jun 20, 2026
d547e35
Escape tag names in HTML export (#1378)
l0b0 Jun 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bookmarks/services/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def append_bookmark(doc: BookmarkDocument, bookmark: Bookmark):
tag_names = bookmark.tag_names
if bookmark.is_archived:
tag_names.append("linkding:bookmarks.archived")
tags = ",".join(tag_names)
tags = ",".join(html.escape(tag) for tag in tag_names)
toread = "1" if bookmark.unread else "0"
private = "0" if bookmark.shared else "1"
added = int(bookmark.date_added.timestamp())
Expand Down
7 changes: 7 additions & 0 deletions bookmarks/tests/test_bookmark_asset_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ def test_snapshot_download_headers(self):
)
self.assertEqual(response["Content-Security-Policy"], "sandbox allow-scripts")

def test_reader_view_headers(self):
bookmark = self.setup_bookmark()
asset = self.setup_asset_with_file(bookmark)
response = self.client.get(reverse("linkding:assets.read", args=[asset.id]))

self.assertEqual(response["Content-Security-Policy"], "sandbox allow-scripts")

def test_uploaded_file_download_headers(self):
bookmark = self.setup_bookmark()
asset = self.setup_asset_with_uploaded_file(bookmark)
Expand Down
2 changes: 2 additions & 0 deletions bookmarks/tests/test_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def test_escape_html(self):
title="<style>: The Style Information element",
description="The <style> HTML element contains style information for a document, or part of a document.",
notes="Interesting notes about the <style> HTML element.",
tags=[self.setup_tag(name='"'), self.setup_tag(name="&")],
)
html = exporter.export_netscape_html([bookmark])

Expand All @@ -105,6 +106,7 @@ def test_escape_html(self):
html,
)
self.assertIn("Interesting notes about the &lt;style&gt; HTML element.", html)
self.assertIn('TAGS="&quot;,&amp;"', html)

def test_handle_empty_values(self):
bookmark = self.setup_bookmark()
Expand Down
30 changes: 19 additions & 11 deletions bookmarks/tests/test_settings_general_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,18 +436,26 @@ def test_automatic_html_snapshots_should_be_visible_when_snapshots_supported(
)

def test_about_shows_version_info(self):
response = self.client.get(reverse("linkding:settings.general"))
html = response.content.decode()

self.assertInHTML(
f"""
<tr>
<td>Version</td>
<td>{get_version_info(random.random())}</td>
</tr>
""",
html,
latest_version_response_mock = Mock(
status_code=200, json=lambda: {"name": f"v{app_version}"}
)
with patch.object(requests, "get", return_value=latest_version_response_mock):
# Clear the lru_cache so the view recomputes the version info under
# the mock instead of returning a value cached by an earlier test
# that made a real (potentially rate-limited) network call.
get_version_info.cache_clear()
response = self.client.get(reverse("linkding:settings.general"))
html = response.content.decode()

self.assertInHTML(
f"""
<tr>
<td>Version</td>
<td>{get_version_info(random.random())}</td>
</tr>
""",
html,
)

def test_get_version_info_just_displays_latest_when_versions_are_equal(self):
latest_version_response_mock = Mock(
Expand Down
4 changes: 3 additions & 1 deletion bookmarks/views/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ def read(request, asset_id: int):
content = _get_asset_content(asset)
content = content.decode("utf-8")

return render(
response = render(
request,
"bookmarks/read.html",
{
"content": content,
},
)
response["Content-Security-Policy"] = "sandbox allow-scripts"
return response
Loading
Loading