Skip to content

Commit

Permalink
Merge pull request #1 from jakubboucek/feature/jb-css-color
Browse files Browse the repository at this point in the history
Add sanitizing of CSS color property values
  • Loading branch information
jakubboucek authored Sep 5, 2021
2 parents 9994c6f + 79d6799 commit 88f13a8
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 3 deletions.
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ Package is substrate of [Latte package](https://github.com/nette/latte/)
- Escape HTML attributes
- Escape HTML comments
- Escape JS
- Escape CSS
- Escape URL
- Escape CSS
- Escape CSS specifics for few properties:
- `color` value

## Install

Expand All @@ -34,12 +36,28 @@ Use:
echo 'Registered user: ' . \JakubBoucek\Escape\Escape::html($username);
```

## CSS specifics

In few cases you cannot use `\JakubBoucek\Escape\Escape::css($cssColor)` to escape
some known format, because standard escaping is broke CSS format. Class `EscapeCss` has prepared
limited set of known propetries with specefics format:

### `color` property

Sanitize value od CSS `color` property to safe format, example:

```php
echo '<style>color: ' . \JakubBoucek\Escape\EscapeCss::color($cssColor) . ';</style>';
```
It's prevent attact by escaping color value context.
## FAQ
### Is it support for escaping SQL query?
No, SQL requires access to active SQL connection to right escape. This package is only aloow to escape contexts without
external requrements.
No, SQL requires access to active SQL connection to right escape. This package is only allows to escape contexts without
external requirements.
## Contributing
Please don't hesitate send Issue or Pull Request.
Expand Down
56 changes: 56 additions & 0 deletions src/EscapeCss.php
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);
}
}
62 changes: 62 additions & 0 deletions tests/EscapeCssTest.php
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();

0 comments on commit 88f13a8

Please sign in to comment.