# What an app page is allowed to load

> Every app page is served with a Content-Security-Policy the browser enforces. Scripts, styles, fonts, workers and data connections must come from the app's own origin; images may additionally come from any `https:` address. A control that tries to reach a third-party origin is refused by the browser, silently — so a vendored library must ship the parts it needs rather than fetch them at run time.

<!-- id: ui-content-security-policy · area: ui · stability: preview · html: https://osysharp.com/reference/ui/content-security-policy/ -->

## Summary        {#summary}
An app page is not an open document. It is served with a **Content-Security-Policy**, and the browser — not the
platform — enforces it. The shape is *same-origin by default*: the client, every control bundle, every chunk, every
font and every data connection comes from the app's own address.

Two deliberate widenings make ordinary content work. **Images may come from any `https:` address**, so a document that
embeds a remote picture renders. And **inline styles are allowed**, because that is how the renderer and every
editor-style control position things.

The rule with teeth for a control author is the one about *fetching*: **a control may not load code, data or a font
from a third-party origin.** Vendor what you need — see [chunks — assets a control loads on demand](https://osysharp.com/reference/ui/control-chunks/), which exists so a library can ship its
own parts, including a worker and a `.wasm` sibling, and still be served from your app. WebAssembly compiled from
something your app served is allowed; a module fetched from someone else's origin never gets that far.

## Description    {#description}

### What the policy allows   {#allowed}

| What | Allowed from | Why it is drawn there |
|---|---|---|
| **Scripts** | the app's own origin, plus one hashed inline bootstrap | the client, control bundles and chunks are all served by your app. There is no `unsafe-inline` and no `unsafe-eval` |
| **WebAssembly** | may be compiled, from a module the rules above let you fetch | a control may ship a `.wasm` chunk, and a browser refuses to compile one unless the policy says so. It permits compiling a module and nothing else — no string ever becomes JavaScript |
| **Styles** | the app's origin, and **inline** | the renderer paints style attributes, and controls position themselves with them continuously |
| **Images** | the app's origin, **any `https:` address**, and `data:` | a document that embeds a remote image is ordinary content, and stylesheets legitimately draw small icons as `data:` SVG |
| **Fonts** | the app's origin, and `data:` | your app's web fonts are served by your app; a chunk's stylesheet may inline a face |
| **Connections** (fetch, WebSocket) | the app's origin | the data channel and live updates are all your app's own address |
| **Workers** | the app's origin | a package chunk may start one; it is served from your app like the rest of the package |
| **Frames** | nothing, in either direction | no page embeds another, and no page may be embedded — which is also what stops clickjacking |

Plugins (`object`), and a `<base>` element that could re-point every relative URL on the page, are refused outright.

Two companion headers ride along: responses are marked `nosniff`, and the referrer sent to another site is trimmed to
your origin — so following a link out of a document does not hand the other site the record id in your page's address.

### The failure is SILENT — this is the part worth remembering   {#silent-failure}

A refused subresource does not raise an error your code can catch. The browser simply does not fetch it, writes a line
to the console, and carries on. A feature that lazily loads something therefore does not *break* — it quietly does
nothing, which looks like a bug anywhere except where it is.

So when a control works in isolation and does nothing in an app, **open the browser console first**. A CSP refusal
names the directive and the address it blocked:

```text
Refused to load the script 'https://cdn.example.com/lib.js' because it violates
the following Content Security Policy directive: "script-src 'self' 'sha256-…'".
```

### What this means when you ship a control   {#controls}

**Vendor, do not fetch.** A library that hard-codes a CDN address for its own code will be refused. The answer is to
ship it as part of your control, which is what a chunk **package** is for: a directory served under a real base, so the
library's own relative imports, `new Worker(new URL(…))` and `.wasm` siblings all resolve exactly as they would on a
static host. See [chunks — assets a control loads on demand](https://osysharp.com/reference/ui/control-chunks/).

**WebAssembly vendors cleanly too, and this is where people expect trouble.** A `.wasm` is an ordinary chunk: it is
served from your app with the right type, and the policy admits compiling it. The one thing to watch is that
Emscripten-built libraries do not embed their module — they *ask* for its address at run time, and the default answer
is usually a CDN, which will be refused. Point that lookup at your own chunk instead. `Osysharp.Barcode`
([The barcode kit — a QR and barcode scanner you opt into](https://osysharp.com/reference/ui/barcode-kit/)) is the worked example: a 1.07 MB ZXing decoder reached through `host.chunkUrl("Wasm")`.

That covers more than it sounds like it should — a diagram engine that lazy-loads a renderer per diagram type, or a
speech model's WASM runtime, both vendor cleanly. What it does not cover is a library that must reach *its own*
origin at run time, such as one fetching multi-hundred-megabyte model weights from a CDN. There is no way to declare
that today; the page's policy refuses it, and that is the current answer rather than an oversight.

**Remote images are fine.** `![](https://…)` in a document, or an image whose address is data, renders normally. Only
`http:` addresses are refused, and those would be blocked as mixed content on a secure page anyway.

**Inline styles are fine.** Setting a `style` attribute from a control works, as does anything the renderer paints.

## See also       {#see-also}
- [chunks — assets a control loads on demand](https://osysharp.com/reference/ui/control-chunks/) — how to ship a library's own parts so it is served from your app rather than fetched
- [control — foreign UI controls (charts, grids, maps)](https://osysharp.com/reference/ui/controls/) — declaring and mounting a control
- [The markdown editor kit — a rich editor you opt into](https://osysharp.com/reference/ui/markdown-editor-kit/) — a worked example of a vendored, chunked control
