-
Notifications
You must be signed in to change notification settings - Fork 0
security
CSV Anonymizer is a local-first desktop app. Its standard detection, preview, transformation, and reporting paths run locally through Rust code in crates/csv-anonymizer-core. Optional Smart replacement uses the user's local Ollama runtime through src-tauri/src/local_ai.
Active contributors: Douwe de Vries
The default workflow reads a local CSV or pasted sample, detects likely sensitive fields, previews replacements, and writes transformed output. It does not call hosted PII APIs.
Important boundaries:
- Rust detection and transformation run in
crates/csv-anonymizer-core. - Tauri commands in
src-tauri/src/commandsexpose local desktop operations tofrontend/src/tauri.ts. - Smart replacement sends selected values only to the configured loopback Ollama endpoint, currently
http://127.0.0.1:11434insrc-tauri/src/local_ai/mod.rs. - Model weights and Ollama runtime binaries are not bundled with the app or tracked in the repository.
- Output is transformed source data, not a formal anonymity or differential privacy guarantee.
PathAccess in src-tauri/src/path_access.rs keeps in-memory grants for input and output paths:
- Input files are canonicalized and must exist as regular files.
- Output paths are normalized by canonicalizing the parent directory.
- Existing output leaves must be regular files.
- Existing output symlinks are rejected.
- Existing output leaves that resolve outside the output directory are rejected.
src-tauri/src/commands/shared.rs asks for explicit Tauri dialog confirmation when a typed path has not already been granted through Browse.
Output safety is split across Tauri and core code:
-
src-tauri/src/commands/shared.rsrejects output suffixes with path separators or control characters before constructing suggested output paths. -
crates/csv-anonymizer-core/src/file_ops.rswrites through a temporary file and renames into place on success. -
crates/csv-anonymizer-core/src/csv_io.rsrejects ragged rows with non-empty fields beyond the header shape. -
crates/csv-anonymizer-core/src/csv_io.rspreserves blank rows and normalizes short rows to the header length.
These guards protect against accidental writes outside the selected location, unsafe symlink leaves, and partial output after transformation errors.
Spreadsheet formula injection is handled in crates/csv-anonymizer-core/src/csv_io.rs. Every output record is passed through neutralize_spreadsheet_formula before writing. Values that begin with formula prefixes, leading whitespace before formula prefixes, tabs, returns, newlines, or full-width formula variants are prefixed with a single quote.
This applies to headers and data cells because the writer path uses write_csv_output_record for both.
src-tauri/tauri.conf.json defines a restrictive content security policy:
default-src 'self'- scripts from self only
- object embedding disabled
- base URI restricted to self
- frame ancestors disabled
- local IPC connect sources only
Development CSP allows the Vite dev server at http://localhost:5173 and WebSocket HMR.
src-tauri/capabilities/default.json is the command allowlist for the main window. It lists each allow-* command permission, core:default, core:app:allow-set-app-theme, and dialog open/save permissions.
Smart replacement is optional and off by default in settings. The Local AI path is deliberately constrained:
-
src-tauri/src/local_ai/ollama.rschecks Ollama/api/versionand/api/tags. -
src-tauri/src/local_ai/provider.rsposts tohttp://127.0.0.1:11434/api/generate. -
src-tauri/src/local_ai/prompt.rsasks for JSON matching a schema with original and replacement pairs. -
crates/csv-anonymizer-core/src/smart.rsvalidates responses before storing replacements.
Rejected Smart replacement outputs include unexpected originals, missing outputs, empty outputs, same-as-original outputs, outputs containing the original value, control characters, duplicate originals, and duplicate outputs. Missing or unsafe model output falls back through normal Smart replacement error and fallback handling rather than silently accepting unsafe replacements.
Release signing inputs are GitHub Actions secrets or variables used by .github/workflows/release.yml. The repository should contain only secret names and release logic, never secret values.
scripts/check-release-metadata.mjs rejects tracked Local AI model/runtime artifacts such as .gguf files, model caches, Ollama caches, and llama-server binaries. This keeps local model setup as an in-app or Ollama action rather than a bundled repository artifact.
Related pages: Deployment, Tauri commands, Configuration, and Patterns and conventions.