Security and privacy
A scan runs locally without uploading source code, editing your files, or executing your project. Fix mode can use the network and run your project’s checks.
What can leave your machine
Section titled “What can leave your machine”| Operation | What is shared | Destination | Your control |
|---|---|---|---|
| Scan | No source code; optional feed downloads | Your machine; feed host for updates | Automatic updates are off by default. |
| Feed update | Snapshot requests without source code or your dependency list | Feed host or your mirror | Run emendant feed update or enable automatic updates. |
| Verify a fix | Package requests; no source code in the preparation directory | Your package registry | --dry-run and --no-verify skip this step and provide structural evidence only. |
| Assisted fix | Matched block, about twenty lines of context, and imports | Your chosen model provider or gateway | Choose a provider explicitly. Without one, these findings stay unfixed. |
| Failed-patch contribution | Package, versions, error codes, SDK declaration names, and a random install identifier; no source code or paths | Emendant’s contribution service | Accept sending at a terminal. Inspect .emendant/contribution.json; disable with emendant feed contribute --disable. |
--offline prevents network requests. See the privacy notice for recipients, retention, and your choices.
During scan
Section titled “During scan”Emendant reads manifests, lockfiles, configuration, .gitignore files, and relevant source files. It uses a locally verified feed to report affected code.
It does not run package scripts, tests, or application code, modify Git history, or transmit credentials. The npm package has no postinstall script.
Source text stays in the local process and is not retained by Emendant after that process exits.
The feed
Section titled “The feed”The feed ships inside the installed package, which is why a scan needs no network access at all.
Updates are verified locally against the trust root bundled with the tool. Each report names its snapshot, source, and age. Use EMENDANT_FEED_ORIGIN for your own mirror or --feed-snapshot <id> to reproduce a run.
Feed download and verification details
A newer feed is fetched only when you ask for one, with emendant feed update, or after you turn automatic refresh on, which is off until you turn it on once. A refresh downloads one whole signed snapshot from feed.emendant.com over HTTPS and verifies it against a trust root inside the package before anything is used. Four request shapes exist and no others:
timestamp.jsonroots/<sequence>.jsonsnapshots/<id>/manifest.jsonsnapshots/<id>/feed/<path>There is no query string, header, body or cookie, and no repository fact appears in anything Emendant constructs. The whole snapshot is downloaded rather than the entries for your dependencies, precisely so that a request cannot name a package you depend on.
An origin decides what bytes arrive and never whether they are accepted: the signature check is local, the trust root is bundled, and the installed tool has no signing key and no signing primitive in it at all. EMENDANT_FEED_ORIGIN is therefore safe to point at your own mirror. --offline makes no request in any mode, and --feed-snapshot <id> reproduces an exact run or exits 2 rather than substituting a different snapshot.
Every report names the snapshot, its source and its age, so a finding can always be traced to the feed that produced it. The privacy notice states what the origin can observe.
Fix mode
Section titled “Fix mode”Most fixes are written locally without a model. Each patch states which checks passed and whether a model wrote it. Review the patch evidence grades before applying a patch.
Assisted fixes send an excerpt directly to your chosen provider. Emendant does not receive or store that source. The destination host is shown before the first request. See the configuration reference for tenant-hosted providers and gateways.
Contributions are separate from assisted fixes. They reach Emendant only after you accept contribution sending at a terminal. The record is saved locally for inspection. See contribution privacy.
Fix data and verification details
Fix mode’s security boundary is different from the scan path’s:
- deterministic fixes require no model, and writing them makes no network request;
- proving a patch does make one, to your package manager’s registry and to nothing else. A
pendingpatch describes your code after an upgrade you have not made, so the scratch copy has to be moved to that release first. Emendant runs your own package manager in a tree holding only this repository’s manifests, lockfiles and package manager configuration, and no source. Your registry sees a package you were about to install anyway. Nothing about your repository goes anywhere else, and Emendant receives none of it.--dry-runand--no-verifyskip that step, and grade the patchstructurally checkedinstead; - a few changes have no mechanical remedy. For those, fix mode can ask a model provider the user names explicitly to write the patch. It sends the matched block, about twenty lines of context, and the file’s import block, from the user’s machine directly to that provider, and nothing else about the repository;
- without an explicit provider, those findings are reported unfixed and nothing is sent. Emendant never selects a provider, never reads a key it was not pointed at, and never falls back from included subscription access to a metered call;
- the provider may be one you operate.
--model-provider azureposts to an Azure AI Foundry resource in your own tenant, and--model-endpointpoints the direct providers at a gateway you run, so a network that permits a fixed list of hosts can still use assisted fixes. The host that will receive the excerpt is printed before the first request, and it names the host actually called rather than the flag it was spelled after; - Emendant does not receive or store that source;
- one request does reach us, and only where you answered yes to it at a terminal. When a patch fails its checks against the new release, Emendant sends back what that release broke: the package, the two versions, the error codes and the quoted names that appear in the new release’s own
.d.tsfiles. No path, no line, no code and nothing naming your repository can be in it, and the record is written to.emendant/contribution.jsonbefore it is sent so you can read it. It carries a random identifier this machine made for itself, so that you can ask for it to be deleted. A machine nobody asked sends nothing, and--offlinesends nothing in any mode. The privacy notice states it in full; - every candidate patch is bounded to the file its finding is in, and is proved in a copy of your repository outside the working tree before it is written. That copy runs your own typecheck and test commands, found rather than configured, behind the strongest boundary the machine has. A temporary home and reduced environment apply everywhere. No network and confined writes apply where the platform supports them. Reads are not confined, and credential files are hidden by name. A patch that does not pass is not written, and every patch says which grade of evidence it has. A patch a model wrote says so, in the report and inside the patch file; and
- Emendant never writes to Git history.
This distinction is intentional. The claim that no source leaves the machine applies to scan. For an assisted fix the user has explicitly enabled, the accurate claim is narrower: Emendant never receives or stores source, and what leaves the machine is the bounded excerpt, going straight to the chosen provider. For a contribution the user has explicitly enabled, the accurate claim is narrower again: Emendant does receive something, and what it receives is the file the user can read on their own disk.