security(github): filter list_issues by trusted author_association (Closes #178) - #187
Merged
Conversation
This was referenced Jul 28, 2026
Owner
Author
Superintendentによるレビュー(PR #187, Issue #178)
差分の内容確認
懸念点
推奨実装はIssueの受け入れ条件を過不足なく満たしており、安全側のデフォルト設計も適切です。人間による承認後のマージを推奨します。マージ時はREQ-015番号衝突の解消をお願いします。 |
This was referenced Jul 28, 2026
ytnobody
force-pushed
the
hermit/ytnobody/issue-178
branch
from
July 28, 2026 02:55
6aa1f99 to
b461163
Compare
…loses #178) HERMIT can run against public repositories, where anyone can open an Issue whose body is then handed to an Engineer running locally with broad tool access (Bash(*) among it). Nothing previously verified the author of an Issue before letting it reach that pipeline. ListOpenIssues/ListAllIssues now drop any Issue whose GitHub author_association is not in a trusted allowlist before returning it, so untrusted Issues never reach assign_issue/create_worktree via list_issues. The allowlist defaults to OWNER/MEMBER/COLLABORATOR and is configurable via harness.toml's new [security] trusted_author_associations, but an absent or empty config resolves to that same safe default rather than falling back to "allow everyone". Excluded issues are logged, not silently dropped. Assumption: association filtering happens once, in the internal/github client layer that all list_issues call paths (single-repo and multi-repo) already funnel through, rather than in internal/mcp or internal/readiness — this keeps a single point of enforcement and requires no interface changes in internal/mcp's githubClient consumer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ytnobody
force-pushed
the
hermit/ytnobody/issue-178
branch
from
July 28, 2026 02:56
b461163 to
568d435
Compare
Owner
Author
|
|
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
Bash(*)among it). Nothing previously verified the Issue author before it reached that pipeline.ListOpenIssues/ListAllIssues(internal/github/client.go) now filter out any Issue whose GitHubauthor_associationis not in a trusted allowlist, via a new(*Client).isTrustedAuthorcheck applied insidelistOpenIssuesFromRepo— the single call path both single-repo and multi-repo modes funnel through.gh.DefaultTrustedAuthorAssociations):OWNER,MEMBER,COLLABORATORonly.CONTRIBUTOR/FIRST_TIME_CONTRIBUTOR/NONEare excluded by default.harness.toml[security] trusted_author_associationskey (cmd/hermit/main.goConfig.Security), wired into bothcmdServeandcmdDryRunviaclient.SetTrustedAuthorAssociations(...). An absent or empty config resolves to the same safe default — there is no configuration path that means "allow everyone."log.Printf(security: excluding issue #N in owner/repo ...: author_association="..." is not in the trusted allowlist).list_issues(internal/mcp/tools.go) only ever queues whatListOpenIssues/ListAllIssuesreturn, excluded Issues automatically never reachassign_issue/create_worktree— no changes needed ininternal/mcp.REQ-017toREQUIREMENTS.mdandTestREQ017_*tests ininternal/github/req_test.gocovering: default-safe-allowlist-when-unconfigured, empty-config-does-not-mean-allow-everyone, custom-allowlist-is-honored (case-insensitively), multi-repo filtering, and that theAuthorAssociationfield is populated on surviving Issues.internal/githubtests (multi_repo_test.go,req_test.go) that assert real Issues surviveListOpenIssues/ListAllIssuesto include anauthor_associationin their fixtures, since the new default-deny behavior would otherwise filter them out.README.md(new "Trusted Issue Authors" section) andcmd/hermit/templates/harness.toml.tmpl.Assumptions
internal/githubclient layer, rather than ininternal/mcporinternal/readiness— this keeps a single point of enforcement and requires no interface changes ininternal/mcp'sgithubClientconsumer or its extensive existing test suite (which uses a fake in-memory implementation of that interface, unaffected by this change).Bash(*)permission is tracked separately in Engineer の Bash を allowlist ではなくサンドボックスで制限する(hermit init / doctor / README) #180.Test plan
go build ./...go vet ./...go test ./...(all packages pass, including newTestREQ017_*tests)Closes #178