Hostkeep
Security model

Protections that don't trust the AI.

An AI assistant can be confused, or tricked by text hidden in a file it reads. Hostkeep assumes that will happen. Every protection below is enforced in code on your machine, and every claim names the code that enforces it and the automated test that proves it.

Updated 8 October 2026hostkeep.tech/security

Trust model

Hostkeep trusts the owner who writes its configuration, and anyone who holds the access token (completely, today; see the known gaps).

Hostkeep does not trust anything the assistant sends: paths, file patterns, SQL, command parameters. It doesn't trust the file system layout either (links and junctions are treated as attacks), archive contents, or responses from the internet.

The seven walls

  • 01 Gate. Hostkeep listens on the local machine only (127.0.0.1) by default. Every request needs the access token (compared in constant time) and an allowed host name, and is rate-limited, before its body is parsed. Remote access goes through a tunnel the owner controls.
  • 02 Only enabled tools exist. Optional tool families (jobs, outbound fetch, exports, host access, desktop) are absent from the tool list unless the owner switches them on.
  • 03 Projects. The assistant addresses files only as a project name plus a relative path. On Windows, file content operations run through a dedicated worker that pins folders by handle (see below).
  • 04 Read-only by default. Writing is switched on per project and can be limited to sub-folders. Repository control paths such as .git and the owner's protected patterns stay read-only even in writable projects, including archive extraction.
  • 05 Tasks, not a shell. Commands are defined by the owner with typed parameters (string, integer, enum, relative path). Values that look like extra options are rejected unless explicitly allowed. Git runs with repository-defined hooks, filters, monitors, diff and signing programs disabled.
  • 06 Secrets stay home. Every program Hostkeep starts receives an allow-listed environment without the access token. Outbound fetch is off by default; when enabled it allows HTTPS only, refuses private and special network ranges, connects to the exact address it checked, and re-checks every redirect.
  • 07 Record. Every tool call, including rejected ones, produces one activity record without file contents, argument values or secrets. Records are SHA-256 hash-chained across daily files, so editing or deleting a record is detected. If writing the log fails, new changes and tasks are refused before they run, until logging recovers.

Project containment on Windows

The classic weakness of file tools is a race: a path is checked, then a folder in it is swapped for a link before the file is opened. Path checks alone can't close that window, and our own measurements showed it.

Hostkeep's answer is a fixed worker that pins every folder from the drive down to the target with an open handle that blocks renames and deletion, then opens each next folder and the file relative to the handle it already holds, never by full path. Windows refuses to resolve a name inside a folder that has been turned into a link this way, so nothing outside the project is reached. After each open, the worker re-checks the held folder and the file's real location, and rejects hard links on writes. Protected-path rules are applied to the real names Windows reports, so short-name aliases don't bypass them.

Evidence: a stress test performs 100,000 reads and overwrites while another process swaps project folders for links as fast as it can (43,220 swaps). Result: zero outside reads, zero changed outside files, zero leftover files. With short pauses between swaps, normal operations keep succeeding (about 900 reads and 1,000 writes in 20,000 attempts). Median contained read time: 0.57 ms.

Scope: this applies to file content operations (read, write, edit, copy, move, delete, hash, export) on local NTFS drives. Listings, search, archives and data helpers keep an earlier identity-check mitigation; see the known gaps.

Claims and evidence

Each claim maps to the function that enforces it and the named automated test that checks it. The full suite has 192 tests.

ClaimEnforced byProven by
Host, token and rate checks run before a request body is parsedsrc/server.mjs:createAppunauthenticated large malformed bodies are rejected before parsing or rate-limit bypass
Disabled tool families are absent from the tool listsrc/server.mjs:defineToolslimited configuration advertises only enabled tool families
Strict Windows file reads never accept outside contentsrc/windows-file-tools.mjsstrict public read never accepts outside content under inconsistent Node path observations
The file worker starts under Windows' default script policy without changing itsrc/windows-file-io.mjsfixed file worker initializes with Restricted child policy without changing persistent policy
Writable projects still protect control pathssrc/security.mjs:assertWritablewritable roots reject every mutation of default and operator-protected paths
Archive extraction checks protected paths before writingsrc/advanced-tools.mjs:archiveExtractarchive extraction checks every selected entry against protected paths before writing
Git never runs repository-defined programssrc/safe-git.mjs:runSafeGitcheckpoint and Git inspection never run repository-defined programs
Task parameters reject option-like valuessrc/command-parameters.mjsdefault string parameters reject option-like and non-string values before process start
Child processes never receive credentialssrc/child-environment.mjsevery project process route withholds credential variables and preload overrides
Outbound HTTPS connects to the checked addresssrc/outbound.mjs:downloadAssetHTTPS connects to the vetted address while preserving the TLS hostname
Every tool call gets one content-free activity recordsrc/server.mjs:recordToolCallevery registered tool call has exactly one content-free audit record, including schema rejection
Edited or deleted activity records are detectedsrc/audit.mjs:verifyAuditFilesediting or deleting an interior audit record reports the first broken record
If logging fails, new changes are refused before they runsrc/server.mjs:observedfailed post-call audit preserves the result and blocks new mutation before its marker is written
Export links work once and are loggedsrc/server.mjs:createAppone admitted HTTP export download consumes the link and is audited without token or contents
Written text stays within the configured size limitsrc/tools.mjs:writeHTTP accepts a configured UTF-8 write even when JSON escaping exceeds five MiB
Fallback: an opened file with a different identity is rejectedsrc/security.mjs:openContainedan opened handle with a different file identity is rejected and closed before any read
Fallback: helper output is discarded if its file changessrc/security.mjs:withHelperIdentitya named helper discards output if its file changes during work

Known gaps

Until a gap is closed, don't rely on the protection it names. Each one has a planned fix on the roadmap.

GapStatusPlanned fix
No human approval before changes or tasks runOpenApproval gate on a local page, optionally with a phone notification, so an assistant can't approve its own action (next phase)
Running tests on a writable project executes that project's codeOpenTask runs behind the same approval gate (next phase)
One access token: no per-client identity, scopes or expiryOpenA separate key per client (next phase), then OAuth sign-in
Folder-swap race for listings, search, archives and data helpersMitigatedClosed for file content operations on local NTFS; the remaining tools keep an identity-check mitigation and move to the pinned worker later

The activity log detects edits against the retained chain. It can't stop someone with full administrator access from rewriting every record; forwarding records off the machine is planned.

Advanced host access

For owners who need it, an optional host module can start processes and PowerShell outside project folders, and an optional desktop module can automate windows. Both are off by default and outside the project protections above: they run with the permissions of Hostkeep's Windows user. What they do provide: explicit opt-in, no privilege escalation, no double execution on retries, the token stripped from child environments and redacted from output, and a private job folder that rejects links. They will be left out of the pilot build.

Deployment advice

  • Run Hostkeep as a standard user, not elevated. A dedicated low-privilege account is better still.
  • Keep projects read-only unless writing is needed, and grant writes to specific sub-folders.
  • Generate a long random token, keep it in the environment only, and rotate it if you suspect exposure.
  • Don't expose the port directly. Use a tunnel with its own access control.
  • Never name a project folder that contains credentials, backups or production data.

Report a vulnerability

Please email fay@hostkeep.tech with "Security report" in the subject. Include what you found and how to see it. Please don't post details publicly until a fix is available. Machine-readable contact: /.well-known/security.txt.