Skip to content

Commit 31134ad

Browse files
Merge pull request #1768 from nextcloud/fix/Stored-HTML-Injection-in-Nextcloud-Notes-Markdown-Preview-via-Unescaped-Image-Alt-Text
fix(files): Apply HTML escaping to all user-controlled input before сoncatenating it into HTML
2 parents 055bf77 + d90875b commit 31134ad

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

src/Util.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,9 @@ export const getDefaultSampleNote = () => {
6666
> ` + t('notes', 'Nextcloud, a safe home for all your data') + `
6767
`
6868
}
69+
70+
export const escapeHtml = (str) => {
71+
const element = document.createElement('div')
72+
element.textContent = str
73+
return element.innerHTML
74+
}

src/components/EditorMarkdownIt.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
1212
import MarkdownIt from 'markdown-it'
1313
import { generateUrl } from '@nextcloud/router'
14+
import { escapeHtml } from '../Util.js'
1415
1516
export default {
1617
name: 'EditorMarkdownIt',
@@ -145,7 +146,10 @@ export default {
145146
146147
if (download) {
147148
const dlimgpath = generateUrl('svg/core/actions/download?color=ffffff')
148-
return '<div class="download-file"><a href="' + path.replace(/"/g, '&quot;') + '"><div class="download-icon"><img class="download-icon-inner" src="' + dlimgpath + '">' + token.content + '</div></a></div>'
149+
const tokenContent = escapeHtml(token.content)
150+
return '<div class="download-file"><a href="' + path.replace(/"/g, '&quot;') + '"><div class="download-icon"><img class="download-icon-inner" '
151+
+ 'src="' + dlimgpath + '">'
152+
+ tokenContent + '</div></a></div>'
149153
} else {
150154
// pass token to default renderer.
151155
return defaultRender(tokens, idx, options, env, self)

0 commit comments

Comments
 (0)