Skip to content

Sending CSRF name/value as request header does not work with Apache #194

@euantorano

Description

@euantorano

Slim-Csrf supports reading the token names and values from HTTP request headers, which is useful when using AJAX and such. This functionality is implemented here: https://github.com/slimphp/Slim-Csrf/blob/1.x/src/Guard.php#L449

Unfortunately, this does not seem to work when serving PHP via fcgid on the Apache web server, as the HTTP headers are stripped.

It's taken me a lot of debugging to get here, but once you set the Apache LogLevel to LogLevel trace1 and send a request with the headers set, you'll see errors such as the following in the Apache error log:

[Wed Oct 29 14:32:35.792102 2025] [core:trace1] [pid 16352:tid 1960] util_script.c(77): [client ::1:50027] Not exporting header with invalid name as envvar: name, referer: http://localhost/system/create
[Wed Oct 29 14:32:35.792102 2025] [core:trace1] [pid 16352:tid 1960] util_script.c(77): [client ::1:50027] Not exporting header with invalid name as envvar: value, referer: http://localhost/system/create

Using Apache's mod_forensic, we can see the request coming in with the header intact:

+14756:690224c8:0|POST /system/create HTTP/1.1|Host:localhost|Connection:keep-alive|Content-Length:363|sec-ch-ua-platform:"Windows"|sec-ch-ua:"Microsoft Edge";v="141", "Not?A_Brand";v="8", "Chromium";v="141"|sec-ch-ua-mobile:?0|csrf_name:csrf690202736056c|X-Requested-With:XMLHttpRequest|User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0|Accept:application/json|Content-Type:application/json|csrf_value:xMqmCCFGUWeSDFlpR554QtPrjbaBjhv1d7YlrN1Uya7x+MJrFXBkVKVoaQpx+k4k4om41+K9IsdBj0Gbuzb/mQ==|Origin:http%3a//localhost|Sec-Fetch-Site:same-origin|Sec-Fetch-Mode:cors|Sec-Fetch-Dest:empty|Referer:http%3a//localhost/system/create|Accept-Encoding:gzip, deflate, br, zstd|Accept-Language:en-GB,en;q=0.9,en-US;q=0.8|Cookie:PHPSESSID=cjlal9vpd00c4ga4ldcmnovmqg
-14756:690224c8:0

This message is logged by Apache here: https://github.com/apache/httpd/blob/trunk/server/util_script.c#L72

To me, it looks like Apache doesn't like that the header contains an underscore (csrf_name and csrf_value become name and value respectively).

It might be useful to be able to customise the logic for the Guard::getTokenNameKey and Guard::getTokenValueKey logic.

As it stands, I've changed the logic to use a hyphen (-) rather than an underscore (-) by subclassing the Guard and re-implementing the two methods, and that resolved the problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions