Network access

Let an Athanor plugin reach the internet: the network permission, allowedDomains and reasoning, where requests can be made from, and the publishing rules.

The rule

A plugin has no network access unless its manifest asks for the network permission and lists the sites it will reach in network.allowedDomains. The person sees those sites on the permission sheet before installing, as "Access the internet: only these sites". It can reach nothing else.

When a plugin holds both network and document.read, the sheet adds a line: "It could send your document's contents to those sites."

Where requests come from

In API 1, network requests are made from the plugin's window (ui.html), with the browser's ordinary fetch. The logic in main.js has no fetch and no other way to reach the network.

So a plugin that looks something up does it in three steps: the logic asks its window, the window fetches, and the window posts the answer back.

A minimal example

manifest.json (the relevant part):

{
  "ui": "ui.html",
  "permissions": ["network", "document.edit"],
  "network": {
    "allowedDomains": ["pubchem.ncbi.nlm.nih.gov"],
    "reasoning": "Looks up a compound's SMILES by name on PubChem."
  },
  "contributes": {
    "commands": [{ "key": "lookup", "title": "Look up a compound on PubChem" }]
  }
}

main.js:

athanor.commands.on('lookup', () => {
  athanor.ui.show({ width: 320, height: 160, title: 'PubChem lookup' });
});
athanor.ui.onmessage = async (m) => {
  if (m.type === 'found') {
    await athanor.apply({ label: 'Insert ' + m.name, ops: [{ op: 'addStructure', smiles: m.smiles, name: m.name }] });
  }
};

ui.html:

<div class="stack" style="padding:12px">
  <label for="q">Compound name</label>
  <div class="row"><input id="q" value="caffeine"><button id="go" class="primary">Insert</button></div>
  <p id="out" class="hint"></p>
</div>
<script>
  document.getElementById('go').onclick = async () => {
    const name = document.getElementById('q').value.trim();
    const out = document.getElementById('out');
    try {
      const r = await fetch('https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/'
        + encodeURIComponent(name) + '/property/IsomericSMILES/JSON');
      const j = await r.json();
      const p = j.PropertyTable.Properties[0];
      const smiles = p.SMILES || p.IsomericSMILES;
      athanor.postMessage({ type: 'found', name, smiles });
      out.textContent = 'Inserted ' + name + '.';
    } catch {
      out.textContent = 'Nothing found for ' + name + '.';
    }
  };
</script>

Whatever comes back from the network still reaches the page only through athanor.apply, so it is checked and screened like any other change.

allowedDomains

Rule Detail
Form A host name such as api.example.org, optionally with a path after it (example.org/v1). Lowercase
How many Up to 20
Scheme Requests go over https:// only
Paths Accepted in the manifest, but the browser enforces the host only
*.example.org Any subdomain of example.org. Works in development; see publishing below
* Any site. Needs network.reasoning, or the manifest is refused. Works in development; see publishing below
reasoning One sentence, up to 300 characters, saying why the plugin needs the internet. Shown on the permission sheet

A manifest with network and no domains is refused. Domains listed without the network permission are ignored, with a warning.

Publishing rules

  • Publishing refuses wildcards. A published plugin that uses the internet must name each of its sites exactly: no * and no *. anywhere. A manifest with one is refused by the automatic screening.
  • Every address in the code must be a declared site. Screening looks for http:// and https:// addresses in main.js and ui.html, and sends a plugin with an address outside its declared sites (or their subdomains) to human review with that finding on the checklist.
  • Adding a site is a new permission. An update that adds a site waits for human review, and each person who installed the plugin must OK it before the new version runs for them.
  • Every permission needs a reason when you publish, and "Access the internet" is no exception. See Publishing.

What a plugin can never send

Requests from a plugin's window come from a sandboxed frame with no origin of its own and no referrer. They carry no Athanor cookies and no sign-in, and the frame has no way to read your Athanor session, email address or password. See Security model.

Is this helpful?

Last updated Nov 11, 2026