Summary for reviewers
- NymForm is an Excel task pane add-in with no NymForm server. It has no telemetry, analytics or error reporting.
- The only network destination for your data is the model endpoint fixed when the add-in is built (OpenRouter). The page's Content Security Policy allows connections to that endpoint only.
- Structure only is the default mode and sends no data cells. Include sample rows replaces every value in the columns you mark private.
- Every request is checked before sending; any match, error or exception blocks it. The check has stated limits (see Alpha limitations). Only a request that passed the check can be sent, and it is sent byte for byte as checked.
- The API key and the stand-in map live in memory only: the key until you close the pane, the map until you refresh the selection or change its ranges.
- Every formula from the model passes an allowlist-based formula gate before and after your values are restored. Nothing is written to the workbook until you choose Insert formula.
NymForm is a technical control. It is not a certification, and using it does not by itself meet the requirements of any regulation.
Data flow
- WorkbookExcel reads the range you choose.
- Task paneNymForm builds the request and replaces private values.
- Request checkStructural check and full-text scan. Any hit, error or exception blocks.
- OpenRouterReceives the checked request with your key, over HTTPS.
- Model providerOpenRouter routes it only to endpoints on its zero-data-retention list.
- Formula gateThe reply is parsed, checked, restored and checked again.
- InsertYou choose Insert formula. Excel calculates it on your real data.
What runs in the task pane
The add-in runs inside Excel as a web page, the task pane. There, NymForm:
- reads the range you choose and infers headers, types and counts,
- suggests private columns (suggestions only; your checkbox decides),
- replaces private values with stand-ins, ranges or months, and keeps the stand-in map in memory,
- builds the request and checks it,
- parses the model's reply, runs the formula gate and restores your values into the formula,
- writes the formula to the workbook when, and only when, you choose Insert formula.
Browser spell check, autocorrect and writing assistants are turned off in the question, answer and note fields, because some of them send text to a cloud service.
Excel calculates the inserted formula on your real data. The model never receives the restored values.
What leaves Excel
One thing: the checked request, sent to the configured model endpoint when you choose Send (and, if the reply can't be read, one automatic correction request; see below). It contains the model ID, the fixed instructions for the model, your question (private values replaced), headers or their aliases, the name of the sheet and table you selected (and the sheet and table name of any lookup range), range addresses, row numbers and row counts, column types, which columns you marked private and how each is treated in sample rows, simple counts (blanks, distinct values, and for text columns average words and longest length), your column notes, up to six earlier messages of the conversation in stand-in form, request settings (token limit, reasoning, response format and provider: { zdr: true }), and, in sample rows mode, the rows with private values replaced. Your workbook's other sheet names, its other tables and its defined names are read only for the formula gate and are not sent.
The request also carries your key as its authorization and an X-Title: Nymform for Excel header. These headers are not part of the text shown by Show exact request.
The task pane also loads Microsoft's Office JavaScript library from Microsoft's add-in host, as Office add-ins do, and that library can load other Microsoft scripts. NymForm sends no data to Microsoft's add-in host; it uses the library, as Office add-ins do, to read from the workbook and to write the formula when you choose Insert formula. In testing outside Excel, the library loaded under the pane's security policy, and the policy refused its attempt to open Microsoft's telemetry service; this hasn't been checked inside Excel yet.
Allowed network endpoints
The endpoint is a build setting, shown read-only in Setup. The default is https://openrouter.ai/api/v1. The task pane's Content Security Policy limits connections to that endpoint's origin, and scripts to the add-in itself and Microsoft's Office library host. There are no remote fonts, analytics or other third-party scripts. Because the endpoint can't be changed from the pane, a user can't be talked into pointing it at another server.
Provider connection and API key
- Provider: OpenRouter is the only supported provider in the alpha. You bring your own key (BYOK).
- Key handling: the key is kept in memory only, until you close the pane. It is sent only to the endpoint, as the request's authorization, and is never logged or stored.
- Zero data retention: every request to OpenRouter asks for zero-data-retention routing (
provider: { zdr: true }), so OpenRouter routes it only to endpoints on its zero-data-retention list, and refuses the request if none can serve the model. This routing flag is added by the request builder when the endpoint is OpenRouter; it is not something the request check enforces. Zero retention limits storage, not processing: the request still reaches the provider. - Model: the default is
openai/gpt-6-luna. The Model field in Setup accepts another OpenRouter model ID; the check blocks a request whose model differs from the one in Setup. - Requests: each Send makes one request, with a 60-second timeout; a network error, timeout or provider error is not retried. If the reply can't be read, NymForm automatically sends one correction request (the same request plus the model's reply and a fixed correction message). It goes through the same check and is recorded on the Log screen, but it is not shown on What gets sent before it is sent.
Use a key with a spending limit, and a separate capped key for each person.
The request check
The check runs on the exact text of the request, after it is built and before it can be sent:
- Structural check: every cell in a private column of the sample rows must be a stand-in, a range or month rendering, or absent. Anything else blocks, whatever its length.
- Text scan: the whole request is scanned for every private value of 4 or more characters from the whole selection (not just the rows being sent), in many forms: case and accent folding, digits-only forms of values with 7 or more digits, JSON-escaped, words of multi-word values, dates in many written forms, amounts with separators, and more.
- Fail closed: any hit, error or exception blocks the send. In the code, the function that sends only accepts a request that the check produced, and it sends that exact text.
A blocked request's status names the column and roughly where the match is (for example, "Found in your question.") without repeating the value. The request itself stays visible in the pane so you can find the problem; it is never sent. The detailed stated limits of this check are in the add-in's security notes and summarized in Alpha limitations.
Stand-in map lifecycle
The stand-in map pairs each private value with its stand-in (PERSON_014). It is created when the pane reads your selection, kept in memory only, and never sent, persisted, logged or exported. Conversation history kept for follow-ups holds stand-ins, never restored values. Restored text is shown only in the pane and never re-sent. The restored formula, which contains your real values, leaves the pane only when you choose Insert formula (into the workbook) or Copy (to the clipboard).
Refreshing the selection, changing the header-row setting, or adding or removing a lookup range starts a fresh map and clears the conversation; closing the pane discards it.
Formula gate
The model's formula is untrusted. Before and after your values are restored, it must pass these rules:
- It uses only functions on an allowlist of ordinary worksheet functions (math, logic, lookup, text, dates, statistics, dynamic arrays). Anything unknown is refused. Explicitly refused: WEBSERVICE, FILTERXML, ENCODEURL, IMAGE, HYPERLINK, RTD, every CUBE function, STOCKHISTORY, PY, COPILOT, TRANSLATE, DETECTLANGUAGE, INDIRECT, OFFSET, CELL, INFO, CALL, REGISTER.ID and GETPIVOTDATA.
- It references only the ranges you chose (whole columns of those ranges included), with no external workbooks, no defined names, and no web addresses (http, https, ftp, file) or network paths in text values.
- A formula that is filled down is checked for every row it reaches.
Insert refuses cells inside your selected ranges, fills down only from the first data row, and asks before replacing cells that hold values, because Excel can't undo an add-in's writes.
Telemetry, logging and retention
- Telemetry: none. There is no NymForm server. The add-in computes evaluation metadata (counts and pass or block codes, never content) and keeps it in the pane; it leaves only if you export it.
- Log: the Log screen keeps up to 200 entries in memory: the exact request sent, the check result, the raw reply and the gate result. It never holds the key or the stand-in map. A blocked request is logged without its body; so you can see why it was blocked, the Log screen alone shows the matched text, with up to 32 characters on each side, beside it, and that note is never exported. Export log saves the entries as a file only when you choose it; that file contains the request bodies, including the values of any unmarked columns that were sent in sample rows.
- Retention: nothing is kept after you close the pane. On the provider side, NymForm requests zero-data-retention routing; what the provider does while processing is outside NymForm's control.
Build and version
The task pane footer shows the version and build, so you can match the running add-in to its source. Each build also writes a build-info.json file with its version, commit, endpoint and model. Benchmark code that can send raw data exists only in separate bench builds and is checked to be absent from release builds.
Current alpha limitations
The check does not catch every way a value can be written, it can't protect columns you leave unmarked, and headers, names, notes and your question are always sent. Read Alpha limitations for the full list, and the supported workflows for what the alpha does today.
Reporting a problem
Report security problems through GitHub's private vulnerability reporting on the add-in's repository (Security → Report a vulnerability), not in a public issue. That channel opens when the repository is published; a dedicated security email address will be added once it is set up and tested. In any report, include the version and build from the pane's footer, and use synthetic data, never real personal data.