Skip to content

Security model and limits

This page sets out who nod trusts with what, which rules the server enforces, and what those rules don't cover. It's written for security reviewers. For data flows and threats, see the Security review guide.

Part What it can do What it's trusted with
You Ask for work, approve actions, choose accounts, change permissions Everything
nod server Hold keys, check policy, decrypt values, record every use Keys and secret values
Browser provider Check field origins and pages, enter values, submit Secret values during entry
Model Plan, choose accounts, fields and buttons Account names, statuses and website results
Checker Decide each app action and browser step from your messages or a schedule's or standing instruction Your recent messages, a schedule's instruction or your standing instruction, and the action. For a browser step: the website, page address, control label, the form a click or Enter sends, dialog text or file, what nod typed or set; never the page's text
Website Receive what's submitted to its origin The values entered on it
flowchart LR
  you([You]):::accent --> server[nod server<br/>keys and policy]:::accent
  server <--> model[Model provider]
  server --> sandbox[Workspace<br/>no keys]:::muted
  server --> browser[Browser<br/>private entry]
  server --> db[(Database<br/>encrypted Vault)]
  browser --> sites[Websites]
  server --> apps[Connected apps]

Only the server holds keys and decides what runs. The model, the workspace and anything the browser loads are on the other side of that line.

  • Only your messages, a schedule's instruction, your standing instruction and your approvals carry authority. Pages, emails, files and tool results can't create permission.
  • App actions beyond reads and drafts need a review match against your request or your yes. See Approvals.
  • A confirmation is bound to the exact action and arguments, and runs once.
  • Background work nod starts itself reads and drafts, and does only what your standing instruction asks. Anything else waits for your yes, and a payment always needs your approval.
  • No tool returns a saved password, code or card to the model.
  • nod is told never to ask for a password, code, card or API key in chat; it opens private entry instead. While a verification code is pending in the conversation that asked for it, a message that ends with its only 4–8 digit number (digits 0–9) is taken as the code, whatever the wording around it, and a message with a code-length number anywhere else is refused. While a card's security code is pending, only a code sent by itself or labeled CVV, CVC or security code, as in "my CVC is 123", is taken, and any other message with a 3- or 4-digit number is refused. A code sent as a reply to a closed request, or by itself until 10 minutes after nod starts on a newer message, is refused too. None of these reach the model. Digits in other scripts and any other secret you type into chat reach the model.
  • Known secret values are removed from tool output and masked in screenshots.
  • Provider keys never enter the workspace, the browser or a prompt.
  • A login is entered only into a field whose real frame origin matches the login's exact origin. Card fields must match the approved destinations.
  • Entry and submission happen in one step that the model can't observe or act during. Scripts on the destination page can read the entered values, as with any form.
  • A page changed by the model's own JavaScript must reload before entry. After a failed entry, the model's view stays locked until the filled page changes.
  • After nod fills a private value on a page, the model's page scripts stay paused on that page until it reloads or moves on, so a script can't read the value back even once the field is gone.
  • The browser and the web tools reach only public addresses, never the host, the local network or other containers. The address is checked when each connection opens, so a name can't switch to a private address after the check. nod drops any proxy for a web tool, whether the model names it or the web extension's settings set it.
  • Every private entry and payment is claimed once before browser work starts. It never runs twice, and an interrupted one becomes uncertain. See One use, one result.
  • The workspace runs as an unprivileged user with no host home folder, Docker socket, provider keys, access key or browser profiles.
  • A connected command-line tool's token reaches only a sealed install of its declared source, run as its own user with a clean environment, apart from other tools.
  • Every query and route is scoped to one owner.
  • File previews never run a file in nod's own page. An HTML file runs in a sandbox with an empty origin and no network, forms or pop-ups, and its preview closes if it tries to open a website. Other formats are read as data. Files that can run code get no local preview before they upload.
  • Loopback isn't treated as identity. Every local /api request needs the owner key from NOD_DATA_ROOT/access-key, or the desktop app's per-launch token. Only verified webhooks, OAuth callbacks, the key exchange and the privacy notice go without it.

Report it privately through GitHub private vulnerability reporting, or through n8n's Vulnerability Disclosure Program. Don't open a public issue, and never include real passwords, keys or other people's data.

The team aims to acknowledge your report within 3 business days and to share a first assessment within 10 business days. Confirmed issues get a GitHub security advisory. Read the full security policy for scope and research rules.

Area Source
Authority and confirmations trust.ts, approvals.ts
Vault and one use vault-access.ts, vault-use.ts
Browser entry and proxy agent-browser
Local access access.ts
File previews attachment-frame.tsx, attachment-kind.ts