| Version | Supported |
|---|---|
| v0.5.x | ✅ |
| < v0.5 | ❌ |
Marcut deals with sensitive legal and personal documents. We take security seriously.
Do NOT report security vulnerabilities via public GitHub issues.
If you discover a security vulnerability, please email security@marclaw.com (or the repository owner directly). We will acknowledge receipt of your vulnerability report within 48 hours and strive to send you regular updates about our progress.
We are particularly interested in reports concerning:
- Data Leakage: Unintended retention of PII or document content (e.g., in logs or temp files).
- Sandbox Escapes: Arbitrary file access outside the sandboxed Application Support container.
- Redaction Failures: Scenarios where "redacted" text is recoverable from the DOCX structure.
- Dependency Vulnerabilities: Issues in embedded libraries (Ollama, Python packages).
- Marcut processes all documents locally.
- Network access is restricted to
localhost(Ollama) and explicit model downloads. - No telemetry or usage data is collected.
This section documents the security controls implemented in Marcut.
Files: docx_io.py, docx_revisions.py
DOCX files are ZIP archives containing XML. Malicious XML can include external entity declarations that read local files or cause denial of service.
Mitigation: All XML parsing uses a safe parser with entity resolution disabled:
parser = etree.XMLParser(resolve_entities=False)
root = etree.fromstring(xml_bytes, parser)File: preflight.py
The application spawns subprocesses to manage the Ollama service.
Mitigation:
- All
subprocess.run()andsubprocess.Popen()calls use list arguments, never shell strings. shell=Trueis never used.- Model names are validated via
validate_model_name()to reject shell metacharacters (;,|,&,$,`,>,<).
File: unified_redactor.py
User-provided model names could potentially be passed to subprocesses.
Mitigation: The validate_model_name() function enforces:
- Ollama model names: alphanumerics, underscores, hyphens, colons, periods only.
- GGUF file paths: no shell metacharacters.
Files: docx_io.py, docx_revisions.py
Malicious ZIP archives can contain paths like ../../../etc/passwd to overwrite files outside the extraction directory.
Mitigation: Core redaction reads and writes DOCX content in memory via ZipFile.read()/ZipFile.writestr(). The macOS app also runs a validation pass that:
- Copies the DOCX to a temp directory for sandbox-safe inspection.
- Runs
/usr/bin/unzip -tand extracts a minimal set of XML parts for integrity checks. - Securely removes the temp directory after validation.
File: MarcutApp.entitlements
The macOS App Sandbox restricts what the application can access.
Entitlements granted:
| Entitlement | Purpose |
|---|---|
com.apple.security.app-sandbox |
Enables sandbox |
com.apple.security.files.user-selected.read-write |
Access files user explicitly opens |
com.apple.security.network.client |
Model downloads + connect to local Ollama |
com.apple.security.network.server |
Ollama binds to localhost |
No broader filesystem access; outbound network use is limited to model downloads, and inference stays on localhost.
Files: model.py, model_enhanced.py, preflight.py
All HTTP requests are made to the local Ollama service (http://127.0.0.1:<port>/api/...).
Security properties:
- Localhost-only: No external network calls.
- No
verify=False: TLS verification is not disabled (not needed for localhost HTTP). - Timeouts: Health checks use short timeouts (2–5s). LLM requests allow long-running responses (up to ~120 minutes). The macOS app also enforces per-phase and per-document timeouts (default 120 minutes for the processing phase).