Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Commit

Permalink
add allow_relative_links setting
Browse files Browse the repository at this point in the history
  • Loading branch information
olegatro committed Mar 18, 2021
1 parent 77c0116 commit f4e7747
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 11 deletions.
15 changes: 15 additions & 0 deletions docs/1-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ $sanitizer = HtmlSanitizer\Sanitizer::create([
* If true, mailto links will be accepted.
*/
'allow_mailto' => false,

/*
* If true, relative links will be accepted.
*/
'allow_relative_links' => false,
],

'img' => [
Expand All @@ -111,6 +116,11 @@ $sanitizer = HtmlSanitizer\Sanitizer::create([
* If true, images data-uri URLs will be accepted.
*/
'allow_data_uri' => false,

/*
* If true, relative links will be accepted.
*/
'allow_relative_links' => false,
],

'iframe' => [
Expand All @@ -124,6 +134,11 @@ $sanitizer = HtmlSanitizer\Sanitizer::create([
* 'allowed_hosts' => ['trusted1.com', 'google.com'],
*/
'allowed_hosts' => null,

/*
* If true, relative links will be accepted.
*/
'allow_relative_links' => false,
],
],
]);
Expand Down
2 changes: 2 additions & 0 deletions src/Extension/Basic/NodeVisitor/ANodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function __construct(array $config = [])
$this->config['allowed_schemes'],
$this->config['allowed_hosts'],
$this->config['allow_mailto'],
$this->config['allow_relative_links'],
$this->config['force_https']
);
}
Expand All @@ -61,6 +62,7 @@ public function getDefaultConfiguration(): array
'allowed_schemes' => ['http', 'https'],
'allowed_hosts' => null,
'allow_mailto' => true,
'allow_relative_links' => false,
'force_https' => false,
];
}
Expand Down
12 changes: 11 additions & 1 deletion src/Extension/Basic/Sanitizer/AHrefSanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ class AHrefSanitizer
private $allowedSchemes;
private $allowedHosts;
private $allowMailTo;
private $allowRelativeLinks;
private $forceHttps;

public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $allowMailTo, bool $forceHttps)
public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $allowMailTo, bool $allowRelativeLinks, bool $forceHttps)
{
$this->allowedSchemes = $allowedSchemes;
$this->allowedHosts = $allowedHosts;
$this->allowMailTo = $allowMailTo;
$this->allowRelativeLinks = $allowRelativeLinks;
$this->forceHttps = $forceHttps;
}

Expand All @@ -46,6 +48,14 @@ public function sanitize(?string $input): ?string
}
}

if ($this->allowRelativeLinks) {
$allowedSchemes[] = null;

if (\is_array($this->allowedHosts)) {
$allowedHosts[] = null;
}
}

if (!$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps)) {
return null;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Extension/Iframe/NodeVisitor/IframeNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function __construct(array $config = [])
$this->sanitizer = new IframeSrcSanitizer(
$this->config['allowed_schemes'],
$this->config['allowed_hosts'],
$this->config['allow_relative_links'],
$this->config['force_https']
);
}
Expand All @@ -64,6 +65,7 @@ public function getDefaultConfiguration(): array
return [
'allowed_schemes' => ['http', 'https'],
'allowed_hosts' => null,
'allow_relative_links' => false,
'force_https' => false,
];
}
Expand Down
17 changes: 15 additions & 2 deletions src/Extension/Iframe/Sanitizer/IframeSrcSanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,30 @@ class IframeSrcSanitizer

private $allowedSchemes;
private $allowedHosts;
private $allowRelativeLinks;
private $forceHttps;

public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $forceHttps)
public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $allowRelativeLinks, bool $forceHttps)
{
$this->allowedSchemes = $allowedSchemes;
$this->allowedHosts = $allowedHosts;
$this->allowRelativeLinks = $allowRelativeLinks;
$this->forceHttps = $forceHttps;
}

public function sanitize(?string $input): ?string
{
return $this->sanitizeUrl($input, $this->allowedSchemes, $this->allowedHosts, $this->forceHttps);
$allowedSchemes = $this->allowedSchemes;
$allowedHosts = $this->allowedHosts;

if ($this->allowRelativeLinks) {
$allowedSchemes[] = null;

if (\is_array($this->allowedHosts)) {
$allowedHosts[] = null;
}
}

return $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps);
}
}
2 changes: 2 additions & 0 deletions src/Extension/Image/NodeVisitor/ImgNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function __construct(array $config = [])
$this->config['allowed_schemes'],
$this->config['allowed_hosts'],
$this->config['allow_data_uri'],
$this->config['allow_relative_links'],
$this->config['force_https']
);
}
Expand All @@ -61,6 +62,7 @@ public function getDefaultConfiguration(): array
'allowed_schemes' => ['http', 'https'],
'allowed_hosts' => null,
'allow_data_uri' => false,
'allow_relative_links' => false,
'force_https' => false,
];
}
Expand Down
13 changes: 11 additions & 2 deletions src/Extension/Image/Sanitizer/ImgSrcSanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ class ImgSrcSanitizer
private $allowedSchemes;
private $allowedHosts;
private $allowDataUri;
private $allowRelativeLinks;
private $forceHttps;

