Security and input bounds¶
vibe-sketch runs as a local server that the browser shell, the desktop window and agents talk to, and it reads files that come from elsewhere: a co-author’s ChemDraw file, a QVF from another program, a SMILES list from a database. This page records what it trusts, what it bounds and what is still open. It is the first part of the 0.8 reliability and security qualification (issue #69). That qualification as a whole is not complete, and no support claim rests on this page.
What is trusted¶
Party |
Trusted with |
Why |
|---|---|---|
The user at this machine |
Everything the server can do, including writing files they name |
It is their sketcher. |
Agents the user starts ( |
The same, through the REST API |
They act for the user. |
Web pages in the user’s browser |
Nothing |
Any site can make the browser send requests to 127.0.0.1. |
Files and pasted data |
Their contents only |
They are read, never run. |
Other machines on the network |
Nothing, unless the user binds to a network interface |
The default bind is 127.0.0.1. |
The local server¶
vibe-sketch serve and the desktop window bind to 127.0.0.1 by default.
Such a loopback server:
answers only requests whose
Hostis a name of this machine (127.0.0.1,localhost,::1), and refuses others with 421. A site that points its own name at 127.0.0.1 (DNS rebinding) shares the server’s origin in the browser, but it still sends its own name.refuses a request whose
Originis another site’s, ornull, with 403. The browser shell, the desktop window and a development server onlocalhostare on this machine and pass.
A server bound to another interface (--host 0.0.0.0) was asked for by
name. It takes any Host, prints that anyone who can reach it can use the
API, and leaves access control to the network. It has no login.
Every request body is read up to 272 MiB (the largest QVF in base64, with room to spare) before the application parses it; a longer one answers 413.
What a file may hold¶
Each check runs before the work it protects, and a refusal says which
bound was met (vibesketch.limits):
Input |
Bound |
Protects |
|---|---|---|
An imported file or text, a |
64 MiB |
parsing |
A QVF archive |
192 MiB packed; 10,000 files; 64 MiB for a JSON member and 1 GiB for any other member, unpacked; 2 GiB in all |
memory: a small archive that unpacks to gigabytes (a zip bomb) is refused from its directory, before anything is unpacked |
JSON (KET, |
64 levels of nesting |
the parser and the validator; JSON too deep for the parser itself is refused too |
One import |
25,000 atoms |
derivation of species and reactions |
A structure without 2D coordinates (SMILES, InChI, a name, XYZ) |
2,500 atoms |
2D layout, which grows faster than linearly: 5,000 atoms take about 17 s; a drawn structure of that size, with coordinates, imports |
CDXML |
expat’s limits on entity expansion |
memory: the “billion laughs” document is refused by the XML parser |
A campaign |
2,000 nodes (two per species and stage); 4,096 cpus and 16 TiB of memory per node |
disk: every node is a directory of files written before the queue sees it |
A canvas that is not one, such as KET whose nodes are not a list, is refused as an invalid canvas instead of failing inside the server.
Files are read, never executed: formats are parsed into data, and no imported file names a program to run. The routes that take a filesystem path (campaign and render directories) and Save, which writes to the file the server opened, act for whoever passes the checks above: the user and their agents.
Saving¶
Every save writes a hidden temporary file beside the target, makes it
reach the disk, renames it over the target and then syncs the directory.
A crash, a full disk or an interrupted save therefore leaves either the
old file or the new one, never a mixture. A crash at the wrong moment can
leave a hidden .NAME.*.tmp file beside the document; it is safe to
delete.
A document the server opened from a file (vibe-sketch serve FILE, the
browser’s Save) remembers the file’s bytes as it read or last wrote
them. If another program changed, replaced, deleted or created the file
since, Save is refused with 409 and the file is left as the other program
wrote it. The edit stays in the open document: reopen the file to see the
other change, or keep this version with a download under another name.
The desktop window checks the same before its Save. A stale revision (two
clients editing at once) answers 409 with the current revision, and the
client re-reads; missing optional programs answer with an installation
hint instead of failing.
Directories¶
Compiling a campaign and rendering its stages write into a directory the client names. It must be absolute, and new or empty; a directory with anything in it is never touched. If the write fails (no permission, a full disk), the refusal says why. A directory that was made for the write is removed, and one the client gave is left empty, as it was. The paths a campaign’s own files and records hold may come from a document someone else wrote, so a render refuses any that lead outside the campaign, and a campaign whose files are missing or unreadable is refused with the reason.
A drawing sent over REST (PUT /api/documents/{id}/canvas) and a posted
document meet the same bounds as an import: nesting, atoms, and a canvas
that is one.
Updating¶
scripts/update.sh only fast-forwards the checkout, so an interrupted
fetch leaves it as it was. With --recreate-venv, the previous virtualenv
is set aside as VENV.previous until the new one is installed and answers;
if the update fails or is interrupted (Ctrl-C included), the new one is
removed and the previous one restored. A VENV.previous left behind by a
killed update stops the next update with the way out: move it back or
delete it. An update without --recreate-venv reinstalls into the existing
virtualenv, where pip replaces one package at a time; run the update again
if it was interrupted.
Desktop startup¶
The desktop window starts its own backend and waits for it. Only the
backend’s own answer counts as ready (200 {"status": "ok"} from
/health), so another program on the port, or an error page, never opens
the editor. A backend that dies while starting ends the wait at once and the
setup window says it did not start, with its exit status in the log. A
backend that stops later closes the editor window and shows The
vibe-sketch server stopped, with Try again to start a new one;
changes since the last save were held by the stopped backend.
Still open¶
These parts of #69 are not done yet:
Clean installation and packaged flows on each supported platform.