-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from jakubboucek/feature/jb-css-color
Add sanitizing of CSS color property values
- Loading branch information
Showing
3 changed files
with
139 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace JakubBoucek\Escape; | ||
|
||
use Nette\Utils\Strings; | ||
|
||
class EscapeCss | ||
{ | ||
/** | ||
* Checks if color value is safe format of known methods | ||
* (keyword, hexadecimal, `rgb()`, `rgba()`, hsl()`, hsla()`, `lch()`, `lab()`) | ||
* otherwise return empty string. | ||
* | ||
* The `color()` format is not allowed because it's too relative to context, here is assumption the user's value | ||
* with `color()` format is not desirable. | ||
* | ||
* Valid inputs: | ||
* - `darkblue` | ||
* - `#000` | ||
* - `#00008b` | ||
* - `#00008bff` | ||
* - `#00008BFF` | ||
* - `rgb(0,0,139)` | ||
* - `rgba(0, 0, 139, 0.8)` | ||
* - `rgba(0, 0, 139 / 0.8)` | ||
* - `hsl(240,100%,27%)` | ||
* - `hsla( 240, 100%, 27%, 0.8)` | ||
* - `hsla( 240, 100%, 27% / 0.8)` | ||
* - `ActiveText` | ||
* - `lab(29.2345% 39.3825 20.0664);` | ||
* - `lab(52.2345% 40.1645 59.9971 / .5);` | ||
* - `lch(52.2345% 72.2 56.2);` | ||
* - `lch(52.2345% 72.2 56.2 / .5);` | ||
* | ||
* Invalid inputs: | ||
* - `#000; display:none` | ||
* - `black</style><script>alert(1)</script>` | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#color_keywords | ||
*/ | ||
public static function color(string $color): string | ||
{ | ||
$valid = (bool)Strings::match( | ||
$color, | ||
'/^\s*(?:[-a-zA-Z]+|#[\da-fA-F]{3,8}|(?:rgba?|hsla?|lch|lab)\([\d,.%\\/ ]+\))\s*$/D' | ||
); | ||
|
||
if ($valid === false) { | ||
return ''; | ||
} | ||
|
||
return trim($color); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
use JakubBoucek\Escape\Escape; | ||
use JakubBoucek\Escape\EscapeCss; | ||
use Tester\Assert; | ||
use Tester\Environment; | ||
use Tester\TestCase; | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
Environment::setup(); | ||
|
||
/** @testCase */ | ||
class EscapeCssTest extends TestCase | ||
{ | ||
public function getCssColorArgs(): array | ||
{ | ||
return [ | ||
// Valid values | ||
['darkblue', 'darkblue'], | ||
['#000', '#000'], | ||
['#00008b', '#00008b'], | ||
['#00008bff', '#00008bff'], | ||
['#00008BFF', '#00008BFF'], | ||
['rgb(0,0,139)', 'rgb(0,0,139)'], | ||
['rgba(0, 0, 139, 0.8)', 'rgba(0, 0, 139, 0.8)'], | ||
['rgba(0, 0, 139 / 0.8)', 'rgba(0, 0, 139 / 0.8)'], | ||
['hsl(240,100%,27%)', 'hsl(240,100%,27%)'], | ||
['hsla( 240, 100%, 27%, 0.8)', 'hsla( 240, 100%, 27%, 0.8)'], | ||
['hsla( 240, 100%, 27% / 0.8)', 'hsla( 240, 100%, 27% / 0.8)'], | ||
['ActiveText', 'ActiveText'], | ||
['lab(29.2345% 39.3825 20.0664)', 'lab(29.2345% 39.3825 20.0664)'], | ||
['lab(52.2345% 40.1645 59.9971 / .5)', 'lab(52.2345% 40.1645 59.9971 / .5)'], | ||
['lch(52.2345% 72.2 56.2)', 'lch(52.2345% 72.2 56.2)'], | ||
['lch(52.2345% 72.2 56.2 / .5)', 'lch(52.2345% 72.2 56.2 / .5)'], | ||
|
||
// Valid values with sanitizing trim spaces | ||
[' darkblue', 'darkblue'], | ||
["\tdarkblue", 'darkblue'], | ||
["\ndarkblue", 'darkblue'], | ||
["\r\ndarkblue", 'darkblue'], | ||
['darkblue ', 'darkblue'], | ||
["darkblue\t", 'darkblue'], | ||
["darkblue\n", 'darkblue'], | ||
["darkblue\r\n", 'darkblue'], | ||
|
||
// Invalid values | ||
["#000; display:none", ''], | ||
["black</style><script>alert(1)</script>", ''], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider getCssColorArgs | ||
*/ | ||
public function testCssColor(string $data, string $expected): void | ||
{ | ||
Assert::same($expected, EscapeCss::color($data)); | ||
} | ||
} | ||
|
||
(new EscapeCssTest())->run(); |