Skip to content

Commit 9338aa2

Browse files
Araqnarimiran
andauthored
fixes a possible 'javascript:' protocol exploit [backport:1.0] (#19134)
* fixes a possible 'javascript:' protocol exploit [backport:1.0] * add tests * Update tests/stdlib/trstgen.nim * add the same logic for hyperlinks * move the logic into a proc Co-authored-by: narimiran <[email protected]>
1 parent c989542 commit 9338aa2

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

lib/packages/docutils/rstgen.nim

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
## can be done by simply searching for [footnoteName].
4141

4242
import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
43-
algorithm, parseutils, std/strbasics
43+
algorithm, parseutils, std/strbasics, strscans
4444

4545
import ../../std/private/since
4646

@@ -827,6 +827,16 @@ proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
827827
rstnodeToRefname(n).idS, tmp, $chr(n.level - 1 + ord('A')), tocName])
828828

829829

830+
proc safeProtocol(linkStr: var string) =
831+
var protocol = ""
832+
if scanf(linkStr, "$w:", protocol):
833+
# if it has a protocol at all, ensure that it's not 'javascript:' or worse:
834+
if cmpIgnoreCase(protocol, "http") == 0 or cmpIgnoreCase(protocol, "https") == 0 or
835+
cmpIgnoreCase(protocol, "ftp") == 0:
836+
discard "it's fine"
837+
else:
838+
linkStr = ""
839+
830840
proc renderTocEntry(d: PDoc, e: TocEntry, result: var string) =
831841
dispA(d.target, result,
832842
"<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>\n",
@@ -891,6 +901,8 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
891901

892902
# support for `:target:` links for images:
893903
var target = esc(d.target, getFieldValue(n, "target").strip(), escMode=emUrl)
904+
safeProtocol(target)
905+
894906
if target.len > 0:
895907
# `htmlOut` needs to be of the following format for link to work for images:
896908
# <a class="reference external" href="target"><img src=\"$1\"$2/></a>
@@ -1192,6 +1204,7 @@ proc renderHyperlink(d: PDoc, text, link: PRstNode, result: var string,
11921204
d.escMode = emUrl
11931205
renderRstToOut(d, link, linkStr)
11941206
d.escMode = mode
1207+
safeProtocol(linkStr)
11951208
var textStr = ""
11961209
renderRstToOut(d, text, textStr)
11971210
let nimDocStr = if nimdoc: " nimdoc" else: ""

tests/stdlib/trstgen.nim

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ Some chapter
398398
399399
Level2
400400
------
401-
401+
402402
Level3
403403
~~~~~~
404404
@@ -407,7 +407,7 @@ Some chapter
407407
408408
More
409409
~~~~
410-
410+
411411
Another
412412
-------
413413
@@ -683,7 +683,7 @@ Test1
683683
test "RST line blocks":
684684
let input2 = dedent"""
685685
Paragraph1
686-
686+
687687
|
688688
689689
Paragraph2"""
@@ -704,7 +704,7 @@ Test1
704704
# check that '| ' with a few spaces is still parsed as new line
705705
let input4 = dedent"""
706706
| xxx
707-
|
707+
|
708708
| zzz"""
709709

710710
let output4 = input4.toHtml
@@ -1549,3 +1549,30 @@ suite "RST/Code highlight":
15491549

15501550
check strip(rstToHtml(pythonCode, {}, newStringTable(modeCaseSensitive))) ==
15511551
strip(expected)
1552+
1553+
1554+
suite "invalid targets":
1555+
test "invalid image target":
1556+
let input1 = dedent """.. image:: /images/myimage.jpg
1557+
:target: https://bar.com
1558+
:alt: Alt text for the image"""
1559+
let output1 = input1.toHtml
1560+
check output1 == """<a class="reference external" href="https://bar.com"><img src="/images/myimage.jpg" alt="Alt text for the image"/></a>"""
1561+
1562+
let input2 = dedent """.. image:: /images/myimage.jpg
1563+
:target: javascript://bar.com
1564+
:alt: Alt text for the image"""
1565+
let output2 = input2.toHtml
1566+
check output2 == """<img src="/images/myimage.jpg" alt="Alt text for the image"/>"""
1567+
1568+
let input3 = dedent """.. image:: /images/myimage.jpg
1569+
:target: bar.com
1570+
:alt: Alt text for the image"""
1571+
let output3 = input3.toHtml
1572+
check output3 == """<a class="reference external" href="bar.com"><img src="/images/myimage.jpg" alt="Alt text for the image"/></a>"""
1573+
1574+
test "invalid links":
1575+
check("(([Nim](https://nim-lang.org/)))".toHtml ==
1576+
"""((<a class="reference external" href="https://nim-lang.org/">Nim</a>))""")
1577+
check("(([Nim](javascript://nim-lang.org/)))".toHtml ==
1578+
"""((<a class="reference external" href="">Nim</a>))""")

0 commit comments

Comments
 (0)