Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request enhances lockdown mode to allow content from trusted bots (dependabot, github-actions, github-copilot) to bypass content filtering. The changes add a ViewerType field to track whether the GitHub API viewer is a Bot, and implement a isTrustedBot() check with a hardcoded list of trusted bot logins.
Key changes:
- Added
ViewerTypefield to track the__typenamefrom GitHub's GraphQL API - Added
trustedBotLoginsmap with hardcoded trusted bot identifiers - Modified
IsSafeContent()to check for trusted bots before filtering content
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pkg/lockdown/lockdown.go | Added ViewerType field, trustedBotLogins map, isTrustedBot() method, and modified IsSafeContent() to check trusted bots; updated GraphQL query to fetch __typename |
| pkg/lockdown/lockdown_test.go | Updated test mocks and assertions to include ViewerType field with value "User" |
7f851b4 to
869c024
Compare
869c024 to
8400964
Compare
| }, nil | ||
| } | ||
|
|
||
| c.logDebug("repo access cache miss", "owner", owner, "repo", repo, "user", username) |
There was a problem hiding this comment.
why you decided to remove attributes?
SamMorrowDrums
left a comment
There was a problem hiding this comment.
That seems ok. I think there's no easy way to do this other than string matching.
Could always allow a trusted user/bot arg so you can allow exceptions with intention. Like comma separated list of names or something.
| logger *slog.Logger | ||
| client *githubv4.Client | ||
| mu sync.Mutex | ||
| cache *cache2go.CacheTable |
There was a problem hiding this comment.
It's possible if it's expensive enough we might want to use redis or memcached on remote server, do you have a solution in mind for that?
There was a problem hiding this comment.
Yes, I was thinking of that, or even creating an adapter for the local server. Generally using Redis in the remote server would be the next logical step.
Two main aspects that will guide enhancing this mode are
- lockdown mode becomes popular and
- if the memory burden on maintaining this cache with TTL is too high (but I need to analyse usage patterns to be 100% sure, my gut feeling is that typical user won't be scanning thousands of repos)
pkg/lockdown/lockdown.go
Outdated
| } | ||
| if repoInfo.IsPrivate || repoInfo.ViewerLogin == username { | ||
|
|
||
| c.logInfo(ctx, fmt.Sprintf("evaluated repo access fur user %s to %s/%s for content filtering, result: hasPushAccess=%t, isPrivate=%t", |
There was a problem hiding this comment.
Does this logger hook into MCP logging because log output shows up like an error with MCP servers using stdio, and I think you can instead send server log messages explicitly.
Also you can log to stderr (at least the docs from MCP debugging in VS Code say that's better.
It looks like this is logging to stdio unless I missed something.
There was a problem hiding this comment.
That should be sufficient.
| func (c *RepoAccessCache) IsSafeContent(ctx context.Context, username, owner, repo string) (bool, error) { | ||
| repoInfo, err := c.getRepoAccessInfo(ctx, username, owner, repo) | ||
| if err != nil { | ||
| c.logDebug("error checking repo access info for content filtering", "owner", owner, "repo", repo, "user", username, "error", err) | ||
| return false, err | ||
| } | ||
| if repoInfo.IsPrivate || repoInfo.ViewerLogin == username { | ||
|
|
||
| c.logDebug(ctx, fmt.Sprintf("evaluated repo access for user %s to %s/%s for content filtering, result: hasPushAccess=%t, isPrivate=%t", | ||
| username, owner, repo, repoInfo.HasPushAccess, repoInfo.IsPrivate)) | ||
|
|
||
| if c.isTrustedBot(username) || repoInfo.IsPrivate || repoInfo.ViewerLogin == strings.ToLower(username) { | ||
| return true, nil | ||
| } | ||
| return repoInfo.HasPushAccess, nil |
There was a problem hiding this comment.
The trusted bot check should be performed before calling getRepoAccessInfo to avoid an unnecessary API query for trusted bots. Currently, the function fetches repo access information first (which may involve a GraphQL API call), then checks if the user is a trusted bot. This wastes API quota and adds latency for bot accounts.
Consider moving the trusted bot check to the beginning:
func (c *RepoAccessCache) IsSafeContent(ctx context.Context, username, owner, repo string) (bool, error) {
if c.isTrustedBot(username) {
return true, nil
}
repoInfo, err := c.getRepoAccessInfo(ctx, username, owner, repo)
if err != nil {
return false, err
}
// ... rest of the logic
}There was a problem hiding this comment.
This sounds reasonable
| // - the author currently has push access to the repository; | ||
| // - the repository is private; | ||
| // - the content was created by the viewer. |
There was a problem hiding this comment.
The documentation lists the conditions in a different order than they are checked in the code. The comment states:
- trusted bot
- push access
- private repo
- viewer matches username
But the code checks:
- trusted bot
- private repo
- viewer matches username
- push access
For clarity and maintainability, the documentation should match the code order. Consider updating the comment to:
// IsSafeContent determines if the specified user can safely access the requested repository content.
// Safe access applies when any of the following is true:
// - the content was created by a trusted bot;
// - the repository is private;
// - the content was created by the viewer;
// - the author currently has push access to the repository.| // - the author currently has push access to the repository; | |
| // - the repository is private; | |
| // - the content was created by the viewer. | |
| // - the repository is private; | |
| // - the content was created by the viewer; | |
| // - the author currently has push access to the repository. |
| func (c *RepoAccessCache) isTrustedBot(username string) bool { | ||
| _, ok := c.trustedBotLogins[strings.ToLower(username)] | ||
| return ok | ||
| } |
There was a problem hiding this comment.
The new trusted bot functionality lacks test coverage. Since other functions in this package have tests (e.g., TestRepoAccessCacheEvictsAfterTTL), the new behavior should also be tested.
Consider adding test cases for:
- Verifying that "copilot" (case-insensitive) is recognized as a trusted bot
- Ensuring
IsSafeContentreturnstruefor trusted bots without querying the API - Testing that non-trusted usernames still trigger the normal access checks
LuluBeatson
left a comment
There was a problem hiding this comment.
Looks good!
Only minor things are: checking isTrustedBot before getRepoAccessInfo, test coverage
Thanks - I will address your feedback in a follow up pr ❤️ |


Lockdown mode improvement: if the author is trusted bot, don't filter out content. For now the list of trusted bots is hardcoded but it can easily be configurable if needed.