Skip to content

Commit aef30dd

Browse files
committed
Implement tight security filtering by default
1 parent de4ebe2 commit aef30dd

2 files changed

Lines changed: 32 additions & 5 deletions

File tree

Filter/Security.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,15 @@ public function filter(mixed $value, FilterScope $scope): mixed
1111
}
1212

1313
$value = (string)$value;
14-
$value = strip_tags($value);
15-
$value = htmlspecialchars_decode($value);
16-
return $value;
14+
15+
do {
16+
$previous = $value;
17+
$value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5);
18+
$value = strip_tags($value);
19+
} while ($value !== $previous);
20+
21+
$value = preg_replace('/(?:javascript|vbscript|data)\s*:/i', '', $value);
22+
23+
return trim($value);
1724
}
1825
}

Test/Unit/Filter/SecurityTest.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,35 @@
33
namespace Loki\Components\Test\Unit\Filter;
44

55
use Loki\Components\Filter\FilterScope;
6+
use PHPUnit\Framework\Attributes\DataProvider;
67
use PHPUnit\Framework\TestCase;
78
use Loki\Components\Filter\Security;
89

910
class SecurityTest extends TestCase
1011
{
11-
public function testFilter()
12+
#[DataProvider('filterDataProvider')]
13+
public function testFilter(string $input, string $expected): void
1214
{
1315
$filterScope = new FilterScope();
1416
$filter = new Security();
15-
$this->assertEquals('foobar', $filter->filter('<script>foobar</script>', $filterScope));
17+
$this->assertSame($expected, $filter->filter($input, $filterScope));
18+
}
19+
20+
public static function filterDataProvider(): array
21+
{
22+
return [
23+
'script tag with content' => ['<script>foobar</script>', 'foobar'],
24+
'bare script tag' => ['<script>', ''],
25+
'encoded script tag' => ['&lt;script&gt;', ''],
26+
'double encoded script tag' => ['&amp;lt;script&amp;gt;', ''],
27+
'broken out img onerror' => ['"><img src=x onerror=1>', '">'],
28+
'javascript scheme' => ['javascript:alert(1)', 'alert(1)'],
29+
'vbscript scheme' => ['vbscript:msgbox(1)', 'msgbox(1)'],
30+
'img onerror' => ['<img src=x onerror=alert(1)>', ''],
31+
'encoded bold tags' => ['&lt;b&gt;already&lt;/b&gt;', 'already'],
32+
'anchor with javascript href' => ['<a href="javascript:alert(1)">x</a>', 'x'],
33+
'benign markup with entity' => ['<b>bold</b> &amp; text', 'bold & text'],
34+
'plain text' => ['plain text', 'plain text'],
35+
];
1636
}
1737
}

0 commit comments

Comments
 (0)