---
"@type": Article
"@id": "https://helloloam.dev/principles/security-bolted-in"
"@source": "https://helloloam.dev/data/article/security-bolted-in.json"
"@stamp": "2026-10-22T21:53:55+00:00"
about:
  "@type": DefinedTerm
  "@id": "https://helloloam.dev/data/definedterm/security-bolted-in.json"
  name: Security bolted in
  identifier: security-bolted-in
  inDefinedTermSet:
    "@type": DefinedTermSet
    "@id": "https://helloloam.dev/data/definedtermset/basics.json"
    name: Basics
    identifier: basics
author: {"@id":"https://helloloam.dev/#organization"}
datePublished: "2026-10-03"
description: No login page, no sessions, no plugins. Writing goes through one door, with a key, and nothing gets in unchecked.
headline: Security bolted in
identifier: security-bolted-in
inLanguage: en
publisher: {"@id":"https://helloloam.dev/#organization"}
url: "https://helloloam.dev/principles/security-bolted-in"
---

# Security bolted in

## No front door

Most attacks on a content management system go through its front door: the login page, the session, [the admin panel](/principles/no-dashboards), a plugin that went out of date. A loam site has none of those. No login form, so nothing to guess passwords against or phish. No sessions, so nothing to hijack. No plugins, so no third-party code going stale. A visitor can only read the site — and so can a bot. The edit client at `/edit`, off by default, is the one place a person signs in — a client of the same door, under the same rights, with a session that lives in the tab and never in a cookie.

## One door, with a key

Writing [goes through the MCP](/principles/mcp-with-a-trust-model), where an agent presents a key. The site keeps a fingerprint of each key, never the key itself. A leaked key is replaced and the old fingerprint stops matching. A site without keys is closed until its owner hands out the first one. A key's rights are cells in a table — per kind of file read, write or remove, and separately publish or take back — and no role implies more than it says.

## Judged at the door

Every file an agent sends in is judged [before it becomes even a draft](/principles/draft-and-live-lifecycle):

- **Content** must be valid structured data, and its text may carry no script.
- **An image** must be an image by its bytes, not its name.
- **A vector graphic** may carry no script and nothing that could act on the page it is drawn into.
- **Executable files and raw web pages** cannot be uploaded at all — a file that can run under your site's name is a danger.

What does not fit does not enter, and so can never be handed out either.

## Checked before it goes live

Publishing checks the whole site as it would be: broken references, missing fields, a template that does not parse. The site's own code is started once in a sealed, throwaway copy before it may go live, so code that parses but breaks on start never reaches visitors. If the check fails or cannot run, nothing goes live — a mistake can only ever exist as a draft.

## A tight page, a quiet server

Every page carries a content-security policy with a fresh nonce per request, so an injected script does not run. The web server serves the public folder only — never keys, drafts, the inbox, history or templates as files. Repeated failed attempts at the MCP are slowed per address, forms check their origin and catch bots with a field people never see, and a content delivery network with a firewall in front is the recommended default.

## What it costs

Some of it stays with you. Hand out keys with the least rights that do the job, and take them back when someone leaves. Protect the account behind your agent like the key itself — whoever can use your agent can use its key. And keep the history mirror private: it holds the key fingerprints.
