@@ -701,7 +701,7 @@ Options are:
701701 result , err := GetSubIssues (ctx , client , deps , owner , repo , issueNumber , pagination )
702702 return attachIFC (result ), nil , err
703703 case "get_parent" :
704- result , err := GetIssueParent (ctx , gqlClient , owner , repo , issueNumber )
704+ result , err := GetIssueParent (ctx , gqlClient , deps , owner , repo , issueNumber )
705705 return attachIFC (result ), nil , err
706706 case "get_labels" :
707707 result , err := GetIssueLabels (ctx , gqlClient , owner , repo , issueNumber )
@@ -900,18 +900,31 @@ func GetSubIssues(ctx context.Context, client *github.Client, deps ToolDependenc
900900 return utils .NewToolResultText (string (r )), nil
901901}
902902
903- // GetIssueParent returns the parent issue of the given issue, or a null parent
904- // when the issue is not a sub-issue of any other issue. It reads the GraphQL
905- // Issue.parent field, the upward counterpart to the downward get_sub_issues read.
906- func GetIssueParent (ctx context.Context , client * githubv4.Client , owner string , repo string , issueNumber int ) (* mcp.CallToolResult , error ) {
903+ // GetIssueParent returns the parent issue of the given issue, or a null
904+ // parent when the issue is not a sub-issue. It reads the GraphQL
905+ // Issue.parent field, the upward counterpart to get_sub_issues.
906+ //
907+ // The parent title is always sanitized (it may be cross-repo). Under
908+ // lockdown mode the parent is only returned when its author has push
909+ // access to the parent repo (mirroring GetIssue); otherwise it is omitted.
910+ func GetIssueParent (ctx context.Context , client * githubv4.Client , deps ToolDependencies , owner string , repo string , issueNumber int ) (* mcp.CallToolResult , error ) {
911+ cache , err := deps .GetRepoAccessCache (ctx )
912+ if err != nil {
913+ return nil , fmt .Errorf ("failed to get repo access cache: %w" , err )
914+ }
915+ flags := deps .GetFlags (ctx )
916+
907917 var query struct {
908918 Repository struct {
909919 Issue struct {
910920 Parent * struct {
911- Number githubv4.Int
912- Title githubv4.String
913- State githubv4.String
914- URL githubv4.String
921+ Number githubv4.Int
922+ Title githubv4.String
923+ State githubv4.String
924+ URL githubv4.String
925+ Author struct {
926+ Login githubv4.String
927+ }
915928 Repository struct {
916929 NameWithOwner githubv4.String
917930 }
@@ -935,10 +948,27 @@ func GetIssueParent(ctx context.Context, client *githubv4.Client, owner string,
935948 return MarshalledTextResult (map [string ]any {"parent" : nil }), nil
936949 }
937950
951+ if flags .LockdownMode {
952+ if cache == nil {
953+ return nil , fmt .Errorf ("lockdown cache is not configured" )
954+ }
955+ // Fail closed: omit the parent if anything needed for the safe-content
956+ // check is missing or unverifiable.
957+ parentAuthorLogin := string (parent .Author .Login )
958+ parentOwner , parentRepo , ok := strings .Cut (string (parent .Repository .NameWithOwner ), "/" )
959+ if parentAuthorLogin == "" || ! ok || parentOwner == "" || parentRepo == "" {
960+ return MarshalledTextResult (map [string ]any {"parent" : nil }), nil
961+ }
962+ isSafeContent , err := cache .IsSafeContent (ctx , parentAuthorLogin , parentOwner , parentRepo )
963+ if err != nil || ! isSafeContent {
964+ return MarshalledTextResult (map [string ]any {"parent" : nil }), nil
965+ }
966+ }
967+
938968 return MarshalledTextResult (map [string ]any {
939969 "parent" : map [string ]any {
940970 "number" : int (parent .Number ),
941- "title" : string (parent .Title ),
971+ "title" : sanitize . Sanitize ( string (parent .Title ) ),
942972 "state" : string (parent .State ),
943973 "url" : string (parent .URL ),
944974 "repository" : string (parent .Repository .NameWithOwner ),
0 commit comments