Skip to content

Commit

Permalink
$mol_dom_safe - sanitize wild dom by white list
Browse files Browse the repository at this point in the history
  • Loading branch information
jin committed Dec 16, 2024
1 parent 6fc15ff commit 936afe7
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
49 changes: 49 additions & 0 deletions dom/safe/safe.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/** @jsx $mol_jsx */
/** @jsxFrag $mol_jsx_frag */
namespace $ {
$mol_test({

'safe tag'() {
$mol_assert_equal(
$$.$mol_dom_safe([ <div>foo</div> ])[0],
<div>foo</div>,
)
},

'bad tag'() {
$mol_assert_equal(
$mol_dom_serialize( $$.$mol_dom_safe([ <script>alert('ahtung!')</script> ])[0] ),
$mol_dom_serialize( <>alert('ahtung!')</> ),
)
},

'common attr'() {
$mol_assert_equal(
$$.$mol_dom_safe([ <a id="foo">foo</a> ])[0],
<a id="foo">foo</a>,
)
},

'safe attr'() {
$mol_assert_equal(
$$.$mol_dom_safe([ <a href="https://example.org/">foo</a> ])[0],
<a href="https://example.org/">foo</a>,
)
},

'bad attr'() {
$mol_assert_equal(
$$.$mol_dom_safe([ <a onclick="alert('ahtung!')">foo</a> ])[0],
<a>foo</a>,
)
},

'danger attr'() {
$mol_assert_equal(
$$.$mol_dom_safe([ <a href="javascript:alert('ahtung!')">foo</a> ])[0],
<a href="about:blank#javascript:alert('ahtung!')">foo</a>,
)
},

})
}
92 changes: 92 additions & 0 deletions dom/safe/safe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace $ {

export function $mol_dom_safe_uri( uri: string ) {
return uri.replace( /^(?=\w+script+:)/, 'about:blank#' )
}

export function $mol_dom_safe_attr( val: string ) {
return val
}

export let $mol_dom_safe_rules: Record< string, Record< string, ( val: string )=> string > > = {

// defaults
'': { id: $mol_dom_safe_attr },

// special
'': { href: $mol_dom_safe_uri },
img: { src: $mol_dom_safe_uri },
object: { src: $mol_dom_safe_uri },

// blocks
div: {},
p: {},
h1: {},
h2: {},
h3: {},
h4: {},
h5: {},
h6: {},
blockquote: {},
pre: {},
ul: {},
ol: {},
li: {},
details: {},
summary: {},
hr: {},
table: {},
tr: {},
td: {},

// inlines
span: {},
strong: {},
em: {},
br: {},
ins: {},
del: {},
code: {},

}

export function $mol_dom_safe( this: $, nodes: ChildNode[] ) {

const res = [] as ChildNode[]

for( const node of nodes ) {

if( node.nodeType === node.TEXT_NODE ) {
res.push( node )
continue
}

if( node.nodeType === node.ELEMENT_NODE ) {

const kids = this.$mol_dom_safe([ ... node.childNodes ])

const allowed = this.$mol_dom_safe_rules[ ( node as Element ).localName ]
if( !allowed ) {
res.push( ... kids )
continue
}

for( const attr of [ ... ( node as Element ).attributes ] ) {
const proc = allowed[ attr.localName ] ?? this.$mol_dom_safe_rules[''][ attr.localName ]
if( proc ) attr.nodeValue = proc( attr.nodeValue! )
else ( node as Element ).removeAttribute( attr.nodeName )
}

$mol_dom_render_children( node as Element, kids )
res.push( node )
continue

}

}

return res
}


}

0 comments on commit 936afe7

Please sign in to comment.