# Missing Content-Security-Policy and clickjacking headers

> `GLC-CSP-MISSING` and `GLC-FRAME-MISSING` are two findings. One is a missing Content-Security-Policy. The other is missing frame protection. A header block can have either, both, or neither. Nothing is for sale. This note was checked against the live API on 17 October 2026.

HTML twin: https://dontdeployonfriday.com/csp-and-clickjacking.html
Home: https://dontdeployonfriday.com/
Privacy: https://dontdeployonfriday.com/privacy.html

Checkout is not connected. Do not send a payment. The check is free.

## When each one fires

`GLC-CSP-MISSING` (high). `Content-Security-Policy` is missing or blank, so the browser will not block an injected script. `Content-Security-Policy-Report-Only` does not count. Any non-blank policy clears this finding, including a weak one. This check does not score the policy.

`GLC-FRAME-MISSING` (medium). The block has neither an `X-Frame-Options` whose first token is `DENY` or `SAMEORIGIN`, nor a `Content-Security-Policy` `frame-ancestors` list other than a lone `*`. Another site can frame the page. A report-only policy does not supply `frame-ancestors` for this check.

Checked on this API on 17 October 2026:

- The other three headers present, plus `Content-Security-Policy-Report-Only` and `X-Frame-Options: DENY`, returned only `GLC-CSP-MISSING`.
- `frame-ancestors *` with `X-Frame-Options: ALLOWALL` returned `GLC-FRAME-MISSING`.
- `default-src 'self'; frame-ancestors 'none'` returned no findings.
- `default-src 'self'` alone left `GLC-FRAME-MISSING`.
- `X-Frame-Options: DENY` alone left `GLC-CSP-MISSING`.

## The curl that returns both

Collect the headers on a deployment you already operate. This server does not open that URL, and it does not guess the platform from the `Server` header. POST the text here. The body is at most 64 KB. `platform` may be `caddy`, `nginx`, `vercel`, `netlify`, or `nextjs`. Any other name, or no platform, returns `fix: null`.

```
curl -sS https://dontdeployonfriday.com/v1/analyze \
  -H 'content-type: application/json' \
  --data '{"headers_raw":"HTTP/1.1 200 OK\nStrict-Transport-Security: max-age=31536000\nX-Content-Type-Options: nosniff\nReferrer-Policy: no-referrer\n","platform":"caddy"}'
```

That block has HSTS, nosniff, and a referrer policy, and it has no CSP and no frame control. On 17 October 2026 the JSON findings were `GLC-CSP-MISSING` and `GLC-FRAME-MISSING`, each with a Caddy snippet. The same call with the platform omitted returns the same two ids and `fix: null`.

Prefer `https://dontdeployonfriday.com`. The name on port 80 redirects to HTTPS. The bare IP still answers on port 80 without TLS. Do not POST secrets, cookies, or tokens on either URL. Leave Cookie, Authorization, and Set-Cookie out of the header block.

Thirty requests per minute per IP, then 429. The response sends `Cache-Control: no-store`. An empty findings list means those seven header checks were clear in the text you sent. It is not a certificate and it is not a pentest.

## Snippets for a missing policy

These are the `GLC-CSP-MISSING` snippets from the local registry, `last_verified` 2026-10-17. The source URL is a citation. This server does not fetch it. Each starter sets `frame-ancestors 'none'`, so pasting it also clears `GLC-FRAME-MISSING` once that header is what the deployment sends. Read the snippet before you paste it. It blocks inline scripts. Add the hosts the app actually loads. A starter can break an app that needs a looser policy.

### Caddy

Source: https://caddyserver.com/docs/caddyfile/directives/header

```
# Add the hosts this app actually loads. This starter blocks inline scripts.
header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'"
```

### nginx

Source: https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

nginx is not installed on this host, so this line was not passed to `nginx -t`.

```
# Add the hosts this app actually loads. This starter blocks inline scripts.
# Keep this with your other add_header lines. A nested block that sets add_header drops headers inherited from above.
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'" always;
```

### Vercel

Source: https://vercel.com/docs/project-configuration/vercel-json#headers

The JSON file carries a note outside the snippet: add the hosts this app actually loads. This starter blocks inline scripts.

```
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Content-Security-Policy",
          "value": "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'"
        }
      ]
    }
  ]
}
```

### Netlify

Source: https://docs.netlify.com/routing/headers/

```
# Add the hosts this app actually loads. This starter blocks inline scripts. Applies to files Netlify serves. A function or a proxy must set this header itself.
/*
  Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'
```

### Next.js

Source: https://nextjs.org/docs/app/api-reference/config/next-config-js/headers

```
// Add the hosts this app actually loads. This starter blocks inline scripts.
module.exports = {
  headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: "Content-Security-Policy",
            value: "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'",
          },
        ],
      },
    ];
  },
};
```

## Snippets when a policy is already there

Use these `GLC-FRAME-MISSING` snippets when the deployment already sends a `Content-Security-Policy` and that policy does not set `frame-ancestors` to something other than `*`. `X-Frame-Options: DENY` clears the frame finding and does not clear `GLC-CSP-MISSING`. Same registry date, 2026-10-17.

### Caddy

Source: https://caddyserver.com/docs/caddyfile/directives/header

```
header X-Frame-Options DENY
```

### nginx

Source: https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

Not passed to `nginx -t` on this host.

```
# Keep this with your other add_header lines. A nested block that sets add_header drops headers inherited from above.
add_header X-Frame-Options "DENY" always;
```

### Vercel

Source: https://vercel.com/docs/project-configuration/vercel-json#headers

```
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        }
      ]
    }
  ]
}
```

### Netlify

Source: https://docs.netlify.com/routing/headers/

```
# Applies to files Netlify serves. A function or a proxy must set this header itself.
/*
  X-Frame-Options: DENY
```

### Next.js

Source: https://nextjs.org/docs/app/api-reference/config/next-config-js/headers

```
module.exports = {
  headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: "X-Frame-Options",
            value: "DENY",
          },
        ],
      },
    ];
  },
};
```

## What this page is not

- Not a review of a config file. The snippets are text. The API attaches them only after you name the platform.
- Not a statement that `DENY` is the right frame policy for an app that must be embedded by a parent you chose. `SAMEORIGIN` also clears the finding. A `frame-ancestors` list other than a lone `*` does too.
- Not legal advice, and not support. There is no contact address yet.

The Server header is not a platform. This server does not fetch a URL you paste, and it does not fetch the source links above.
