Security and privacy
Emendant’s scan path is deliberately local and read-only.
During scan
Section titled “During scan”Emendant:
- reads supported manifests, lockfiles, configuration,
.gitignorefiles, and relevant source files; - uses a locally verified feed, either the copy bundled inside the package or a newer cached snapshot;
- parses source without loading or executing it; and
- prints findings to the terminal or standard output.
Emendant does not:
- upload source code;
- make a network request unless you have already enabled automatic feed refresh;
- write to the repository;
- run package scripts, tests, or application code;
- modify the Git index or history; or
- discover or transmit credentials.
The npm package has no postinstall script.
Source retention
Section titled “Source retention”There is no Emendant service in the scan path. Source text is read in the local process, parsed into plain matching facts, and not retained by Emendant after the 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.
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”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.