Skip to content

Commit 97365f5

Browse files
committed
Add a basic test for SVG sanitation
1 parent 163abe3 commit 97365f5

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

webapp/src/Controller/Jury/SubmissionController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ public function viewAction(
581581
'requestedOutputCount' => $requestedOutputCount,
582582
'version_warnings' => [],
583583
'isMultiPassProblem' => $submission->getProblem()->isMultipassProblem(),
584+
'thumbnailSize' => $this->config->get('thumbnail_size'),
584585
];
585586

586587
if ($selectedJudging === null) {

webapp/src/Controller/Team/SubmissionController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ public function viewAction(Request $request, int $submitId): Response
200200
'showSampleOutput' => $showSampleOutput,
201201
'runs' => $runs,
202202
'showTooLateResult' => $showTooLateResult,
203+
'thumbnailSize' => $this->config->get('thumbnail_size'),
203204
];
204205
if ($actuallyShowCompile) {
205206
$data['size'] = 'xl';

webapp/templates/jury/submission.html.twig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
.judging-table tr.disabled td a {
2020
color: silver
2121
}
22+
23+
.image_thumb {
24+
max-width: {{ thumbnailSize }}px;
25+
max-height: {{ thumbnailSize }}px;
26+
}
2227
</style>
2328
{% endblock %}
2429

webapp/tests/Unit/Utils/UtilsTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,55 @@ public function provideTestGetImageSize(): Generator
713713
yield [__DIR__ . '/../../../public/images/DOMjudgelogo.svg', 510, 1122];
714714
}
715715

716+
public function testSanitizeSvg(): void
717+
{
718+
// SVG source: https://svg.enshrined.co.uk/
719+
$dirty = <<<EOF
720+
<?xml version="1.0" encoding="utf-8" ?>
721+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
722+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve">
723+
<rect fill="url('http://example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
724+
<rect fill="url('https://example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
725+
<rect fill=" url( ' https://example.com/benis.svg ' ) " x="0" y="0" width="1000" height="1000"></rect>
726+
<rect fill="url('ftp://192.168.2.1/benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
727+
<rect fill="url('//example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
728+
<rect fill="url('/benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
729+
<rect fill="url('#benis.svg')" x="0" y="0" width="1000" height="1000"></rect>
730+
<g id="righteye" class="eye">
731+
<path id="iris-2" data-name="iris" class="cls-4" d="M241.4,143.6s18.5,11.9,36,7.1,29.6-15.8,27.2-24.6c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,60.14,60.14,0,0,0-14.9,18.3" transform="translate(-9.7 -9.3)"/>
732+
<path id="lid" class="cls-11" d="M304.5,124.4c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,61.21,61.21,0,0,0-14.9,18.1" transform="translate(-9.7 -9.3)"/>
733+
<path id="pupil-2" data-name="pupil" class="cls-12" d="M256.7,126.1c2.5,9.2,11,14.8,18.9,12.6s12.3-11.4,9.8-20.6a16.59,16.59,0,0,0-1.2-3.1,59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,9.23,9.23,0,0,0,.5,2.5" transform="translate(-9.7 -9.3)"/>
734+
<path id="eyelash-2" data-name="eyelash" class="cls-13" d="M302.9,122.3c7.7,2.5,17-5,20.8-16.8M292,115.7c7.6,2.8,17.2-4.4,21.4-16M277,115.1c8.1-.3,14.3-10.5,13.9-22.8" transform="translate(-9.7 -9.3)"/>
735+
<path id="reflection-2" data-name="reflection" class="cls-14" d="M271.1,127.1c0,3.6-2.6,6.5-5.8,6.5s-5.8-2.9-5.8-6.5,2.6-6.4,5.8-6.4,5.8,2.9,5.8,6.4" transform="translate(-9.7 -9.3)"/>
736+
</g>
737+
<a href="javascript:alert(2)">test 1</a>
738+
<a xlink:href="javascript:alert(2)">test 2</a>
739+
<a href="#test3">test 3</a>
740+
<a xlink:href="#test">test 4</a>
741+
742+
<a href="data:data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 5</a>
743+
<a xlink:href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 6</a>
744+
<use xlink:href="defs.svg#icon-1"/>
745+
<line onload="alert(2)" fill="none" stroke="#000000" stroke-miterlimit="10" x1="119" y1="84.5" x2="454" y2="84.5"/>
746+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="111.212" y1="102.852" x2="112.032" y2="476.623"/>
747+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="198.917" y1="510.229" x2="486.622" y2="501.213"/>
748+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="484.163" y1="442.196" x2="89.901" y2="60.229"/>
749+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="101.376" y1="478.262" x2="443.18" y2="75.803"/>
750+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="457.114" y1="126.623" x2="458.753" y2="363.508"/>
751+
<this>shouldn't be here</this>
752+
<script>alert(1);</script>
753+
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="541.54" y1="299.573" x2="543.179" y2="536.458"/>
754+
755+
</svg>
756+
EOF;
757+
$clean = Utils::sanitizeSvg($dirty);
758+
self::assertFalse(str_contains($clean, "script"));
759+
self::assertFalse(str_contains($clean, "alert"));
760+
self::assertFalse(str_contains($clean, "shouldn't be here"));
761+
self::assertFalse(str_contains($clean, "example.com"));
762+
self::assertTrue(str_contains($clean, '</svg>'));
763+
}
764+
716765
/**
717766
* Test that the wrapUnquoted function returns the correct result
718767
*/

0 commit comments

Comments
 (0)