The short version#
- Nodal never stores your Codex, OpenAI or Claude credentials. It starts a sign-in in your own browser and reads only status.
- The app window is sandboxed: context isolation on, Node integration off, a narrow named bridge to the main process.
- The built-in browser is sandboxed, loads web pages only and keeps each tab’s session separate and ephemeral.
- Terminals are only ended when Nodal can prove it owns the process.
- Logs redact prompt text by default; diagnostics and telemetry are opt-in.
- Where Nodal cannot protect you, the documentation says so.
The credential boundary#
The rule is stated in a single requirement: Nodal shall not copy provider credentials into its own credential store. It is easy to state and harder to keep, because the real Codex protocol hands a live token to any client that asks. A status call returns an authentication method, a flag saying whether sign-in is required and, in the real response, a token field. A parameter that asks for no token did not prevent it: measured on a real Codex CLI, the response still carried a non-null token. So the boundary is enforced by discarding, not by absence and not by asking.
Three layers apply, in order:
- A credential-free method where one exists. The account surface (email, plan, sign-in state) reads a method whose response type declares no credential field at all, so it is safe by construction.
- A parameter asking for no token on the one method that still has to be called, because it is the only one reporting the authentication method. This is hygiene, not the boundary.
- A redactor on every inbound frame, which depends on neither of the above and discards exactly the credential-bearing field before any other code in the process receives the payload.
The tests make the boundary measurable. The redactor carries dozens of tests in both directions. A purpose-built fake provider returns a marker token from the status call and from a field nested two levels inside the account read, and four test rows assert that the marker reaches neither the status view, nor the canonical event stream, nor the renderer’s own received stream in the packaged end-to-end run. One correction is asserted too: usage figures such as tokenUsage, inputTokens and outputTokens survive the redactor. An early draft treated any key containing the word token as a secret and would have deleted the numbers the usage meters exist to show.
There is one more refusal. The protocol contains a request in which the server asks the client for authentication tokens. Nodal records that request and never answers it. It holds no token to answer with, and holding one in order to answer would be exactly what the rule forbids.
Sign-in without a form#
Nodal asks Codex for a login URL and opens your own browser. There is no login form in Nodal, so no password crosses its boundary in either direction. Persistence comes free from Codex’s own credential store: a request to let Nodal keep its own copy so you would not have to log in every time was raised, discussed and withdrawn when the evidence showed Codex already delivers that outcome. Claude API keys come from environment variables only, and there is no key field in Settings.
Privacy defaults#
Nodal sends the provider requests you choose and nothing else. It does not collect or send additional personal data for advertising, brokerage or analytics. Diagnostics and telemetry are opt-in. The log defaults:
- Prompt text is redacted in every log, including local debug logs: only a hash or length is recorded. An explicit verbose debug mode may show full text when actually needed, and is never the default.
- Secrets and raw audio are never logged by default.
- Operating-system toasts are minimal and redacted. They do not contain full prompt text, and detailed provider questions and choices appear only inside the notification center after you act.
- Nodal masks known secret inputs and can hide known structured sensitive fields. It does not promise perfect automatic detection of sensitive text.
The record includes a candid self-correction. The first live probe transcript captured a real email address in a raw frame dump, because masking ran in a summary line and not in the log above it. Masking now runs inside the redactor that every frame passes through and inside the log function every written line passes through, and the transcript was replaced. An email is not a credential, but it is personal data, and the rule against retaining extra user information applies to a committed transcript as much as to a store.
The sandboxed renderer and the narrow bridge#
The interface runs in a renderer with contextIsolation on and nodeIntegration off. It talks to the main process through a preload bridge of named, typed methods. There is deliberately no generic file, shell, evaluation or process method, so a compromised page cannot ask for an arbitrary action. Every handler checks that the request comes from the trusted main renderer. Main resolves and validates paths, so the renderer never decides what is safe to open.
The built-in browser#
The browser in the sidebar and in Tab Mode is a view owned by the main process. It is sandboxed, uses an ephemeral session for each resource, loads web pages only and denies navigation, popups and extra frames outside policy. Agent actions on it go through typed handlers that check policy first. Restoring a saved layout shows an address and an explicit Load button; it starts no browser until you choose to. Local HTML and PDF previews are scoped to the project and served separately.
Process ownership#
When Nodal starts a terminal it records the process ID, the operating-system-reported start time, the executable path and its own session ID. Before any force-kill it re-reads the current start time and refuses to proceed on a mismatch, because a changed start time means the process number was reused by something unrelated. Descendants are not authorized just because their parent is: each explicit target is revalidated immediately before action, and any missing, stale, reused or conflicting identity blocks the kill. The packaged test covers nested processes, unrelated processes, PID reuse, concurrent exit, active output and concurrent resize with zero wrong-process terminations. See Tab Mode.
Agents run commands: where the limits are#
Nodal is open about what its sandbox does not cover. A provider’s sandbox modes apply only to that provider’s tool execution. They do not constrain commands you type into a Tab Mode terminal, and they do not prove protection against a provider defect or a misconfiguration. Nodal sends a named sandbox and approval pair per session, shows the state, never silently escalates and never uses full access by default. An unknown or conflicting state blocks unattended delivery. Human-typed terminal commands are a separate capability. Before untrusted repositories, third-party providers, public plugins, auto-continue or hidden or tray execution are supported, a host boundary has to be revisited. A virtual machine or operating-system sandbox for agents is a recorded idea, deferred to plugin-shaped form.
One gate is stated as not fully met: the effective sandbox and approval state should be visible to the user, and in the early build it was sent but not shown, with the Settings control disabled and its reason spelled out. The Ollama tools are stricter than the others: they never leave the project folder, even in Bypass mode, while a command run by the model still uses your own rights and has no network rule.
Plugins#
Plugin isolation is real process separation, not a framework promise: sandboxed windows and utility processes, a versioned handshake and bounded restarts. Public plugins and third-party code stay out until a trust model exists. The plugins page covers the details, including the honest limit that declared capabilities are protocol checks rather than operating-system restrictions.
Storage safety#
Persisted data goes through one writer queue with atomic replacement, backups and quarantine. Corrupt or unsupported data fails closed and never loads as valid state. Nodal does not store full provider transcripts by default, and it never stores live process handles.
The installer#
Because the beta installer is not yet code-signed, Windows SmartScreen may warn about an unrecognized app and Smart App Control may block it. Testers are told to verify the published file hash before running it. Signing or a store listing is on the roadmap. See the beta page.
Reporting and questions#
This is a beta built in public, and security feedback is welcome in the community channel linked from the about page. If you find something that looks like a defect rather than a design limit, say so there, and expect the answer to be a recorded decision rather than a shrug.