# frame-src (/en/docs/web-security/policies/content-security-policy/directives/frame-src)



The `frame-src` Content Security Policy (CSP) directive controls which sources a
page is allowed to load into `<frame>` and `<iframe>` elements. If a frame points
at a URL the directive does not allow, the browser refuses to load it and sends a
violation report.

A minimal safe policy for this directive, when the page embeds nothing:

```http
Content-Security-Policy: frame-src 'none'
```

## Fallback chain [#fallback-chain]

`frame-src` does not stand alone. When it is absent, the browser falls back to
[`child-src`](/en/docs/web-security/policies/content-security-policy/directives/child-src),
and when that is absent too, to `default-src`:

```
frame-src -> child-src -> default-src
```

So a policy with only `default-src 'self'` already restricts frames to the same
origin. Set `frame-src` when you want frame sources to differ from the rest of
your policy.

## Values [#values]

`frame-src` takes a source list, the same grammar as the other fetch directives:
[host sources](/en/docs/web-security/policies/content-security-policy/values/csp-host-source),
[scheme sources](/en/docs/web-security/policies/content-security-policy/values/csp-scheme-source),
and the `'self'` or `'none'` [keywords](/en/docs/web-security/policies/content-security-policy/values/csp-keywords):

| Value                   | Status  | Description                                                     |
| ----------------------- | ------- | --------------------------------------------------------------- |
| `'none'`                | ✅ Good  | Blocks all frames and iframes.                                  |
| `'self'`                | ✅ Good  | Frames from the page's own origin only.                         |
| `https://embed.example` | ✅ Good  | Frames from a specific host you embed.                          |
| `https:`                | ❌ Risky | Lets any HTTPS page be framed, including phishing content.      |
| `data:`                 | ❌ Risky | An injected `data:` frame is fully attacker-controlled content. |
| `*`                     | ❌ Risky | Frames from anywhere. Never matches `data:` or `blob:`.         |

Nonces and hashes do not apply to `frame-src`; framed documents are matched by
their URL, not by an inline digest.

## Examples [#examples]

```http
Content-Security-Policy: frame-src 'self' https://www.youtube.com
```

This page embeds frames only from its own origin and from `www.youtube.com`. A
frame pointing anywhere else is blocked.

## Security notes [#security-notes]

Restricting frame sources limits where embedded content can come from, which
reduces the surface for malicious or unexpected third-party frames, click
redirection inside an iframe, and framed phishing content. It pairs with
`frame-ancestors` (who frames you) and [`connect-src`](/en/docs/web-security/policies/content-security-policy/directives/connect-src)
(where your page talks to) as part of a layered policy.

`frame-src` is not `frame-ancestors`. These two directives sound alike and point
in opposite directions. `frame-src` controls the pages **you embed** (what your
page may put in an iframe).
[`frame-ancestors`](/en/docs/web-security/policies/content-security-policy/directives/frame-ancestors)
controls **who may embed you** (which parent pages may frame your page), and is the
modern anti-clickjacking control that supersedes `X-Frame-Options`. They do not
substitute for each other, a page often sets both.

## Known bypasses and risks [#known-bypasses-and-risks]

`frame-src` governs the frame's document URL, not what runs inside an allowed
frame. Once a frame is allowed, its own CSP (or lack of one) governs its contents,
so allowing a broad host like `https:` lets any HTTPS page be framed. A
`javascript:` or `data:` frame URL is matched as a scheme source, so do not add
those schemes unless you mean to allow them.

## Recommendation [#recommendation]

```http
Content-Security-Policy: frame-src 'none'
```

Block framing entirely unless you embed third-party content. If you do embed, list
the exact hosts (for example `frame-src 'self' https://www.youtube.com`) rather
than a broad scheme, so an injected iframe cannot pull in arbitrary pages.

## Reporting [#reporting]

When a frame is blocked, the browser sends a [csp-violation report](/en/docs/web-security/reporting-api/reports/csp-violation)
with `frame-src` as the `effectiveDirective`, including the blocked URL. CentralCSP
collects and aggregates these reports, so you can see every host your pages embed
before you tighten the directive.

## Browser support [#browser-support]

Widely supported across current browsers as part of CSP Level 3. The
[`child-src`](/en/docs/web-security/policies/content-security-policy/directives/child-src)
fallback is also widely supported, so omitting `frame-src` still leaves frames
governed by `child-src` or `default-src`.

## See also [#see-also]

* [child-src](/en/docs/web-security/policies/content-security-policy/directives/child-src), the fallback for frame and worker sources
* [frame-ancestors](/en/docs/web-security/policies/content-security-policy/directives/frame-ancestors), which controls who may embed your page
* [Evaluate a policy](/tools/csp-evaluator) with the CSP evaluator

## Sources [#sources]

* [MDN, CSP frame-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-src)
* [W3C, Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)
