ActivityPub compatibility#1323
Conversation
| previewEl.innerHTML = `<img | ||
| class="img-responsive" | ||
| src="${url}" | ||
| alt="Preview" | ||
| onerror="this.style.display='none'" | ||
| onload="this.style.display='block'" | ||
| />` |
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
In general, this should be fixed by not using innerHTML with strings that contain or are derived from untrusted data. Instead, create DOM elements programmatically (e.g., via document.createElement) and assign untrusted data only to safe properties/attributes (like img.src), which will be treated as plain text/URLs rather than parsed as HTML.
For this file, the best minimal fix without changing existing functionality is to replace the innerHTML assignment that embeds the <img> tag with DOM-based creation and update of an <img> element inside previewEl. Concretely:
- In
handleImageUrlInput, in the block starting at line 93, remove the template literal assigned topreviewEl.innerHTML. - Instead, clear any existing content in
previewEl, then:- Create an
<img>element. - Set its
classNameto"img-responsive". - Set its
altattribute to"Preview". - Set its
srcproperty to the untrustedurl. - Attach
onerrorandonloadhandlers equivalent to the inline ones: hide the image on error, show it on load. - Append this
<img>element topreviewEl.
- Create an
- Keep the
elsebranch that setspreviewEl.innerHTML = ''or similarly clear the element.
No new imports or external libraries are needed; this can be done with standard DOM APIs in tools/bazar/presentation/javascripts/inputs/image-field.js.
| @@ -91,13 +91,23 @@ | ||
| if (!previewEl) return | ||
|
|
||
| if (url && (url.startsWith('http://') || url.startsWith('https://'))) { | ||
| previewEl.innerHTML = `<img | ||
| class="img-responsive" | ||
| src="${url}" | ||
| alt="Preview" | ||
| onerror="this.style.display='none'" | ||
| onload="this.style.display='block'" | ||
| />` | ||
| // Clear previous preview content | ||
| previewEl.innerHTML = '' | ||
|
|
||
| // Create image element safely without using innerHTML with untrusted data | ||
| const img = document.createElement('img') | ||
| img.className = 'img-responsive' | ||
| img.alt = 'Preview' | ||
| img.style.display = 'none' | ||
| img.onerror = function onImageError() { | ||
| this.style.display = 'none' | ||
| } | ||
| img.onload = function onImageLoad() { | ||
| this.style.display = 'block' | ||
| } | ||
| img.src = url | ||
|
|
||
| previewEl.appendChild(img) | ||
| } else { | ||
| previewEl.innerHTML = '' | ||
| } |
…ctivitypub-compatibility
…i into activitypub-compatibility
068c31c to
52aae21
Compare
See documentation activitypub.md