# Policies and safety

> What links, images, HTML, and remote resources may do by default, and how to change it.

## Defaults

SiriusMarkdown checks links and resources before using them, sanitizes HTML, and never executes document content. These defaults apply to both document and chat presets.

- **Links** to `http`, `https`, `mailto`, and relative destinations are allowed. Any other link is shown as plain text that can't be activated.
- **Images** on public HTTPS origins load anonymously through a bounded loader. Private-network destinations, credentials, unsafe redirects, oversized downloads, and invalid image data are refused. A host can opt out with `LocalOnlyMarkdownImagePolicy`. Relative files need a host resolver that knows the document location.
- **HTML** is limited to a documented subset: `a`, `strong`/`b`, `em`/`i`, `s`/`del`, `code`, `br`, `sub`, `sup`, `span`, `p`, `div`, headings, block quotes, lists, `pre`, horizontal rules, tables with merged cells, and images that pass image policy. It renders the same way Markdown does. Scripts, event handlers, iframes and other embedded pages, plugins, forms, and arbitrary CSS are removed. They're never run, and their tags are never shown as text.
- **Code** is always shown as text, never run. You can replace the highlighter.
- **Math** is typeset natively. Input that can't be typeset is shown as source text.
- **Link icons** are fetched anonymously from public HTTPS sites. See [Link icons](https://siriusmarkdown.com/docs/policies/#link-icons) below.

## Policy protocols

Link, image, HTML, code, and math policies each return a `MarkdownPolicyDecision`: `.allow` or `.deny(reason:)`. `DefaultMarkdownPolicy` implements all five. A custom policy can narrow the default rules, as this example does for links:

```swift
import Foundation
import SiriusMarkdown

struct InternalLinksOnly: MarkdownLinkPolicy, MarkdownLinkPolicyCacheIdentifying {
    var linkPolicyCacheIdentity: String { "internal-links.v1" }

    func evaluateLink(destination: String) -> MarkdownPolicyDecision {
        let policy = DefaultMarkdownPolicy()
        guard let normalized = policy.normalizedLinkDestination(for: destination),
              let url = URL(string: normalized),
              (url.scheme == nil && url.host == nil)
                || (url.scheme == "https" && url.host == "docs.example.com") else {
            return .deny(reason: "External links are disabled in this reader.")
        }
        return .allow
    }
}

var configuration = MarkdownRendererConfiguration.document
configuration.linkPolicy = InternalLinksOnly()
```

Markdown links and HTML `<a href>` links go through the same policy check, so HTML can't be used to get around a decision about a Markdown link. Images and remote resources work the same way.

## Link icons

Allowed links show a fallback symbol immediately. When an eligible site's icon is available, it replaces that symbol. Icons are fetched anonymously, without cookies or referrers, and only from public HTTPS sites. Requests to local or private network addresses are refused, and downloads are size-limited. An arriving icon updates only the affected content. Set `linkMetadataResolver = nil` to stop icon discovery, or `linkDecoration = .disabled` to hide link decorations.

## Remote images

Public HTTPS pictures load by default. Loading is anonymous, with limits on download size, image format, frames, dimensions, concurrent requests, and request duration. Hosts can defer requests until an image is visible.

To disable network pictures:

```swift
var configuration = MarkdownRendererConfiguration.document
configuration.imagePolicy = LocalOnlyMarkdownImagePolicy()
```

Document-relative paths require a host resolver. HTML images go through the same policy as Markdown images.

[Public policy APIs](https://siriusmarkdown.com/api/documentation/siriusmarkdowncore/)
