diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 13358074514..da93b01fc26 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -778,12 +778,16 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options =
do {
$oldstringtoclean = $out;
+ // Ckeditor use the numeric entitic for apostrophe so we force it to text entity (all other special chars are correctly
+ // encoded using text entities). This is a fix for CKeditor.
+ $out = preg_replace('/'/i', ''', $out);
+
// We replace chars from a/A to z/Z encoded with numeric HTML entities with the real char so we won't loose the chars at the next step.
// No need to use a loop here, this step is not to sanitize (this is done at next step, this is to try to save chars, even if they are
// using a non coventionnel way to be encoded, to not have them sanitized just after)
$out = preg_replace_callback('/(x?[0-9][0-9a-f]+;?)/i', 'realCharForNumericEntities', $out);
- // Now we remove all remaining HTML entities staring with a number. We don't want such entities.
+ // Now we remove all remaining HTML entities starting with a number. We don't want such entities.
$out = preg_replace('/?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'.
$out = dol_string_onlythesehtmltags($out, 0, 1, 1);
diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php
index 08d4ec88703..d75ec962020 100644
--- a/test/phpunit/SecurityTest.php
+++ b/test/phpunit/SecurityTest.php
@@ -321,6 +321,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase
$test="XSS";
$result=testSqlAndScriptInject($test, 0);
$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject lll');
+
+ $test="Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)";
+ $result=testSqlAndScriptInject($test, 0);
+ $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject mmm');
}
/**
@@ -358,6 +362,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase
$_POST["param12"]='aaa';
$_POST["param13"]='n n > < " XSS';
$_POST["param13b"]='n n > < " XSS';
+ $_POST["param14"]="Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)";
//$_POST["param13"]='javascript%26colon%26%23x3B%3Balert(1)';
//$_POST["param14"]='javascripT&javascript#x3a alert(1)';
@@ -494,6 +499,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase
print __METHOD__." result=".$result."\n";
$this->assertEquals('n n > < " XSS', $result, 'Test 13b that HTML entities are decoded with restricthtml, but only for common alpha chars');
+ $result=GETPOST("param14", 'restricthtml');
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals("Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)", $result, 'Test 14');
+
// Special test for GETPOST of backtopage, backtolist or backtourl parameter
$_POST["backtopage"]='//www.google.com';