Dolibarr/dolibarr · error
Access refused by CSRF protection in main.inc.php. Referrer…
Error message
Access refused by CSRF protection in main.inc.php. Referrer of form (${HTTP_REFERER}) is outside the server that serve this page (with method = ${REQUEST_METHOD}). What it means
filefunc.inc.php performs an early CSRF referrer check for state-changing requests (POST/PUT/etc.): HTTP_REFERER host must match the server's HTTP_HOST (or be empty/allowed). When a form is submitted from a page on another origin, $csrfattack is set, Dolibarr logs a warning, prints this message plus the proxy hint, and dies. It protects against cross-site form posts before the token check (MAIN_SECURITY_CSRF_WITH_TOKEN) later runs.
Solutions
- Ensure all HTTP headers are propagated through the proxy: set proxy_set_header Host $host; X-Forwarded-Host, X-Forwarded-Proto and appropriate Referrer-Policy, and make dolibarr_main_url_root match the externally visible URL.
- Access Dolibarr using the exact same host name that appears in dolibarr_main_url_root / HTTP_HOST.
- For special trusted setups only, add $dolibarr_nocsrfcheck=1 to conf.php to skip this check (reduces security — the token check remains only if MAIN_SECURITY_CSRF_WITH_TOKEN is enabled).
- Update Dolibarr: newer versions handle proxies better and allow configuring accepted referrers.
- If a third-party site posts to your Dolibarr, embed the form in Dolibarr or use the REST API with tokens instead of cross-origin form posts.
Example fix
// before (nginx)
location / { proxy_pass http://backend; }
// after
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Referer $http_referer;
} Defensive patterns
Strategy: fallback
Validate before calling
// before submitting a form programmatically, ensure Referer matches the target host
if (!str_starts_with($referer, 'https://doli.example.com/')) {
$referer = 'https://doli.example.com/htdocs/'; // set explicitly in the HTTP client
} Type guard
function refererMatchesHost(?string $referer, string $host): bool {
if ($referer === null || $referer === '') return true; // empty referer is allowed
return parse_url($referer, PHP_URL_HOST) === $host;
} Try / catch
// CSRF refusal ends with die => client sees truncated 200 body, detect by content
$resp = $client->post($url, ['headers' => ['Referer' => $baseUrl.'/'], 'form_params' => $data]);
if (str_contains($resp->getBody(), 'refused by CSRF protection')) {
// fix Referer/Host headers or configure the proxy, then retry
} Prevention
- Always send an explicit Referer header matching the Dolibarr host when scripting form posts.
- Configure reverse proxies to forward Host, X-Forwarded-Host and X-Forwarded-Proto.
- Keep dolibarr_main_url_root identical to the public hostname users browse.
- Avoid cross-origin form posts; use the REST API with tokens.
- Only use $dolibarr_nocsrfcheck=1 for trusted internal setups, and document it.
When it happens
Trigger: POST request whose HTTP_REFERER points to a different host/port/scheme than the served URL — e.g. form submitted from another domain, or behind a proxy/CDN that rewrites Host or strips/alters Referer headers.
Common situations: Running Dolibarr behind a reverse proxy with URL rewriting where X-Forwarded-Host/Referer are not propagated; accessing the server by two different names (localhost vs domain) and the browser sends the other one; embedded forms/iframe integrations from another origin; browser extensions stripping referers.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- If you access your server behind a proxy using url…
- If you access your server behind a proxy using url…
- Access to a page that needs a token (constant…
- Access to this page this way (POST method or GET with a…
- Access refused by IP protection. Your detected IP is
AI-assisted analysis of Dolibarr/dolibarr@598aa4bdad (2026-09-14).
Data as JSON: /api/errors/3d9871afebb923f9.
Report an issue: GitHub.
Appendix: source
Thrown at htdocs/filefunc.inc.php:352
// Note about $_SERVER[HTTP_HOST/SERVER_NAME]: http://shiflett.org/blog/2006/mar/server-name-versus-http-host
// See also CSRF protections done into main.inc.php
if (!defined('NOCSRFCHECK') && isset($dolibarr_nocsrfcheck) && $dolibarr_nocsrfcheck == 1) { // If $dolibarr_nocsrfcheck is 0, there is a strict CSRF test with token in main
if (!empty($_SERVER['REQUEST_METHOD']) && !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')) && !empty($_SERVER['HTTP_HOST'])) {
$csrfattack = false;
if (empty($_SERVER['HTTP_REFERER'])) {
$csrfattack = true; // An evil browser was used
} else {
$tmpa = parse_url($_SERVER['HTTP_HOST']);
$tmpb = parse_url($_SERVER['HTTP_REFERER']);
if ((empty($tmpa['host']) ? $tmpa['path'] : $tmpa['host']) != (empty($tmpb['host']) ? $tmpb['path'] : $tmpb['host'])) {
$csrfattack = true;
}
}
if ($csrfattack) {
//print 'NOCSRFCHECK='.defined('NOCSRFCHECK').' REQUEST_METHOD='.$_SERVER['REQUEST_METHOD'].' HTTP_HOST='.$_SERVER['HTTP_HOST'].' HTTP_REFERER='.$_SERVER['HTTP_REFERER'];
// Note: We can't use dol_escape_htmltag here to escape output because lib functions.lib.ph is not yet loaded.
dol_syslog("--- Access to ".(empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"].' ').$_SERVER["PHP_SELF"]." refused by CSRF protection (Bad referrer).", LOG_WARNING);
print "Access refused by CSRF protection in main.inc.php. Referrer of form (".htmlentities(empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'], ENT_COMPAT, 'UTF-8').") is outside the server that serve this page (with method = ".htmlentities($_SERVER['REQUEST_METHOD'], ENT_COMPAT, 'UTF-8').").\n";
print "If you access your server behind a proxy using url rewriting, you might check that all HTTP headers are propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file to remove this security check).\n";
die;
}
}
// Another test is done later on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on.
}
if (empty($dolibarr_main_db_host) && !defined('NOREQUIREDB')) {
print '<div class="center">Dolibarr setup is not yet complete.<br><br>'."\n";
print '<a href="install/index.php">Click here to finish Dolibarr install process</a> ...</div>'."\n";
die;
}
if (empty($dolibarr_main_url_root) && !defined('NOREQUIREVIRTUALURL')) {
print 'Value for parameter \'dolibarr_main_url_root\' is not defined in your \'htdocs\conf\conf.php\' file.<br>'."\n";
print 'You must add this parameter with your full Dolibarr root Url (Example: http://myvirtualdomain/ or http://mydomain/mydolibarrurl/)'."\n";
die;
}
if (empty($dolibarr_main_url_root_alt)) {View on GitHub (pinned to 598aa4bdad)