public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $allowDataUri, bool $forceHttps)
public function __construct(array $allowedSchemes, ?array $allowedHosts, bool $allowDataUri, bool $allowRelativeLinks, bool $forceHttps)
{
$this->allowedSchemes = $allowedSchemes;
$this->allowedHosts = $allowedHosts;
$this->allowDataUri = $allowDataUri;
$this->allowRelativeLinks = $allowRelativeLinks;
$this->forceHttps = $forceHttps;
}

Expand All @@ -38,13 +40,20 @@ public function sanitize(?string $input): ?string
$allowedSchemes = $this->allowedSchemes;
$allowedHosts = $this->allowedHosts;

if ($this->allowDataUri) {
if ($this->allowDataUri && !$this->allowRelativeLinks) {
$allowedSchemes[] = 'data';
if (null !== $allowedHosts) {
$allowedHosts[] = null;
}
}

if ($this->allowRelativeLinks) {
$allowedSchemes[] = null;
if (null !== $allowedHosts) {
$allowedHosts[] = null;
}
}

if (!$sanitized = $this->sanitizeUrl($input, $allowedSchemes, $allowedHosts, $this->forceHttps)) {
return null;
}
Expand Down
29 changes: 27 additions & 2 deletions tests/Sanitizer/AHrefSanitizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'https://trusted.com/link.php',
'output' => 'https://trusted.com/link.php',
Expand All @@ -32,6 +33,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => ['trusted.com'],
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'https://trusted.com/link.php',
'output' => 'https://trusted.com/link.php',
Expand All @@ -41,6 +43,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => ['trusted.com'],
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'https://untrusted.com/link.php',
'output' => null,
Expand All @@ -50,6 +53,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => '/link.php',
'output' => null,
Expand All @@ -59,16 +63,28 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => '/link.php',
'output' => null,
];

yield [
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => true,
'forceHttps' => false,
'input' => '/link.php',
'output' => '/link.php',
];

// Force HTTPS
yield [
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => ['trusted.com'],
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => true,
'input' => 'http://trusted.com/link.php',
'output' => 'https://trusted.com/link.php',
Expand All @@ -79,6 +95,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'output' => null,
Expand All @@ -88,6 +105,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => true,
'input' => 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'output' => null,
Expand All @@ -98,6 +116,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => false,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'mailto:test@gmail.com',
'output' => null,
Expand All @@ -107,6 +126,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'mailto:test@gmail.com',
'output' => 'mailto:test@gmail.com',
Expand All @@ -116,6 +136,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => ['trusted.com'],
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'mailto:test@gmail.com',
'output' => 'mailto:test@gmail.com',
Expand All @@ -125,6 +146,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => ['trusted.com'],
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => true,
'input' => 'mailto:test@gmail.com',
'output' => 'mailto:test@gmail.com',
Expand All @@ -134,6 +156,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'mailto:invalid',
'output' => null,
Expand All @@ -143,6 +166,7 @@ public function provideUrls()
'allowedSchemes' => ['http', 'https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'mailto:',
'output' => null,
Expand All @@ -152,6 +176,7 @@ public function provideUrls()
'allowedSchemes' => ['https'],
'allowedHosts' => null,
'allowMailTo' => true,
'allowRelativeLinks' => false,
'forceHttps' => false,
'input' => 'http://trusted.com/link.php',
'output' => null,
Expand All @@ -161,8 +186,8 @@ public function provideUrls()
/**
* @dataProvider provideUrls
*/
public function testSanitize($allowedSchemes, $allowedHosts, $allowMailTo, $forceHttps, $input, $expected)
public function testSanitize($allowedSchemes, $allowedHosts, $allowMailTo, $allowRelativeLinks, $forceHttps, $input, $expected)
{
$this->assertSame($expected, (new AHrefSanitizer($allowedSchemes, $allowedHosts, $allowMailTo, $forceHttps))->sanitize($input));
$this->assertSame($expected, (new AHrefSanitizer($allowedSchemes, $allowedHosts, $allowMailTo, $allowRelativeLinks, $forceHttps))->sanitize($input));
}
}
Loading

0 comments on commit f4e7747

Please sign in to comment.