Security
What Gryndara enforces. What it doesn't. No marketing adjectives.
Every row below maps to code in the product. If you're evaluating Gryndara for a regulated business, this page is the source of truth — and security@gryndara.com answers questions it doesn't.
The one-sentence model
Work is local. Licensing is not. The portal runs as the signed-in Windows user, listens only on the loopback interface, stores its data in a folder next to the executable, and never sends your documents anywhere. gryndara.com holds accounts, keys and device check-ins so Gryndara can license seats and support customers. Its threat model is “keep business documents off third-party servers and keep unauthorised staff out of the portal” — not “resist a compromised host”.
Enforced controls
| Area | Control | Where |
|---|---|---|
| Network exposure | Portal binds 127.0.0.1 (default port 8080; next free port if busy). Ollama binds 127.0.0.1:11434. No LAN listener. Gryndara never kills another program to take a port. | scripts/fortress-service.mjs, ollama-process.ts |
| Cloud inference | None. Documents are never sent to any server, including ours. | — |
| Outbound connections | Trial start + daily license refresh to gryndara.com (license id, device id, version, OS, health flags — never file names or content) so we can manage seats and support; optional signed-update check; one-time Ollama and model download. Not used for inference. | lib/license/client.ts |
| Passwords | scrypt (N=16384, r=8, p=1), 64-byte key, per-user 16-byte salt, constant-time compare. | lib/auth/crypto.ts |
| Sessions | 32-byte random token; only its SHA-256 is stored. 7-day expiry. Validated against the store on every request. | src/proxy.ts, session-verify.ts |
| Cookies | HttpOnly, SameSite=Strict, Path=/. Secure when served over HTTPS. | lib/auth/cookies.ts |
| Authorisation | Roles admin / operator / viewer. One permission matrix enforced for pages (proxy), APIs (requireFeature) and navigation. | lib/auth/types.ts, guards.ts |
| Brute force | 5 failures per account+IP → 15-minute lockout; 30 failures/minute globally → cooldown. | lib/auth/rate-limit.ts |
| Updates | Manifest must carry a valid Ed25519 signature from the key pinned in the install. Package SHA-256 verified. HTTPS re-checked on every redirect. ZIP entries inspected for traversal and symlinks. Never overwrites data or the pinned key. | scripts/update-manager.mjs, release-signing.mjs |
| Licenses | License files are Ed25519-signed by gryndara.com with a key separate from the release key; the portal verifies offline against the public key shipped in the install. Bound to a device fingerprint; 30-day validity, 14-day grace. | lib/license/, install/license-public-key.pem |
| Ollama install | HTTPS download from ollama.com; Authenticode signature must be Valid and issued to Ollama before execution. | lib/runtime/ollama-install.ts |
| Watch folders | Drive roots, Windows/Program Files, profile root, .ssh/.aws/.gnupg, and Gryndara's data folder are refused. .env files never indexed. | storage/watch-folders-store.ts |
| Data files | JSON stores written mode 0600 via temp-file rename. | lib/runtime/paths.ts |
| Process environment | Only whitelisted variables reach the customer portal process — no dev secrets. | scripts/production-env.cjs |
| gryndara.com | Better Auth: Google sign-in and/or email + password (hashed with scrypt; never sent to Google). Same email on both paths is one account. License keys stored as SHA-256 plus AES-256-GCM for owner display. Stripe holds all card data; we store customer and subscription ids only. Neon Postgres, TLS. | web/src/lib/ |
Not enforced (yet) — and what to do instead
- At-rest encryption.
.gryndara/is plain files. Turn on BitLocker (Windows) or FileVault (macOS). This is the right layer for it anyway. - Process sandboxing. No seccomp, AppArmor or AppContainer. The portal has the same rights as the Windows user who launched it. Run it under a dedicated standard (non-admin) account.
- Installer code signing. The installer is signed only once a certificate is configured in CI. Until then, verify the SHA-256 published on the release page.
- Remote control of installs. Customer
/accountand Gryndara/opsshow last check-in and health flags; neither can read files or act on a PC.
Why we publish the gaps. Earlier builds of this product carried UI copy about “AES-256 data volumes” and “seccomp sandboxes” that the code did not implement. We removed every such claim. If you find one we missed, that's a bug — report it.
Exactly what the license check sends
Starting a trial POSTs a hardware fingerprint (not an install id) to gryndara.com/api/license/trial so the 14 days cannot be reset by deleting local files. Once a day, if the PC is online, a paid or trial license POSTs this to gryndara.com/api/license/refresh:
{
"licenseId": "…", // your license
"deviceId": "…", // this installation
"fingerprint": "sha256…", // hash of hostname + CPU + RAM + install id
"appVersion": "0.1.0",
"health": { // whitelisted flags only
"engine": "running",
"modelTier": "standard",
"ramGb": 16,
"watchFolders": 2,
"usersCount": 3
}
}The server whitelists those keys and drops anything else. No file names, no folder paths, no prompts, no outputs, no user names or emails.
Data flow
- You add a folder. Gryndara walks it, extracts text from supported files and stores an index (file paths, sizes, 8 KB previews) in
.gryndara/data. Originals are never copied or modified. - You send a task. The orchestrator selects relevant indexed files and sends their text to Ollama at
127.0.0.1:11434. - Agents run in sequence. Outputs are held in memory, then the final deliverable is written to
.gryndara/reportsand your outbox folder. - Nothing in steps 1–3 leaves the machine. The license check-in is a separate path and never includes those documents.
Reporting a vulnerability
Email security@gryndara.com with reproduction steps. We acknowledge within two business days and credit reporters in the changelog unless you prefer otherwise. Please don't open public GitHub issues for security reports.
Source access for audits
Gryndara is proprietary, but customers and prospective customers can request read access to the repository for security review under NDA. Ask at hello@gryndara.com.