Conversation
Adds application-level audit trail for the MCP server so a downstream host can spot-check what yactt reads, where it rooted, and whether the running binary matches the install hook's TOFU record. - structured startup line on stderr (event=startup): resolved root, MaxFiles cap, loaded file count, grammar set, per-language LSP presence + version, binary SHA-256. - opt-in per-tool audit via --audit-log=<path>: one JSON line per tools/call with tool name, input paths (extracted from common field names + absolute-path heuristic), output bytes, duration, is_error. - runtime TOFU assertion: reads install hook's known-good file at XDG_DATA_HOME/yactt/known-good and warns on stderr when the running binary's SHA-256 diverges from the recorded hash at the same version (silent on version mismatch / missing TOFU / dev builds). - documents the audit story in docs/security.md §6 + README.md Security section + plugins/yactt/README.md trust section.
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.
Summary
Closes #3 — adds application-level audit trail for the MCP server so a downstream host can spot-check what yactt reads, where it rooted, and whether the running binary matches the install hook's TOFU record.
What's in this PR
Four AST09 mitigations, mirroring the layout of the prior AST02 (#1) and AST05 (#2) close-outs:
Structured startup line on stderr (
event=startup). Always emitted. Carries the resolved absolute root,MaxFilescap, loaded file count, grammar set, per-language LSP presence + tool + version, and the running binary's SHA-256. Thebinary_sha256field is the runtime anchor for the install-hook trust chain — a downstream host can cross-check it against the publishedSHA256SUMSfor the running release.Opt-in per-tool audit via
--audit-log=<path>. Writes one JSON line pertools/callto the file (mode 0600, append). Each line carries the tool name, every path discovered in the input JSON (via a narrow heuristic that recognisesrepo/file/scope/file_filterfield names plus POSIX/Windows absolute paths), output byte count, wall-clock duration, andis_error.internal/mcp/server.go::dispatchtimes the handler; the server depends only on a tiny unexported interface sointernal/auditstays free of MCP imports.Install-hook runtime TOFU assertion.
cmd/yactt/main.go::warnInstallTrustChainreads${XDG_DATA_HOME:-~/.local/share}/yactt/known-good(the fileinstall.shalready writes) and compares the recorded(version, sha256)against the running binary's hash. A mismatch writes aWARNING:line on stderr identifying recorded, actual, and version, then continues (a compromised install is surfaced, not silently run). Silent ondevbuilds, missing TOFU, and version mismatches (legitimate upgrades).Audit story in
docs/security.md— new §6 walks the threat, the four mitigations, what they don't defend against, and the test-coverage anchors. README.md Security section +plugins/yactt/README.mdupdated to reflect AST09 as mitigated and link the audit-log quickstart.Files
internal/audit/audit.go,internal/audit/audit_test.go,cmd/yactt/main_test.go.cmd/yactt/main.go,internal/mcp/server.go,internal/mcp/server_test.go,docs/security.md,README.md,plugins/yactt/README.md.Test coverage
internal/audit/audit_test.go— path-extraction heuristic (relative paths via field-name allowlist, absolute paths via POSIX/Windows shapes, empty-field filtering, sort-stable order), all fourCheckKnownGoodstatus branches (missing/unknown_version/match/mismatch), concurrent emission (Loggeris mutex-guarded), file-backed append (NewFileLoggersurvives repeated opens).internal/mcp/server_test.go— three new tests pinning the dispatch-side contract: one line pertools/call,is_errorset on handler error, clean no-op when no auditor is attached.cmd/yactt/main_test.go— startup snapshot shape, runtime TOFU warning branches, binary path resolution.go vet ./...clean. Full package test suite passes.Smoke test
Live run on
tests/fixtures/sample-gowith gopls on PATH:Stderr (startup line):
{"event":"startup","timestamp":"2026-07-06T06:32:49Z","version":"dev","repo_root":"/…/sample-go","max_files":50000,"loaded_files":4,"grammars":["go","typescript","javascript"],"lsp":[{"language":"go","tool":"gopls","version":"v0.22.0"}, …],"binary_sha256":"6ddda703…"}Audit log (per-tool lines):
{"event":"tool_call","tool":"get_symbols_overview","input_paths":["auth/login.go"], …} {"event":"tool_call","tool":"find_code","input_paths":["/Users/…/proj","src/auth/**/*.go"], …}Out of scope (deliberate)
WithMaxFilesoverride is not surfaced in the startup line'smax_filesfield.loadOptionsis unexported; lifting it would need either a publicProbe()interface onLoadOptionor to exposeloadOptions. Both are heavier than the value today (no caller sets a non-default cap in production). Marked with a// ponytail:comment inbuildStartupInfonaming the upgrade path.(binary, sha256)pair is still installable. The runtime check catches same-version replay; the SLSA L3 attestation (gh attestation verify) documented in §2 is the back-line defense for full supply-chain integrity.