Problem/Motivation

I have set `add_header X-Frame-Options SAMEORIGIN always;` in my nginx server config file and verify it is there via running `curl -I https://websitename.com`

HTTP/2 200 
date: Thu, 20 Nov 2025 15:05:44 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
vary: Cookie
cache-control: max-age=86400, public
x-drupal-dynamic-cache: HIT
content-language: en
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
...

Running the Review results in the following warning:

There are some headers a site should set. One such header is X-Frame-Options with a value that will protect the site against clickjacking.

The following headers were missing.

  • X-Frame-Options

The review should not warn about this since it is set properly.

Steps to reproduce

  • add `add_header X-Frame-Options SAMEORIGIN always;` to your nginx site conf file
  • curl website to verify it is set
  • run review

Proposed resolution

The header check doesn't convert to lower case in array_key_exists

$headers = array_merge(['X-Frame-Options'], $additional_headers);
    $host = $this->requestStack->getCurrentRequest()->getSchemeAndHttpHost();
    try {
      $requestHeaders = $this->httpClient->request('GET', $host)->getHeaders();

      foreach ($headers as $header) {
        if (!array_key_exists($header, $requestHeaders)) {
          $findings[] = $header;
        }
      }

    }

Remaining tasks

Update code and convert all header checks to lowercase

User interface changes

None

API changes

None

Data model changes

None

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

sagesolutions created an issue. See original summary.

smustgrave made their first commit to this issue’s fork.

smustgrave’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

sagesolutions’s picture

Thanks for the fix!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

drale01’s picture

Version: 3.1.1 » 3.1.2

We’re seeing the same problem on the latest Security Review version 3.1.2.
X-Frame-Options is present in the response headers (verified in browser and via curl -I), but the check still reports it as missing.
Environment: Drupal 11, Plesk, nginx in front of Apache.
Header is set in nginx (add_header x-frame-options "SAMEORIGIN" always;) and also tested in .htaccess.
It looks like the check is case‑sensitive or not normalizing header keys from Guzzle response.

peraltamori’s picture

Version: 3.1.2 » 3.1.3

We are observing the same problem in the latest version of Security Review, 3.1.3, with Drupal 11.

sagesolutions’s picture

I am also getting a false positive on Drupal 11 with Security review 3.1.3.

I think we should re-open this ticket.

See results of curl below

HTTP/2 200 
server: nginx
content-type: text/html; charset=UTF-8
content-length: 17693
vary: Accept-Encoding
cache-control: max-age=86400, public
date: Wed, 15 Apr 2026 16:45:27 GMT
x-drupal-dynamic-cache: HIT
content-language: en
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
expires: Sun, 19 Nov 1978 05:00:00 GMT
last-modified: Wed, 15 Apr 2026 16:54:35 GMT
etag: "1776272075"
vary: Cookie
x-generator: Drupal 11 (https://www.drupal.org)
x-xss-protection: 1; mode=block