Guide

Policies and safety

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

SDK on GitHub ↗

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 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.

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

Native captureOpen original ↗
Native document capture