feat(agentDir): enforce registry permission manifest at load and run time - #386
Merged
Merged
Conversation
…time (#272) The lousho add receipt (M7a) is now verified when an agent directory loads and enforced while its tools run, instead of being install-time documentation only. - verifyReceipt re-hashes every receipt file; an item with edited or missing files is 'unattested': a warning names the item and files, and manifest.registry reports the same. Loading is never refused - the files are the owner's to edit. - confineToolsToReceipt binds each receipt item's tools to the manifest accepted at install: exec/needsApproval items - and any unattested item - always ask for approval (a tool's own deny still denies); fetch is limited to the declared network hosts; process.env shows only the declared env names; a requiresSandbox tool gets a narrowed adapter (run() refused without exec, writeFile() without filesystem write, command env of the non-secret base plus declared variables only). Ambient fetch/env guards run under AsyncLocalStorage so unrelated code is untouched. - The envelope stays as narrow as the last accepted manifest until 'lousho add <name> --overwrite' attests the current files, so a post-install edit adding network or exec use is surfaced and refused. Closes #272
LinuxDevil
force-pushed
the
fix/lou-s7-registry-manifest
branch
from
October 4, 2026 09:03
76eeb9a to
12d829a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #272
What
Extends the M7a registry permission-manifest work from install-time static enforcement to load-time and run-time enforcement. The
lousho-registry.jsonreceipt written bylousho addis no longer ambient authorization — it is evidence tied to the installed artifact, re-verified against the files actually loaded.How
src/agentDir/registryEnforce.ts(new):verifyReceipt(dir)reads the receipt and re-hashes every recorded file (sha256, same scheme asaddReceipt.ts). An item whose files changed or went missing isunattested; a missing/unparseable receipt is reported, never thrown.registryWarnings()produces one warning per unattested item naming the item and the modified/missing files.confineToolsToReceipt()wraps every tool whose source file a receipt item owns so calls run inside the manifest accepted at install:exec: trueorneedsApproval: trueitems — and any unattested item — always wait for approval (a tool's owndenystill denies; approval is the channel that surfaces stale code).fetchwhile the tool runs is limited to the declarednetworkhost patterns (matchesHost); an item with nonetworkcannot fetch at all.process.envwhile the tool runs shows only the declaredenvnames.requiresSandboxtool gets a narrowedSandboxAdapter:run()refused withoutexec,writeFile()withoutfilesystem: "write", and command env = the SDK's non-secret base plus declared variables only (commandEnv).fetch/process.envguards are scoped per call viaAsyncLocalStorage, so unrelated code and the SDK's own env use are untouched. Async-generator (isPartialStream) results are confined pernext().loadAgentDir.ts:resolveWithverifies the receipt before loading tools, prints the warnings, confines the loaded tools, and reports the result onmanifest.registry(newRegistryStatus/RegistryItemStatus/Attestationtypes, exported viaagentDir/index.ts).lousho add <name> --overwritere-attests the current files.Adversarial case covered
Install an item declaring no
network/exec, then edit its tool file to callfetchand a sandboxedrun(): the load reports the item unattested, its calls now require approval, the fetch is refused (declares no network access), andsandbox.run()throws without declaredexec.Limits (documented)
In-process guards intercept
fetchandprocess.envonly — nothttp/net/axios, the filesystem, module-scope captures, or a container's own network policy. The manifest is not a sandbox; this is stated in docs/registry.md.Tests
src/agentDir/registryEnforce.test.ts: 14 tests — receipt parse/read errors, attested vs modified/missing reporting, valid receipt doesn't block load, approval forexec/needsApproval/unattested items (incl. owndenypreserved), fetch allow/refuse, env filtering, sandbox adapter narrowing, and the modified-after-install adversarial flow.registryEnforce.test.ts(14) +add.test.ts(46) +loadAgentDir.test.ts(18) = 78 pass; broader related run earlier: 100 pass / 8 files.npm run lint✅npm run typecheck✅npm run build✅docs:verify-snippets --skip-build✅ (258 snippets)docs:llmsregenerated.npm run typecheck:testshas pre-existing failures across unrelated test files on main; the new test file itself is clean.Docs
docs/registry.md: permission-manifest section now covers load-time integrity, runtime approval/network/env/sandbox enforcement, the re-attestation path, and the confinement's limits.docs/agent-directories.md:manifest.registryonresolveAgentDir().CHANGELOG.md: Unreleased Security entry;llms.txt/llms-full.txtregenerated.