# Security Considerations for Automattic/harper: Privacy-First Grammar Checking

> Explore security considerations for Automattic harper. Learn how this privacy-first grammar checker processes text locally via WebAssembly and Rust, keeping your content secure and private.

- Repository: [Automattic/harper](https://github.com/Automattic/harper)
- Tags: best-practices
- Published: 2026-07-27

---

**Harper processes all text locally using WebAssembly, Rust native binaries, or language servers, ensuring user content never leaves the machine or transmits over networks.**

Understanding the **security considerations for Automattic/harper** reveals a privacy-first architecture designed to eliminate external attack vectors. Unlike cloud-based alternatives that stream keystrokes to remote servers, Harper operates entirely within the user's environment through sandboxed WebAssembly modules, native CLI tools, and local language servers. This offline-first approach ensures complete data sovereignty while maintaining functionality across desktop applications, browser extensions, and editor integrations.

## Local-Only Processing Architecture

Harper's core security guarantee rests on its **local-only processing** model. The grammar engine runs as a native binary via `harper-cli`, as a WebAssembly module in `harper-wasm`, or as a language server through `harper-ls`—all without network dependencies.

In `harper-core`, the `Linter` struct performs all text analysis in-process. The `LocalLinter` class in the JavaScript bindings loads the WASM module directly into the runtime environment, ensuring that sensitive documents remain in memory without external transmission. The component boundaries enforcing these isolation guarantees are documented in [`ARCHITECTURE.md`](https://github.com/Automattic/harper/blob/main/ARCHITECTURE.md), which details how the core engine remains separate from platform-specific I/O operations.

### WebAssembly Sandbox

The `harper-wasm` package executes within the browser's or Node.js's **WebAssembly sandbox**, which provides memory isolation and prevents direct filesystem or network access. As documented in [`harper-wasm/README.md`](https://github.com/Automattic/harper/blob/main/harper-wasm/README.md), this sandboxing limits the impact of potential code-execution vulnerabilities by restricting the grammar engine to a confined execution environment with no system call privileges.

### No External API Dependencies

Harper does **not** call external APIs for spelling suggestions, language models, or analytics. This eliminates risks associated with third-party data breaches or man-in-the-middle attacks that plague services requiring cloud connectivity for core functionality.

## Data Privacy and Persistence

Harper implements **data isolation** by design, minimizing persistent storage and eliminating telemetry entirely.

### User Dictionary Storage

The only data Harper persists is the optional **mutable user dictionary**, stored as a plain-text file named [`dictionary.txt`](https://github.com/Automattic/harper/blob/main/dictionary.txt) in the application's configuration directory. The implementation in [`harper-desktop/src-tauri/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config.rs) handles this storage without encryption requirements, as it contains only user-added words rather than full document content. No grammar rules, document text, or usage patterns are cached between sessions.

### Zero Telemetry Policy

According to the [`README.md`](https://github.com/Automattic/harper/blob/main/README.md), Harper emits **no telemetry** and maintains **no network requests** for analytics, spelling suggestions, or language model inference. This eliminates the data exfiltration risks common in third-party grammar services that rely on external APIs for core functionality.

## Platform-Specific Security Models

Different Harper distributions employ platform-appropriate security controls to maintain isolation between components.

### Tauri Desktop Security

The `harper-desktop` application uses **Tauri v2**, which enforces a strict permission model between the frontend and backend. The Svelte-based UI communicates with the Rust backend via a JSON-line protocol over stdin/stdout, as implemented in [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs). All messages serialize through Rust structs, preventing injection attacks that could arise from raw string parsing.

Native OS calls—such as the screen-overlay highlighter—require explicit user consent through Tauri's permission system. The highlighter subprocess communicates via newline-delimited JSON, ensuring that arbitrary code execution cannot occur through message parsing.

### Browser Extension Permissions

The Chrome and Firefox extensions declare **minimal permissions** limited to `activeTab` and `storage` access. As documented in [`packages/chrome-plugin/README.md`](https://github.com/Automattic/harper/blob/main/packages/chrome-plugin/README.md), these extensions perform linting using the locally-loaded WASM module rather than background networking, preventing cross-origin data leakage or man-in-the-middle attacks during text analysis.

## Development and Supply Chain Security

Harper maintains security through dependency management and contributor policies that prevent supply chain compromises.

### Dependency Auditing

The project uses `cargo audit` for Rust dependencies and `npm audit` for Node.js packages to surface known vulnerabilities. While the [`pnpm-lock.yaml`](https://github.com/Automattic/harper/blob/main/pnpm-lock.yaml) file contains some legacy dependency warnings (such as older `glob` versions), the CI pipeline actively monitors these advisories. Regular updates to the lockfile ensure that development tooling does not introduce exploitable components into the build chain.

### Contributor Security Policies

The [`AGENT_POLICY.md`](https://github.com/Automattic/harper/blob/main/AGENT_POLICY.md) file establishes strict security boundaries for contributors, explicitly forbidding secret leakage, arbitrary code execution, or filesystem access outside the repository boundary. This policy integrates with CI automation to prevent malicious contributions from compromising the build artifacts distributed to users.

## Implementation Examples

The following examples demonstrate Harper's privacy-preserving APIs operating entirely offline:

```javascript
// harper.js – using the WASM build in a Node script
import { LocalLinter } from "harper.js";

(async () => {
  const linter = await LocalLinter.create();           // loads WASM locally
  const result = await linter.lint(
    "Their is a mistake in this sentence."
  );
  console.log(result);                                 // only local output
})();

```

```rust
// harper-core – calling the core library directly
use harper_core::lint::Linter;

fn main() {
    let linter = Linter::new();                         // pure Rust, no I/O
    let diagnostics = linter.lint("She has a dog.");
    println!("{:?}", diagnostics);
}

```

```bash

# CLI – lint a file without sending data anywhere

harper-cli lint path/to/document.txt

```

All three execution paths—JavaScript WASM, native Rust, and command-line interface—process text without network transmission, ensuring complete data containment within the host environment.

## Summary

- **Local-only processing** ensures text never leaves the machine through `harper-wasm`, `harper-cli`, or `harper-ls` implementations.
- **WebAssembly sandboxing** restricts the grammar engine's access to system resources and network interfaces.
- **Minimal data persistence** stores only user-defined dictionaries in [`dictionary.txt`](https://github.com/Automattic/harper/blob/main/dictionary.txt) via [`harper-desktop/src-tauri/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config.rs), with no document caching or telemetry.
- **Tauri security model** isolates the desktop UI from native OS calls using structured JSON communication in [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs).
- **Supply chain protection** relies on `cargo audit`, `npm audit`, and the [`AGENT_POLICY.md`](https://github.com/Automattic/harper/blob/main/AGENT_POLICY.md) contributor guidelines to prevent dependency vulnerabilities and malicious code insertion.

## Frequently Asked Questions

### Does Harper send my text to cloud servers?

No. Harper operates entirely offline without external API calls. The [`README.md`](https://github.com/Automattic/harper/blob/main/README.md) explicitly states that no network requests occur during linting, and the `harper-core` library processes text in-memory without transmission. This applies to all distribution formats: CLI, WebAssembly, language server, and desktop application.

### What data does Harper store locally?

Harper persists only the optional user dictionary as a plain-text file ([`dictionary.txt`](https://github.com/Automattic/harper/blob/main/dictionary.txt)) in the configuration directory, as managed by [`harper-desktop/src-tauri/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config.rs). The software does not cache documents, grammar corrections, or usage patterns. No telemetry data is collected or transmitted.

### How does Harper handle security in browser extensions?

The browser extensions (Chrome/Firefox) request only `activeTab` and `storage` permissions per [`packages/chrome-plugin/README.md`](https://github.com/Automattic/harper/blob/main/packages/chrome-plugin/README.md). Linting occurs within the WebAssembly sandbox using locally-loaded code, eliminating background network requests that could expose sensitive text to third parties.

### What measures prevent code injection in the desktop app?

The Tauri-based desktop application uses structured JSON serialization over stdin/stdout for inter-process communication, defined in [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs). This approach avoids raw string parsing vulnerabilities. Additionally, native OS access requires explicit user consent through Tauri's permission system, preventing unauthorized file system or network operations.