Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY] Add a name validator matching keycloak constraints #17

Merged
merged 8 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ vendor
*.idea
*.lock
/.phplint-cache
/var/log/*
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,5 @@
])
->setFinder(
PhpCsFixer\Finder::create()
->in(['src'])
->in(['src', 'tests'])
);
4 changes: 3 additions & 1 deletion .phplint.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
path: ./src
path:
- ./src
- ./tests
jobs: 10
extensions:
- php
Expand Down
19 changes: 19 additions & 0 deletions build/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="../tests/bootstrap.php" stopOnError="false" stopOnFailure="false" cacheDirectory=".phpunit.cache">
<coverage/>
<php>
<ini name="error_reporting" value="16383"/>
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>../tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">../src</directory>
</include>
</source>
</phpunit>
15 changes: 13 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,24 @@
"symfony/framework-bundle": "^5.4 || ^6.4",
"symfony/security-bundle": "^5.4 || ^6.4",
"symfony/security-core": "^5.4 || ^6.4",
"symfony/security-http": "^5.4 || ^6.4"
"symfony/security-http": "^5.4 || ^6.4",
"symfony/validator": "^5.4 || ^6.4"
},
"autoload": {
"psr-4": {
"T3G\\Bundle\\Keycloak\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"T3G\\Bundle\\Keycloak\\Tests\\": "tests/"
}
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"overtrue/phplint": "^3.0 || ^4.0",
"roave/security-advisories": "dev-latest"
"roave/security-advisories": "dev-latest",
"phpunit/phpunit": "^10.5"
},
"scripts": {
"t3g:cgl": [
Expand All @@ -51,8 +58,12 @@
"t3g:test:php:lint": [
"phplint"
],
"t3g:test:php": [
"./vendor/bin/phpunit -c build/phpunit.xml.dist"
],
"t3g:test": [
"@t3g:cgl",
"@t3g:test:php",
"@t3g:test:php:lint"
]
},
Expand Down
21 changes: 21 additions & 0 deletions src/Validator/Name.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/*
* This file is part of the package t3g/symfony-keycloak-bundle.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

namespace T3G\Bundle\Keycloak\Validator;

use Symfony\Component\Validator\Constraint;

#[\Attribute]
class Name extends Constraint
{
public const PATTERN = '/[<=>&"[\]%!#?§;*~|()^{}\f\r\t\v\x00-\x1F\x7F]/';
public string $message = 'The value {{ value }} is not a valid name.';
}
37 changes: 37 additions & 0 deletions src/Validator/NameValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/*
* This file is part of the package t3g/symfony-keycloak-bundle.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

namespace T3G\Bundle\Keycloak\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class NameValidator extends ConstraintValidator
{
public function validate(mixed $value, Constraint $constraint): void
{
if (
!is_string($value)
|| '' === $value
|| !$constraint instanceof Name
) {
return;
}

$matches = [];
preg_match_all(Name::PATTERN, $value, $matches);
if (!empty($matches[0])) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $value)
->addViolation();
}
}
}
83 changes: 83 additions & 0 deletions tests/Unit/Validator/NameValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

/*
* This file is part of the package t3g/symfony-keycloak-bundle.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

namespace T3G\Bundle\Keycloak\Tests\Unit\Validator;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
use T3G\Bundle\Keycloak\Validator\Name;
use T3G\Bundle\Keycloak\Validator\NameValidator;

class NameValidatorTest extends ConstraintValidatorTestCase
{
protected function createValidator(): NameValidator
{
return new NameValidator();
}

#[DataProvider('valuesDataProvider')]
public function testNameValidator(?string $value, bool $isValid): void
{
$this->validator->validate($value, new Name());
if (true === $isValid) {
$this->assertNoViolation();
} else {
$this->buildViolation('The value {{ value }} is not a valid name.')
->setParameter('{{ value }}', $value ?? 'null')
->assertRaised();
}
}

public static function valuesDataProvider(): array
{
return [
// Basic checks
'null' => [null, true],
'empty string' => ['', true],
'Valid name' => ['Dscherêmy-Pasquàlle Gucci', true],
'Valid name 2' => ['X Æ A-12', true],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you did there.

'Valid name 3' => ['all\' Arrabbiata', true],
// Regex Characters
'Smaller than' => ['You < Me', false],
'Equals' => ['People = Shit', false],
'Greater than' => ['Me > You', false],
'Ampersand' => ['Simon & Garfunkel', false],
'Quote' => ['Hans-Peter "HP"', false],
'Opening square bracket' => ['[Harald', false],
'Closing square bracket' => ['Sieglinde]', false],
'Percent' => ['100% creative', false],
'Exclamation mark' => ['My name\'s not Rick!', false],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed chance: I am Pickle Rick!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, never watched it. 😬

'Hash' => ['#Snoop', false],
'Question mark' => ['Am I supposed to put my name in here?', false],
'Paragraph' => ['§ 307 StGB', false],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WAS IST LOS MIT DIR 😂

'Semicolon' => ['return true;', false],
'Asterisk' => ['Ein *, der deinen Namen trägt.', false],
'Tilde' => ['~~~oO Andiii Oo~~~', false],
'Pipe' => ['Roddy |er', false],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<3

'Opening bracket' => ['(Herribert', false],
'Closing bracket' => ['Gisela)', false],
'Circumflex' => ['Ich heiße Marvin ^^', false],
'Opening curly bracket' => ['{Hugo', false],
'Closing curly bracket' => ['Jackqueline}', false],
'FORM FEED' => ["Formi\f", false],
'CARRIAGE RETURN' => ["\rPing", false],
'TAB' => ["Tele\tie", false],
'Vertical whitespace' => ["Whitespacei\n\x0B\f\r\x85\u2028\u2029", false],
'Control character' => ["Shifty\x0E", false],
'DEL character' => ["Delete\x7F", false],
// General cases
'Tags' => ['<evil-html><script>alert(\'Anyone reading this is stupid.\');</script></evil-html>', false],
'Query Strings' => ['?exposeData=true&evilParameters[]=shutdown&evilParameters%5B%5D=encoded-shutdown', false],
'SQL Queries' => ['DELETE FROM users;', false],
'Example' => ['{{7*7}}\nevil.com', false],
];
}
}
12 changes: 12 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

/*
* This file is part of the package t3g/symfony-keycloak-bundle.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

require dirname(__DIR__) . '/vendor/autoload.php';
Loading