diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..6a29319
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,13 @@
+# CONTRIBUTING
+
+## Testing
+
+```bash
+./vendor/bin/pest
+```
+
+## Formatting
+
+```bash
+./vendor/bin/pint
+```
diff --git a/README.md b/README.md
index 79feb5b..9f8d688 100644
--- a/README.md
+++ b/README.md
@@ -9,13 +9,14 @@
## Why use Xssless
-- **Prevent XSS Attacks:** Safeguard your application by cleaning user-submitted HTML, eliminating potential XSS threats.
-- **Painless HTML 5 support:** Xssless leverages engines with the best HTML5 support.
-- **Easy to build policies:** (todo).
+- Your application features a [Rich Text Editor](https://en.wikipedia.org/wiki/Online_rich-text_editor) and you want to prevent all XSS.
+- You want full HTML5 & CSS3 support.
+- You want to allow all safe HTML elements, their attributes, and CSS properties without going deep into whitelist configs.
+- [TODO] You want a fluent and an intuitive way to build policies.
The default driver aligns with [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#html-sanitization) recommendations:
-> HTML Sanitization will strip dangerous HTML from a variable and return a safe string of HTML. OWASP recommends **DOMPurify** for HTML Sanitization.
+> ... OWASP recommends **DOMPurify** for HTML Sanitization.
## Requirements
@@ -135,18 +136,6 @@ Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed re
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
-### Testing
-
-```bash
-./vendor/bin/pest
-```
-
-### Formatting
-
-```bash
-./vendor/bin/pint
-```
-
## Security Vulnerabilities
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
diff --git a/composer.json b/composer.json
index 138b879..95e64c8 100644
--- a/composer.json
+++ b/composer.json
@@ -5,7 +5,8 @@
"xss",
"sanitizer",
"purifier",
- "html"
+ "html",
+ "laravel"
],
"homepage": "https://github.com/medilies/xssless",
"license": "MIT",
diff --git a/src/Dompurify/DompurifyService.php b/src/Dompurify/DompurifyService.php
index eef8783..caf04e6 100644
--- a/src/Dompurify/DompurifyService.php
+++ b/src/Dompurify/DompurifyService.php
@@ -145,6 +145,4 @@ private function isSigTerm(): bool
// {
// return $this->serviceProcess->getTermSignal() === 1;
// }
-
- // 92..97, 104, 113..136
}
diff --git a/src/Dompurify/DompurifyServiceConfig.php b/src/Dompurify/DompurifyServiceConfig.php
index e3bf332..c953ffa 100644
--- a/src/Dompurify/DompurifyServiceConfig.php
+++ b/src/Dompurify/DompurifyServiceConfig.php
@@ -6,13 +6,13 @@
class DompurifyServiceConfig implements ConfigInterface
{
- public readonly string $class;
+ private readonly string $class;
public function __construct(
public string $node = 'node',
public string $npm = 'npm',
public string $host = '127.0.0.1',
- public int $port = 6300,
+ public int $port = 63000,
public ?string $binary = null,
) {
$this->class = DompurifyService::class;
diff --git a/src/Xssless.php b/src/Xssless.php
index 01cb8ed..1b6d0bb 100755
--- a/src/Xssless.php
+++ b/src/Xssless.php
@@ -8,9 +8,9 @@ class Xssless
// TODO: policy builder
- public function clean(string $html, ?ConfigInterface $config = null): string
+ public function clean(string $html, ?ConfigInterface $tempConfig = null): string
{
- $cleaner = $this->makeCleaner($config);
+ $cleaner = $this->makeCleaner($tempConfig);
return match (true) {
$cleaner instanceof CliInterface => $this->exec($cleaner, $html),
@@ -18,9 +18,9 @@ public function clean(string $html, ?ConfigInterface $config = null): string
};
}
- public function start(?ConfigInterface $config = null): ServiceInterface
+ public function start(?ConfigInterface $tempConfig = null): ServiceInterface
{
- $service = $this->makeCleaner($config);
+ $service = $this->makeCleaner($tempConfig);
if (! $service instanceof ServiceInterface) {
throw new XsslessException("'".$service::class."' must implement: '".ServiceInterface::class."'.");
@@ -29,9 +29,9 @@ public function start(?ConfigInterface $config = null): ServiceInterface
return $service->start();
}
- public function setup(?ConfigInterface $config = null): void
+ public function setup(?ConfigInterface $tempConfig = null): void
{
- $service = $this->makeCleaner($config);
+ $service = $this->makeCleaner($tempConfig);
if (! $service instanceof HasSetupInterface) {
throw new XsslessException("'".$service::class."' must implement: '".HasSetupInterface::class."'.");
@@ -66,9 +66,9 @@ public function using(ConfigInterface $config): static
return $this;
}
- private function makeCleaner(?ConfigInterface $config = null): CliInterface|ServiceInterface
+ private function makeCleaner(?ConfigInterface $tempConfig = null): CliInterface|ServiceInterface
{
- $config ??= $this->config ?? null;
+ $config = $tempConfig ?? $this->config ?? null;
if (is_null($config)) {
throw new XsslessException('A config must be provided.');
diff --git a/src/laravel/Facades/Xssless.php b/src/laravel/Facades/Xssless.php
index b1feb20..6e0aa7f 100644
--- a/src/laravel/Facades/Xssless.php
+++ b/src/laravel/Facades/Xssless.php
@@ -18,6 +18,7 @@ class Xssless extends Facade
{
protected static function getFacadeAccessor(): string
{
+ // TODO: model cast
return \Medilies\Xssless\Xssless::class;
}
}
diff --git a/tests/Dompurify/DompurifyCliTest.php b/tests/Dompurify/DompurifyCliTest.php
index 46cedd1..84336ff 100644
--- a/tests/Dompurify/DompurifyCliTest.php
+++ b/tests/Dompurify/DompurifyCliTest.php
@@ -8,27 +8,20 @@
it('throws on bad node path', function () {
$cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig(
- 'nodeZz',
- 'npm',
+ node: 'nodeZz',
));
expect(fn () => $cleaner->exec('foo'))->toThrow(ProcessFailedException::class);
});
test('setup()', function () {
- $cleaner = (new Xssless)->using(new DompurifyCliConfig(
- 'node',
- 'npm',
- ));
+ $cleaner = (new Xssless)->using(new DompurifyCliConfig);
expect(fn () => $cleaner->setup())->not->toThrow(Exception::class);
});
test('exec()', function () {
- $cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig(
- 'node',
- 'npm',
- ));
+ $cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig);
$clean = $cleaner->exec('">');
@@ -37,8 +30,6 @@
test('clean()', function () {
$cleaner = (new Xssless)->using(new DompurifyCliConfig(
- node: 'node',
- npm: 'npm',
tempFolder: __DIR__,
));
@@ -49,8 +40,6 @@
it('throws when cannot read cleaned file', function () {
$cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig(
- node: 'node',
- npm: 'npm',
binary: __DIR__.'/js-mocks/cli-returns-bad-path.js',
));
@@ -59,8 +48,6 @@
it('throws when cannot find binary file', function () {
$cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig(
- node: 'node',
- npm: 'npm',
binary: __DIR__.'/js-mocks/x.js',
));
@@ -69,8 +56,6 @@
it('throws when cannot locate temp folder', function () {
$cleaner = (new DompurifyCli)->configure(new DompurifyCliConfig(
- node: 'node',
- npm: 'npm',
tempFolder: __DIR__.'/x',
));
diff --git a/tests/Dompurify/DompurifyServiceTest.php b/tests/Dompurify/DompurifyServiceTest.php
index 1bc2751..5422165 100644
--- a/tests/Dompurify/DompurifyServiceTest.php
+++ b/tests/Dompurify/DompurifyServiceTest.php
@@ -7,23 +7,13 @@
use Symfony\Component\Process\Exception\ProcessFailedException;
test('setup()', function () {
- $cleaner = (new DompurifyService)->configure(new DompurifyServiceConfig(
- 'node',
- 'npm',
- '127.0.0.1',
- 63000,
- ));
+ $cleaner = (new DompurifyService)->configure(new DompurifyServiceConfig);
expect(fn () => $cleaner->setup())->not->toThrow(Exception::class);
});
test('send()', function () {
- $cleaner = (new DompurifyService)->configure(new DompurifyServiceConfig(
- 'node',
- 'npm',
- '127.0.0.1',
- 63000,
- ));
+ $cleaner = (new DompurifyService)->configure(new DompurifyServiceConfig);
$cleaner->start();
@@ -38,10 +28,7 @@
test('clean()', function () {
$config = new DompurifyServiceConfig(
- 'node',
- 'npm',
- '127.0.0.1',
- 63001,
+ port: 63001, // for parallel tests
);
$cleaner = (new Xssless)->using($config);
@@ -59,10 +46,7 @@
it('throws on bad host', function () {
$cleaner = (new DompurifyService)->configure(new DompurifyServiceConfig(
- 'node',
- 'npm',
- 'a.b.c.example.com',
- 63000,
+ host: 'a.b.c.example.com',
));
$dirty = '">';
@@ -72,10 +56,7 @@
it('throws on bad node path', function () {
$service = (new DompurifyService)->configure(new DompurifyServiceConfig(
- 'nodeZz',
- 'npm',
- '127.0.0.1',
- 5555555555,
+ node: 'nodeZz',
));
expect(fn () => $service->start())->toThrow(ProcessFailedException::class);
diff --git a/tests/Pest.php b/tests/Pest.php
index f3d76d1..1a8db6d 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -1,6 +1,5 @@
in(__DIR__);
+uses(TestCase::class)->in(__DIR__);
diff --git a/tests/TestCase.php b/tests/TestCase.php
deleted file mode 100644
index cfb05b6..0000000
--- a/tests/TestCase.php
+++ /dev/null
@@ -1,10 +0,0 @@
-