{"record":{"id":"4954113ef02f5993","repo":"Dolibarr/dolibarr","slug":"if-you-access-your-server-behind-a-proxy-using-url-rewriting","errorCode":null,"errorMessage":"If you access your server behind a proxy using url rewriting and the parameter is provided by caller, you might check that all HTTP header are propagated (or add the line $dolibarr_nocsrfcheck=1 into your conf.php file or MAIN_SECURITY_CSRF_WITH_TOKEN to 0${current_value} into setup).","messagePattern":"If you access your server behind a proxy using url rewriting and the parameter is provided by caller, you might check that all HTTP header are propagated \\(or add the line \\$dolibarr_nocsrfcheck=1 into your conf\\.php file or MAIN_SECURITY_CSRF_WITH_TOKEN to 0(.+?) into setup\\)\\.","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"htdocs/main.inc.php","lineNumber":444,"sourceCode":"\t\t((GETPOSTISSET('actionlogin') || GETPOSTISSET('action')) && defined('CSRFCHECK_WITH_TOKEN'))\n\t) {\n\t\t// If token is not provided or empty, error (we are in case it is mandatory)\n\t\tif (!GETPOST('token', 'alpha') || GETPOST('token', 'alpha') == 'notrequired') {\n\t\t\ttop_httphead();\n\t\t\tif (GETPOSTINT('uploadform')) {\n\t\t\t\tdol_syslog(\"--- Access to \".(empty($_SERVER[\"REQUEST_METHOD\"]) ? '' : $_SERVER[\"REQUEST_METHOD\"].' ').$_SERVER[\"PHP_SELF\"].\" refused. File size too large or not provided.\");\n\t\t\t\t$langs->loadLangs(array(\"errors\", \"install\"));\n\t\t\t\tprint $langs->trans(\"ErrorFileSizeTooLarge\").' ';\n\t\t\t\tprint $langs->trans(\"ErrorGoBackAndCorrectParameters\");\n\t\t\t} else {\n\t\t\t\thttp_response_code(403);\n\t\t\t\tif (defined('CSRFCHECK_WITH_TOKEN')) {\n\t\t\t\t\tdol_syslog(\"--- Access to \".(empty($_SERVER[\"REQUEST_METHOD\"]) ? '' : $_SERVER[\"REQUEST_METHOD\"].' ').$_SERVER[\"PHP_SELF\"].\" refused by CSRF protection (CSRFCHECK_WITH_TOKEN protection) in main.inc.php. Token not provided.\", LOG_WARNING);\n\t\t\t\t\tprint \"Access to a page that needs a token (constant CSRFCHECK_WITH_TOKEN is defined) is refused by CSRF protection in main.inc.php. Token not provided.\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tdol_syslog(\"--- Access to \".(empty($_SERVER[\"REQUEST_METHOD\"]) ? '' : $_SERVER[\"REQUEST_METHOD\"].' ').$_SERVER[\"PHP_SELF\"].\" refused by CSRF protection (POST method or GET with a sensible value for 'action' parameter) in main.inc.php. Token not provided.\", LOG_WARNING);\n\t\t\t\t\tprint \"Access to this page this way (POST method or GET with a sensible value for 'action' parameter) is refused by CSRF protection in main.inc.php. Token not provided.\\n\";\n\t\t\t\t\tprint \"If you access your server behind a proxy using url rewriting and the parameter is provided by caller, you might check that all HTTP header are propagated (or add the line \\$dolibarr_nocsrfcheck=1 into your conf.php file or MAIN_SECURITY_CSRF_WITH_TOKEN to 0\";\n\t\t\t\t\tif (getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN')) {\n\t\t\t\t\t\tprint \" instead of \" . getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN');\n\t\t\t\t\t}\n\t\t\t\t\tprint \" into setup).\\n\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tdie;\n\t\t}\n\t}\n\n\t$sessiontokenforthisurl = (empty($_SESSION['token']) ? '' : $_SESSION['token']);\n\t// TODO Get the sessiontokenforthisurl into an array of session token (one array per base URL so we can use the CSRF per page and we keep ability for several tabs per url in a browser)\n\tif (GETPOSTISSET('token') && GETPOST('token') != 'notrequired' && GETPOST('token', 'alpha') != $sessiontokenforthisurl) {\n\t\tdol_syslog(\"--- Access to \".(empty($_SERVER[\"REQUEST_METHOD\"]) ? '' : $_SERVER[\"REQUEST_METHOD\"].' ').$_SERVER[\"PHP_SELF\"].\" refused by CSRF protection (invalid token), so we disable POST and some GET parameters - referrer=\".(empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']).\", action=\".GETPOST('action', 'aZ09').\", _GET|POST['token']=\".GETPOST('token', 'alpha'), LOG_WARNING);\n\t\t//dol_syslog(\"_SESSION['token']=\".$sessiontokenforthisurl, LOG_DEBUG);\n\t\t// Do not output anything on standard output because this create problems when using the BACK button on browsers. So we just set a message into session.\n\t\tif (!defined('NOTOKENRENEWAL')) {\n\t\t\t// If the page is not a page that disable the token renewal, we report a warning message to explain token has expired.","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/main.inc.php#L426-L462","documentation":"This is not a standalone error but the trailing hint appended to the generic CSRF refusal (error 8): it explains that behind a proxy with URL rewriting the token parameter may be lost, and suggests checking header propagation, setting $dolibarr_nocsrfcheck=1 in conf.php, or changing MAIN_SECURITY_CSRF_WITH_TOKEN to 0 in setup. The current value of MAIN_SECURITY_CSRF_WITH_TOKEN is interpolated when set.","triggerScenarios":"CSRF refusal occurs while the site is served behind a reverse proxy doing URL rewriting that drops query strings, or the operator intends to relax the token check via conf.php/setup constants.","commonSituations":"Nginx/Apache reverse proxy rewrite rules stripping 'token='; misconfigured trusted-proxy header propagation; admins considering disabling CSRF token enforcement (security trade-off).","solutions":["Fix proxy rewrite rules so the query string (including token) is preserved (e.g. proxy_pass with $uri/$args, keep original args)","Propagate all HTTP headers (Host, X-Forwarded-*) to the backend","If truly required, add $dolibarr_nocsrfcheck=1; to conf.php — understand this weakens security","Or set MAIN_SECURITY_CSRF_WITH_TOKEN to 0 in Home > Setup > Other Setup"],"exampleFix":"# before (nginx)\nrewrite ^/dolibarr/(.*)$ /index.php last;\n# after\nrewrite ^/dolibarr/(.*)$ /index.php?$args last;","handlingStrategy":"validation","validationCode":"// Behind a proxy, verify the query string reaches PHP:\nif (empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['REQUEST_URI'], '?') !== false) { error_log('Proxy is stripping query string'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Test token-bearing URLs through the full proxy chain before go-live","Preserve query args in rewrite rules and pass all headers upstream","Treat $dolibarr_nocsrfcheck=1 as a last resort — it disables CSRF protection","Document proxy setup when deploying Dolibarr behind nginx/Apache/Cloudflare"],"tags":["csrf","dolibarr","proxy","security","configuration"],"backgroundTag":"invalid-config-value","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"}