Skip to content

Fix/lru eviction and effective fingerprint - #9

Merged
nayfly merged 5 commits into
mainfrom
fix/lru-eviction-and-effective-fingerprint
Aug 1, 2026
Merged

nayfly merged 5 commits into
mainfrom
fix/lru-eviction-and-effective-fingerprint

Conversation

@nayfly

@nayfly nayfly commented Aug 1, 2026

Copy link
Copy Markdown
Owner

No description provided.

Robert and others added 5 commits August 1, 2026 11:26
Three days of real OpenClaw traffic produced 51 hard_deny events, every one
`tool not allowed by execution gate`. The policy knew `shell`, `http` and
`filesystem`; the agent speaks `exec`, `read`, `write`, `edit`, `memory_get`.
Nothing was being judged — the gate was refusing a vocabulary, and a benign
markdown-to-docx conversion tripped it eleven times.

`tool_aliases` maps external names to the canonical capability. Data, not code:
adding a runtime is a config change, and the allowlist stays five capabilities
rather than accumulating every ecosystem's names. Taken from OpenClaw's own
tool-group definitions rather than from observation — the `coding` profile
exposes 25 tools and only 7 had appeared, so waiting to see the rest would have
measured nothing while the gate refused everything.

It lives at policy root, not inside the execution gate. Scoped to one gate, the
first version passed `exec` through the allowlist and had the capability matrix
refuse it immediately after: ordinary work denied for a reason nobody can find.
Both gates now resolve through the same map, asserted by a test.

The action is left alone, so the audit trail keeps the name the agent used and
the vocabulary report still reads `exec` rather than `shell`.

Two things this nearly broke, both caught by tests already there:

- `operation` fell out of filesystem's allowed parameters. It is what the
  confirmation gate reads to know a write is a write, so dropping it silently
  disables confirmation for every file action.
- `Remove-Item -Path C:/ -Recurse -Force` scored 0 while its backslash twin was
  hard-denied. Windows accepts both separators.

Replaying the real trail under the new policy: 51 hard_deny become 40 log_only,
and every destructive form still refuses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ve predicted

First day of real traffic under the new mapping: 12 allow, 2 escalate. Both
escalations were `unexpected parameters for tool` — `web_search` sends
`language`, `session_status` sends `sessionKey`. My lists were guesses from the
vocabulary report, and two were wrong.

The check catches a tool called in a shape the policy did not anticipate. That
is worth enforcing where a stray parameter could carry a payload, and is only
noise where it cannot. Kept for `shell` and `filesystem`: few parameters, and an
unexpected one is worth a second look. Dropped for `http`, `memory` and
`runtime`, whose parameters are provider-specific metadata no policy can
enumerate and none of which can carry a destructive payload.

Replaying the same trail: 14 of 14 allow, no escalations. Every destructive form
still refuses, and an unmapped tool is still hard-denied — asserted, not assumed.

This is what the phase exists to produce. The mapping was built from OpenClaw's
documentation, which gives tool names but not the arguments a provider actually
attaches; only traffic does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Third parameter name real traffic corrected in two days: `web_search` sends
`language`, `session_status` sends `sessionKey`, and `apply_patch` sends the
whole patch as `input`. The filesystem list did not know it, so the first patch
an agent applied escalated.

Observed, not guessed. OpenClaw's documentation names its tools; only traffic
names their arguments.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Posting a credential file scored 0. So did uploading an SSH private key,
archiving Documents and shipping the zip, and piping `cat ~/.ssh/id_rsa` into
curl. Every rule in the corpus asks whether a command destroys something; none
asked whether it sends something away.

For this deployment that is the likelier chain, not a theoretical one. The agent
holds a shell on the host, reads untrusted web pages, and its MEMORY.md contains
live credentials — it read them out on request two days ago. Poisoned page,
proposed one-liner, secrets gone, and the engine says risk 0.

Six shapes: curl's upload forms (`-d @file`, `-F name=@file`, `-T file`), a read
piped into a network client, PowerShell `-InFile` and `-Body (Get-Content ...)`,
WebClient.UploadFile, scp/rsync to `user@host:`, and `wget --post-file`.

Elevated, not critical. Uploading a file is sometimes exactly the request, so
this asks for a human rather than refusing. A rule that blocks legitimate work
gets switched off, and a switched-off rule protects less than none.

Downloading must not read as uploading: `-OutFile` and `-o` are the inverse of
`-InFile` and `-d @`, and confusing them would flag most of what the agent does.
Asserted as structured tool calls rather than through the free-text corpus,
because a bare command string has no declared tool and escalates for an
unrelated reason.

Replayed against 23 real decisions from today: all still allow.

Known limit, stated in the module: an agent that writes a script and runs it
matches no one-liner shape. This raises the cost of the easy path; it is not a
boundary. Keeping credentials out of files the agent can read is worth more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nayfly
nayfly merged commit e3c0301 into main Aug 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant