Skip to content

Commit 4f8197a

Browse files
fix(bleach-to-nh3): migrate os_message.py and fix test assertions for nh3
- Replace bleach with nh3 in dojo/announcement/os_message.py (was causing ModuleNotFoundError in 132 rest-framework tests) - Update sonarqube importer test assertions to match nh3 output, which adds rel="noopener noreferrer" to all links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f416d7f commit 4f8197a

2 files changed

Lines changed: 11 additions & 13 deletions

File tree

dojo/announcement/os_message.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22

3-
import bleach
43
import markdown
4+
import nh3
55
import requests
66
from django.core.cache import cache
77

@@ -75,11 +75,10 @@ def parse_os_message(text):
7575

7676
headline_source = headline_source[:100]
7777
headline_rendered = markdown.markdown(headline_source)
78-
headline_cleaned = bleach.clean(
78+
headline_cleaned = nh3.clean(
7979
headline_rendered,
80-
tags=INLINE_TAGS,
81-
attributes=INLINE_ATTRS,
82-
strip=True,
80+
tags=set(INLINE_TAGS),
81+
attributes={k: set(v) for k, v in INLINE_ATTRS.items()},
8382
)
8483
headline_html = _strip_outer_p(headline_cleaned)
8584

@@ -98,11 +97,10 @@ def parse_os_message(text):
9897
expanded_source,
9998
extensions=["extra", "fenced_code", "nl2br"],
10099
)
101-
expanded_html = bleach.clean(
100+
expanded_html = nh3.clean(
102101
expanded_rendered,
103-
tags=BLOCK_TAGS,
104-
attributes=BLOCK_ATTRS,
105-
strip=True,
102+
tags=set(BLOCK_TAGS),
103+
attributes={k: set(v) for k, v in BLOCK_ATTRS.items()},
106104
)
107105

108106
return {"message": headline_html, "expanded_html": expanded_html}

unittests/tools/test_api_sonarqube_importer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ def test_get_rule_details_sanitizes_markdown_html(self):
351351
)
352352

353353
self.assertIn("<h1>Heading</h1>", rule_details)
354-
self.assertIn('<a href="https://example.com">safe</a>', rule_details)
355-
self.assertIn("<a>unsafe</a>", rule_details)
354+
self.assertIn('<a href="https://example.com" rel="noopener noreferrer">safe</a>', rule_details)
355+
self.assertIn('<a rel="noopener noreferrer">unsafe</a>', rule_details)
356356
self.assertNotIn("<script", rule_details)
357357
self.assertNotIn("alert('boom')", rule_details)
358358
self.assertNotIn("javascript:", rule_details)
@@ -370,8 +370,8 @@ def test_get_rule_details_sanitizes_html_desc(self):
370370
)
371371

372372
self.assertIn("<h2>References</h2>", rule_details)
373-
self.assertIn('<a href="https://owasp.org">OWASP</a>', rule_details)
374-
self.assertIn("<a>unsafe</a>", rule_details)
373+
self.assertIn('<a href="https://owasp.org" rel="noopener noreferrer">OWASP</a>', rule_details)
374+
self.assertIn('<a rel="noopener noreferrer">unsafe</a>', rule_details)
375375
self.assertNotIn("<style", rule_details)
376376
self.assertNotIn("display: none", rule_details)
377377
self.assertNotIn("javascript:", rule_details)

0 commit comments

Comments
 (0)