{"record":{"id":"48e312285c3ec08a","repo":"Dolibarr/dolibarr","slug":"security-injection-exception-message","errorCode":null,"errorMessage":"Security injection exception: ${message}","messagePattern":"Security injection exception: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"htdocs/waf.inc.php","lineNumber":302,"sourceCode":"\t\t\t\t\tprint \"<br>\\n\";\n\t\t\t\t\tprint 'Try to go back, fix data of your form and resubmit it. You can contact also your technical support.';\n\n\t\t\t\t\tprint \"\\n\".'<!--'.\"\\n\";\n\t\t\t\t\tprint $errormessage2;\n\t\t\t\t\tprint \"\\n\".'-->';\n\n\t\t\t\t\t// Add entry into the PHP server error log\n\t\t\t\t\tif (function_exists('error_log')) {\n\t\t\t\t\t\terror_log($errormessage.' '.substr($errormessage2, 2000));\n\t\t\t\t\t}\n\n\t\t\t\t\t// Note: No addition into security audit table is done because we don't want to execute code in such a case.\n\t\t\t\t\t// Detection of too many such requests can be done with a fail2ban rule on 403 error code or into the PHP server error log.\n\n\n\t\t\t\t\tif (class_exists('PHPUnit\\Framework\\TestSuite')) {\n\t\t\t\t\t\t$message = $errormessage.' '.substr($errormessage2, 2000);\n\t\t\t\t\t\tthrow new Exception(\"Security injection exception: $message\");\n\t\t\t\t\t}\n\t\t\t\t\texit;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t} else {\n\t\treturn (testSqlAndScriptInject($var, $type) <= 0);\n\t}\n}\n\n// Prevent the use of method TRACE in case of the web server authorizes it (some do it by default). TRACE method can be used by attacker to steal cookies or other sensitive information.\nif (!empty($_SERVER[\"REQUEST_METHOD\"]) && $_SERVER[\"REQUEST_METHOD\"] == \"TRACE\") {\n\tprint 'Access refused with request method TRACE';\n\thttp_response_code(405);\n\texit();","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/waf.inc.php#L284-L320","documentation":"Same WAF detection as the 403 case, but this branch runs when Dolibarr detects it is executing under PHPUnit (class PHPUnit\\Framework\\TestSuite exists). Instead of exit, analyseVarsForSqlAndScriptsInjection throws a plain Exception with the 'Security injection exception: ...' message so tests can assert on it. Production code never sees this exception — production just exits with 403.","triggerScenarios":"Running Dolibarr PHPUnit tests (e.g. test/unit framework) with a request/variable containing injection-pattern content, so the WAF throws instead of exiting; also triggered by tests that deliberately post malicious payloads to verify the WAF.","commonSituations":"Writing or running Dolibarr core test suites; custom test harnesses that bootstrap main.inc.php under PHPUnit; a test fixture whose data accidentally contains script/SQL patterns.","solutions":["In tests, wrap the call in a try/catch (Exception) and assert the message starts with 'Security injection exception:'.","Clean your test fixtures: remove SQL/script-looking strings from GET/POST simulation, or set the variables the WAF considers safe.","If testing the WAF itself, expect this exception and catch it; do not rely on exit codes as in production.","Ensure NOSCANPHPUSENUMPARAMS-type guards or define('NOSCANPOSTFORINJECTION') in test bootstrap only if the test legitimately needs raw payloads."],"exampleFix":"// before\n$this->callMainIncWithMaliciousVar();\n// after\ntry {\n    $this->callMainIncWithMaliciousVar();\n    $this->fail('WAF did not trigger');\n} catch (Exception $e) {\n    $this->assertStringContainsString('Security injection exception', $e->getMessage());\n}","handlingStrategy":"try-catch","validationCode":"// test bootstrap: detect PHPUnit context and pre-scan simulated superglobals\nif (class_exists('PHPUnit\\Framework\\TestSuite')) {\n    foreach ($_GET + $_POST as $k => $v) {\n        if (!is_string($v)) continue;\n        if (preg_match('/<\\s*script|union\\s+select/i', $v)) {\n            unset($_GET[$k], $_POST[$k]);\n        }\n    }\n}","typeGuard":"function isWafTestException(Throwable $e): bool {\n    return $e instanceof Exception && str_starts_with($e->getMessage(), 'Security injection exception:');\n}","tryCatchPattern":"try {\n    $this->bootMainInc();\n} catch (Exception $e) {\n    if (str_starts_with($e->getMessage(), 'Security injection exception:')) {\n        $this->markTestSkipped('Payload rejected by WAF: '.$e->getMessage());\n    }\n    throw $e;\n}","preventionTips":["Always expect this exception (not an exit) when running tests against WAF-protected pages.","Keep test fixtures free of raw script/SQL strings.","If the test's purpose is WAF validation, assert on the exception message explicitly.","Define injection-scan exemptions only in the dedicated test bootstrap."],"tags":["waf","security","phpunit","testing"],"backgroundTag":"schema-validation-failed","analyzedSha":"598aa4bdada683d17ca04b1842548821ff0eb6c6","analyzedAt":"2026-09-14T11:12:15.309Z","contentChangedAt":"2026-09-14T11:12:15.309Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}