Skip to content

Releases: churnast/hermes-memory-shield

Memory Shield v1.1.2

Choose a tag to compare

@churnast churnast released this 09 Oct 09:40

Fixed

  • A call that refers to a memory alias so often that following it would add more than 16,384 characters is now judged as a direct edit of the owner's profile, which the default policy refuses. In 1.1.1 the substitution stopped silently, so F=~/.hermes/memories/USER.md, then echo $F 700 times, then echo pwned > $F (5.6 KB) passed, and so did the Python form with open(p, 'r') 700 times before open(p, 'w'); 1.1.0 refused both.
  • The check for a call longer than 16,384 characters ignores case, quotes and backslashes: it looks for the word memories, USER.md or MEMORY.md after dropping ", ' and \, so mem"ori"es/US"ER".md, mem\ories/US\ER.md and MEMORIES/user.md padded past the cap are refused again, as in 1.1.0. Such a call is charged to the agent's notes only when MEMORY.md is the only word found.
  • A shell call that mixes memory aliases with xargs rm reads its words once after the last command instead of once per new alias: an alternation of the two under 16 KB took 0.66 to 1.16 s on a Mac and now takes about 12 to 20 ms.
  • The pattern for open(path, mode) no longer retries a long run of spaces at every split: open(a followed by 16,370 spaces took about 280 ms, and open( followed by 2,000 spaces about 2.9 s (16,370 did not finish in 20 s), in both execute_code and terminal. Both now take about 3 ms. The verdicts are the same.
  • Timing tests now cover payloads just under the cap, where the scanner actually runs, as well as past it, and new tests cover the alias budget in shell and Python and the case, quote and backslash forms past the cap.

Changed

  • The README says what the check past the cap looks for (the word memories, USER.md or MEMORY.md, any case, quotes ignored), gives the cap as 16,384 characters, and says that a snapshot, the audit log or a restored memory file that did not exist before is created with mode 0600, while an existing one keeps its permissions.

Memory Shield v1.1.1

Choose a tag to compare

@churnast churnast released this 09 Oct 08:49

Fixed

  • The pre_tool_call hook now has a bound on its time and memory use for terminal and execute_code calls, after a review of the plugin for the Hermes catalog. A call is read up to 16 KB; a longer one is judged without being read: it is refused when it mentions USER.md, MEMORY.md or the memories folder (with a hint to split it up or keep the memory files out of it) and let through when it mentions none of them. Before, a one-line call of .hermes.unlink( repeated 2000 times (30 KB) kept the hook busy for about two minutes, because the memory path was looked for once per .unlink( or .write_text( in a statement; it is now looked for once per statement.
  • Shell variables and Python names assigned a memory path are substituted in one pass, a name whose value refers to another such name is not kept, and the substitution stops once it has added more than 16 KB to the call. Before, about thirty chained lines like a1 = '.hermes/memories' + a2 + a2 doubled the text at every step until memory ran out.
  • The two regular expressions that looked for the memories folder behind the Hermes home no longer rescan the rest of the line for every mention of the home.
  • Snapshots, the audit log and a restored memory file are written through a temporary file with a unique name in the same folder (tempfile.mkstemp) instead of a fixed .tmp neighbour, so two writers can never share one; a file that already exists keeps its permissions.

Memory Shield v1.1.0

Choose a tag to compare

@churnast churnast released this 08 Oct 14:38

Added

  • A new level for the owner's profile, owner_edits, now the default: the agent may add facts wherever it may write and may replace one only when the owner asks in a direct chat, the CLI or a chat in trusted_chats (and, once trusted_users is set, only for a person listed there); nobody may delete one, and a replace with empty or placeholder text still counts as a delete. In a group, a scheduled job or the background review it behaves like append_only. append_only stays available for owners who want nothing changed by the agent at all.
  • Hermes' unattended self-improvement review, the fork that tidies memory and skills after a conversation with nobody watching, may not add to, change or delete the owner's profile unless user_profile is off. The plugin reads Hermes' own marker for that fork (tools.skill_provenance.is_unattended_review), which reaches pre_tool_call hooks under the default plugins.isolation: in_process; a review the owner starts with /refine is attended and keeps the direct-chat rules. The agent's own notes keep their level there, where Hermes itself holds deletions for approval.

Changed

  • trusted_users now applies to direct chats too: once it is set, a direct chat with someone not listed is judged like a shared chat (read-only by default, group_chats decides), and mode: approve blocks there instead of asking. A session without a user id, such as the CLI, still counts as the owner. With trusted_users empty nothing changes. /memory-shield and /memory-shield whoami say so.
  • The policy hints name the new rules: a replace outside the owner's direct chat says that facts about the owner are changed only when the owner asks in a direct chat; a refused delete of a fact about the owner says that facts are never deleted and that placeholder text counts as deleting.

Fixed

  • Shell and Python side-door detection no longer refuses commands that only read a memory file or write somewhere else. Before, any command that mentioned a memory file together with any writing word was refused, so cat ~/.hermes/memories/USER.md > /tmp/copy.md, cp ~/.hermes/memories/USER.md /tmp/x and grep ... USER.md > elsewhere were blocked. Now the plugin reads the call command by command and counts only a write whose target is USER.md, MEMORY.md or the memory folder: a redirection, tee, cp, install, rsync, ln or dd of= into it, sed -i or perl -i on it, rm, mv, truncate, shred or find -delete of it, and in Python open(..., "w"/"a"/"x"/"+"), write_text, write_bytes, unlink, os.remove, shutil.move, shutil.rmtree and shutil.copy with it as the destination. Simple shell variables, cd into the memory folder and Python names assigned a memory path in the same call are followed, and quoted strings are read as shell text once, for python -c, subprocess and os.system.

Memory Shield v1.0.1

Choose a tag to compare

@churnast churnast released this 08 Oct 12:35

Fixed

  • /memory-shield log follows the same rule as /memory-shield restore: it answers only in a direct chat, the CLI or a chat in trusted_chats, and when trusted_users is set, only the people listed there; a session without a user id, such as the CLI, counts as the owner. Before, anyone who could message the agent directly could read up to 50 events from every chat, with excerpts from the owner's own chats (for a deletion, words from the memory entry itself), even with trusted_users set. Someone not listed there gets a refusal that says where the command works and who may run it, and restore now gives the same one. /memory-shield snapshots is unchanged: it shows times, stores and sizes, no memory text.

Memory Shield v1.0.0

Choose a tag to compare

@churnast churnast released this 08 Oct 11:48

The first stable release. What the plugin does as of this release is listed under Added and the two fixes since 0.1.4 under Fixed; the README, its banner, a catalog card and a short demo video are new.

Added

  • A policy for Hermes' built-in memory tool through one pre_tool_call hook, per store: the owner's profile (USER.md, setting user_profile) is append-only, and the agent's own notes (MEMORY.md, setting agent_notes) can be added to and updated but not deleted. Levels off, no_delete, append_only and read_only; a batch is checked operation by operation.
  • Shared chats (groups, channels, forum topics, guild threads, webhook runs) are read-only (group_chats), except for the people in trusted_users (ids as platform:id) and the owner-only chats in trusted_chats, which are judged like a direct chat. scheduled_jobs adds an extra limit in cron runs; it is off by default.
  • Modes: block refuses with a hint the model can act on, approve asks through Hermes' approval prompt in direct chats (with a key for that exact call) and blocks elsewhere, observe allows the call and logs it.
  • Replacing an entry with empty or placeholder text ("n/a", "[deleted]", and placeholder words in Russian, Spanish, Portuguese, German and French) counts as removing it.
  • Direct edits of USER.md and MEMORY.md through write_file, patch, terminal and execute_code, and shell commands that wipe or move the whole memory folder, are judged as an add, a replace and a remove at once.
  • A snapshot of the memory file right before an edit or deletion goes through: 20 per file by default, at most 200, snapshots: 0 turns them off. /memory-shield snapshots lists them, and /memory-shield restore <n> puts one back in a direct chat or a chat in trusted_chats, after saving the current file.
  • An audit log of refused and flagged writes (the last 500, each with a 160-character excerpt; audit_log: false turns it off), shown by /memory-shield log [n] in a direct chat, the CLI or a chat in trusted_chats. /memory-shield shows the policy and how many events and snapshots are kept; /memory-shield whoami shows the user id and, in a shared chat, the chat key.
  • A card for the Hermes plugin catalog, docs/card.png (1200x600): in a group, a stranger asks the agent to forget everything about its owner, the agent's notes stay, and the shield sits on the chat. docs/banner.png stays the README banner.
  • The README shows a short demo (docs/demo.webp, also as docs/demo.mp4, 20 seconds), re-drawn from a local test run with fictional people, in two scenes: in the group "Friends", Sam asks the agent to remember "Alex owes me $100" and it refuses; in a direct chat, the owner, Alex, asks it to forget everything, and it refuses and offers a dated note. Under What you get, five screenshots from docs/screenshots.

Changed

  • The README follows the layout of Telegram Stickers: badges in one style, a one-line introduction to Hermes Agent, a Quick start (install and restart, /memory-shield to check, trusted_users for groups), What you get, the commands, Configuration, the comparison with memory.write_approval, Privacy and safety, Known limitations and Troubleshooting as a list. Known limitations is new: groups where the gateway does not pass the message author to plugins (trusted_chats covers an owner-only one), memory provider plugins, best-effort file and shell detection, facts about the owner that only the owner can fix by default, and approve depending on Hermes' approvals. Privacy and safety now also say who can run which subcommand and that the plugin holds the memory store's lock file while it reads or writes a memory file.
  • The README banner is redrawn as a mini chat, like the Telegram Stickers banner: in a group, Sam tries to plant a claim about the owner, Alex, then to wipe what the agent knows, and the agent's notes stay. It drops its pills and uses larger text so it reads in small link previews.

Fixed

  • /memory-shield log answers only in a direct chat, the CLI or a chat in trusted_chats, like /memory-shield restore, and in any other chat says where to run it. Before, it worked in any chat, so whoever could run the agent's slash commands in a group could read up to 50 events from every chat, with excerpts from the owner's direct chats (for a deletion, words from the memory entry itself). /memory-shield snapshots still works in any chat: it shows times, stores and sizes, no memory text.
  • A level set to off with hermes config set or as an unquoted off in config.yaml is stored as YAML false; the plugin now reads that as off instead of silently keeping the default. This applies to user_profile, agent_notes, group_chats and scheduled_jobs.

Memory Shield v0.1.4

Choose a tag to compare

@churnast churnast released this 05 Oct 11:39

The scheduled_jobs setting now appears in the Hermes Desktop settings form (it was missing from the plugin settings list), the trusted_users hint asks for platform:id ids, and the README explains how to update, switch off and remove the plugin.

hermes plugins update memory-shield

Memory Shield v0.1.3

Choose a tag to compare

@churnast churnast released this 05 Oct 10:59

New trusted_chats setting: a chat that only you and the agent are in (for example a private Telegram group with topics) is judged like a direct chat. In Telegram groups that Hermes observes (observe_unmentioned_group_messages), the sender is not passed to plugins, so trusted_users cannot match there and every memory write from such a group was blocked, even yours. /memory-shield whoami now shows the chat key to add. Also fixed: platform:id entries whose id contains colons (Matrix) now match.

hermes plugins update memory-shield

Memory Shield v0.1.2

Choose a tag to compare

@churnast churnast released this 05 Oct 09:23

Placeholder words in Russian and a few other languages ("удалено", "нет", "неактуально", "gelöscht") now count as deleting an entry, like "deleted" and "n/a" already did.

hermes plugins update memory-shield

Memory Shield v0.1.1

Choose a tag to compare

@churnast churnast released this 05 Oct 09:21

Shell commands that wipe or move the whole memory folder without naming a file (rm -rf ~/.hermes/memories, find ... -delete, shutil.rmtree) are now caught like direct edits of USER.md and MEMORY.md.

hermes plugins update memory-shield

Memory Shield v0.1.0

Choose a tag to compare

@churnast churnast released this 05 Oct 09:00

First public release.

Install

hermes plugins install churnast/hermes-memory-shield --enable

Added

  • Policy for the built-in memory tool through a pre_tool_call hook: owner profile append-only, agent notes without deletion, shared chats read-only; levels off, no_delete, append_only, read_only.
  • Modes block (refuse with a hint the model can act on), approve (Hermes' approval prompt, direct chats only) and observe (log only).
  • Replacing an entry with empty or placeholder text counts as removing it.
  • Direct edits of USER.md and MEMORY.md through write_file, patch, terminal and execute_code are judged like the memory tool.
  • trusted_users who may write memory from shared chats, and a scheduled_jobs level for cron runs.
  • Snapshots of the memory file before every allowed edit or deletion, with /memory-shield restore.
  • Audit log of refused and flagged writes, shown by /memory-shield log; /memory-shield whoami.

Requires Hermes Agent 0.21.5 or newer. Settings, commands and the privacy section are in the README.