Repository navigation
Releases
capability-gate plugin bundle 0.1.1
Hermes plugin bundle, version 0.1.1.
The bundle holds __init__.py, capability_gate.py, plugin.yaml,
allowlist.example.yaml and a SHA256SUMS over those bytes. Build provenance
is a GitHub SLSA attestation, as in 0.1.0. Verify before you install:
gh attestation verify capability-gate-plugin-0.1.1.zip --repo Steck43/capability-gate
Upgrade notes: read before you install
- Calls with no skill now need an
UNLABELEDgrant. Hermes sends no
skill onpre_tool_call. In 0.1.0 those calls fell to the*grant; in
0.1.1 they resolve toUNLABELEDand are denied unless the allowlist grants
UNLABELEDby name. Add anUNLABELEDentry for the tools your hook
traffic uses. The example allowlist grantsUNLABELEDread_fileand
skills_list. - The config and allowlist files must be private. The adapter refuses
either file when it is a symlink, not a regular file, not owned by the
current user, or writable by group or others (0644loads;0664does
not). A refused config resolves to enforce and blocks every call until it
is fixed. - Relative paths resolve where Hermes writes. A relative path is resolved
against the folder Hermes will use for the call, not the process working
directory. A relative path with no usable base folder is denied. - Path matching uses the real path. A path is resolved before it is
matched, and a path that needs~or$VARexpansion is denied. - YAML is strict. Duplicate keys and merge keys (
<<) in the config or
allowlist are refused at load.
New
- Kill switch.
Gate.throwwrites a marker beside the decision log and
one THROWN row to the chain. Every later call is denied, with no restart,
in this gate and any other gate on the same log. A person clears it by
removing the marker. A marker the gate cannot read is a deny. - Hash-chained decision log. Each row is chained to the one before it by
sha256, with a witness of the head hash and row count. Editing an older
row, cutting the tail or deleting the log is detected, and the next write
is refused.
Fixed
- A planted
secret-canary.txtis denied even when a grant covers its folder. - Denials that happen before the decision (an unresolved mode, a plugin that
fails to load, an adapter exception) still write a decision row. - Two processes cannot fork the log: writes take an exclusive lock.
- A short write to the log rolls back the partial line and raises, instead of
leaving a torn row. - In observe mode, an error inside the gate is recorded as a deny instead of
raising before any row is written. - The adapter reads every path a call carries against a closed argument
schema. Apatchcall's file headers count as paths, so a grantedpatch
cannot write a file outside the grant. A tool with no schema, or an
argument the schema does not list, is denied. - The bundle now includes
__init__.py, so the Hermes entry point is present.
None of these had a CVE or a public advisory. They came from internal review
and testing; each has a regression test in the repository.
Full detail: CHANGELOG.md in the repository, between plugin-v0.1.0 and
plugin-v0.1.1.
capability-gate plugin bundle 0.1.0
Hermes plugin bundle, version 0.1.0.
A signed release of the deterministic allowlist gate: capability_gate.py, plugin.yaml, allowlist.example.yaml, and a SHA256SUMS covering exactly those bytes. This is the plugin as it runs, not a snapshot of the repository, which is why the attestation subject is the bundle, not GitHub's source archive.
Build provenance is attested with SLSA through GitHub's native attestation, signed by the workflow that produced it. You do not have to take that on trust:
gh release download plugin-v0.1.0 --repo Steck43/capability-gate
gh attestation verify capability-gate-plugin-0.1.0.zip --repo Steck43/capability-gate
A clean copy exits 0. Alter a single byte, and the same command fails with no matching subject, which is the property worth having and the reason the check is published alongside the file.
sha256 8e3dc71d37e53a4d9e26ae5a75515e08520f4d9f9526a997a3e88588d9077584