Skip to content

Commit 6162fb0

Browse files
GustedKN4CK3R6543
authored
Check for permission when fetching user controlled issues (go-gitea#20133) (go-gitea#20196)
* Check if project has the same repository id with issue when assign project to issue * Check if issue's repository id match project's repository id * Add more permission checking * Remove invalid argument * Fix errors * Add generic check * Remove duplicated check * Return error + add check for new issues * Apply suggestions from code review Co-authored-by: Gusted <[email protected]> Co-authored-by: KN4CK3R <[email protected]> Co-authored-by: 6543 <[email protected]>
1 parent df0b330 commit 6162fb0

File tree

7 files changed

+83
-29
lines changed

7 files changed

+83
-29
lines changed

models/issue_milestone.go

+16
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ func getMilestoneByRepoID(e db.Engine, repoID, id int64) (*Milestone, error) {
116116
return m, nil
117117
}
118118

119+
// HasMilestoneByRepoID returns if the milestone exists in the repository.
120+
func HasMilestoneByRepoID(repoID, id int64) (bool, error) {
121+
return db.GetEngine(db.DefaultContext).ID(id).Where("repo_id=?", repoID).Exist(new(Milestone))
122+
}
123+
119124
// GetMilestoneByRepoID returns the milestone in a repository.
120125
func GetMilestoneByRepoID(repoID, id int64) (*Milestone, error) {
121126
return getMilestoneByRepoID(db.GetEngine(db.DefaultContext), repoID, id)
@@ -251,6 +256,17 @@ func changeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) err
251256
}
252257

253258
func changeMilestoneAssign(ctx context.Context, doer *user_model.User, issue *Issue, oldMilestoneID int64) error {
259+
// Only check if milestone exists if we don't remove it.
260+
if issue.MilestoneID > 0 {
261+
has, err := HasMilestoneByRepoID(issue.RepoID, issue.MilestoneID)
262+
if err != nil {
263+
return fmt.Errorf("HasMilestoneByRepoID: %v", err)
264+
}
265+
if !has {
266+
return fmt.Errorf("HasMilestoneByRepoID: issue doesn't exist")
267+
}
268+
}
269+
254270
if err := updateIssueCols(ctx, issue, "milestone_id"); err != nil {
255271
return err
256272
}

models/project_issue.go

+11
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U
150150
e := db.GetEngine(ctx)
151151
oldProjectID := issue.projectID(e)
152152

153+
// Only check if we add a new project and not remove it.
154+
if newProjectID > 0 {
155+
newProject, err := GetProjectByID(newProjectID)
156+
if err != nil {
157+
return err
158+
}
159+
if newProject.RepoID != issue.RepoID {
160+
return fmt.Errorf("issue's repository is not the same as project's repository")
161+
}
162+
}
163+
153164
if _, err := e.Where("project_issue.issue_id=?", issue.ID).Delete(&ProjectIssue{}); err != nil {
154165
return err
155166
}

routers/api/v1/repo/pull_review.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ func dismissReview(ctx *context.APIContext, msg string, isDismiss bool) {
883883
return
884884
}
885885

886-
_, err := pull_service.DismissReview(review.ID, msg, ctx.User, isDismiss)
886+
_, err := pull_service.DismissReview(review.ID, ctx.Repo.Repository.ID, msg, ctx.User, isDismiss)
887887
if err != nil {
888888
ctx.Error(http.StatusInternalServerError, "pull_service.DismissReview", err)
889889
return

routers/web/repo/issue.go

+28-20
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,15 @@ const (
5757
issueTemplateTitleKey = "IssueTemplateTitle"
5858
)
5959

60-
var (
61-
// IssueTemplateCandidates issue templates
62-
IssueTemplateCandidates = []string{
63-
"ISSUE_TEMPLATE.md",
64-
"issue_template.md",
65-
".gitea/ISSUE_TEMPLATE.md",
66-
".gitea/issue_template.md",
67-
".github/ISSUE_TEMPLATE.md",
68-
".github/issue_template.md",
69-
}
70-
)
60+
// IssueTemplateCandidates issue templates
61+
var IssueTemplateCandidates = []string{
62+
"ISSUE_TEMPLATE.md",
63+
"issue_template.md",
64+
".gitea/ISSUE_TEMPLATE.md",
65+
".gitea/issue_template.md",
66+
".github/ISSUE_TEMPLATE.md",
67+
".github/issue_template.md",
68+
}
7169

7270
// MustAllowUserComment checks to make sure if an issue is locked.
7371
// If locked and user has permissions to write to the repository,
@@ -245,7 +243,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
245243
}
246244
}
247245

248-
var issueList = models.IssueList(issues)
246+
issueList := models.IssueList(issues)
249247
approvalCounts, err := issueList.GetApprovalCounts()
250248
if err != nil {
251249
ctx.ServerError("ApprovalCounts", err)
@@ -311,8 +309,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
311309
assigneeID = 0 // Reset ID to prevent unexpected selection of assignee.
312310
}
313311

314-
ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] =
315-
issue_service.GetRefEndNamesAndURLs(issues, ctx.Repo.RepoLink)
312+
ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, ctx.Repo.RepoLink)
316313

317314
ctx.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 {
318315
counts, ok := approvalCounts[issueID]
@@ -442,7 +439,6 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
442439
}
443440

444441
func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
445-
446442
var err error
447443

448444
ctx.Data["OpenProjects"], _, err = models.GetProjects(models.ProjectSearchOptions{
@@ -796,7 +792,8 @@ func NewIssue(ctx *context.Context) {
796792
body := ctx.FormString("body")
797793
ctx.Data["BodyQuery"] = body
798794

799-
ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeProjects)
795+
isProjectsEnabled := ctx.Repo.CanRead(unit.TypeProjects)
796+
ctx.Data["IsProjectsEnabled"] = isProjectsEnabled
800797
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
801798
upload.AddUploadContext(ctx, "comment")
802799

@@ -812,7 +809,7 @@ func NewIssue(ctx *context.Context) {
812809
}
813810

814811
projectID := ctx.FormInt64("project")
815-
if projectID > 0 {
812+
if projectID > 0 && isProjectsEnabled {
816813
project, err := models.GetProjectByID(projectID)
817814
if err != nil {
818815
log.Error("GetProjectByID: %d: %v", projectID, err)
@@ -1017,6 +1014,12 @@ func NewIssuePost(ctx *context.Context) {
10171014
}
10181015

10191016
if projectID > 0 {
1017+
if !ctx.Repo.CanRead(unit.TypeProjects) {
1018+
// User must also be able to see the project.
1019+
ctx.Error(http.StatusBadRequest, "user hasn't permissions to read projects")
1020+
return
1021+
}
1022+
10201023
if err := models.ChangeProjectAssign(issue, ctx.User, projectID); err != nil {
10211024
ctx.ServerError("ChangeProjectAssign", err)
10221025
return
@@ -1713,6 +1716,11 @@ func getActionIssues(ctx *context.Context) []*models.Issue {
17131716
issueUnitEnabled := ctx.Repo.CanRead(unit.TypeIssues)
17141717
prUnitEnabled := ctx.Repo.CanRead(unit.TypePullRequests)
17151718
for _, issue := range issues {
1719+
if issue.RepoID != ctx.Repo.Repository.ID {
1720+
ctx.NotFound("some issue's RepoID is incorrect", errors.New("some issue's RepoID is incorrect"))
1721+
return nil
1722+
}
1723+
17161724
if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
17171725
ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil)
17181726
return nil
@@ -2515,7 +2523,7 @@ func filterXRefComments(ctx *context.Context, issue *models.Issue) error {
25152523
// GetIssueAttachments returns attachments for the issue
25162524
func GetIssueAttachments(ctx *context.Context) {
25172525
issue := GetActionIssue(ctx)
2518-
var attachments = make([]*api.Attachment, len(issue.Attachments))
2526+
attachments := make([]*api.Attachment, len(issue.Attachments))
25192527
for i := 0; i < len(issue.Attachments); i++ {
25202528
attachments[i] = convert.ToReleaseAttachment(issue.Attachments[i])
25212529
}
@@ -2529,7 +2537,7 @@ func GetCommentAttachments(ctx *context.Context) {
25292537
ctx.NotFoundOrServerError("GetCommentByID", models.IsErrCommentNotExist, err)
25302538
return
25312539
}
2532-
var attachments = make([]*api.Attachment, 0)
2540+
attachments := make([]*api.Attachment, 0)
25332541
if comment.Type == models.CommentTypeComment {
25342542
if err := comment.LoadAttachments(); err != nil {
25352543
ctx.ServerError("LoadAttachments", err)
@@ -2674,7 +2682,7 @@ func handleTeamMentions(ctx *context.Context) {
26742682
var isAdmin bool
26752683
var err error
26762684
var teams []*models.Team
2677-
var org = models.OrgFromUser(ctx.Repo.Owner)
2685+
org := models.OrgFromUser(ctx.Repo.Owner)
26782686
// Admin has super access.
26792687
if ctx.User.IsAdmin {
26802688
isAdmin = true

routers/web/repo/projects.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package repo
66

77
import (
8+
"errors"
89
"fmt"
910
"net/http"
1011
"net/url"
@@ -531,7 +532,6 @@ func EditProjectBoard(ctx *context.Context) {
531532

532533
// SetDefaultProjectBoard set default board for uncategorized issues/pulls
533534
func SetDefaultProjectBoard(ctx *context.Context) {
534-
535535
project, board := checkProjectBoardChangePermissions(ctx)
536536
if ctx.Written() {
537537
return
@@ -631,10 +631,17 @@ func MoveIssues(ctx *context.Context) {
631631
}
632632

633633
if len(movedIssues) != len(form.Issues) {
634-
ctx.ServerError("IssuesNotFound", err)
634+
ctx.ServerError("some issues do not exist", errors.New("some issues do not exist"))
635635
return
636636
}
637637

638+
for _, issue := range movedIssues {
639+
if issue.RepoID != project.RepoID {
640+
ctx.ServerError("Some issue's repoID is not equal to project's repoID", errors.New("Some issue's repoID is not equal to project's repoID"))
641+
return
642+
}
643+
}
644+
638645
if err = models.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil {
639646
ctx.ServerError("MoveIssuesOnProjectBoard", err)
640647
return

routers/web/repo/pull_review.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package repo
66

77
import (
8+
"errors"
89
"fmt"
910
"net/http"
1011

@@ -116,6 +117,11 @@ func UpdateResolveConversation(ctx *context.Context) {
116117
return
117118
}
118119

120+
if comment.Issue.RepoID != ctx.Repo.Repository.ID {
121+
ctx.NotFound("comment's repoID is incorrect", errors.New("comment's repoID is incorrect"))
122+
return
123+
}
124+
119125
var permResult bool
120126
if permResult, err = models.CanMarkConversation(comment.Issue, ctx.User); err != nil {
121127
ctx.ServerError("CanMarkConversation", err)
@@ -234,7 +240,7 @@ func SubmitReview(ctx *context.Context) {
234240
// DismissReview dismissing stale review by repo admin
235241
func DismissReview(ctx *context.Context) {
236242
form := web.GetForm(ctx).(*forms.DismissReviewForm)
237-
comm, err := pull_service.DismissReview(form.ReviewID, form.Message, ctx.User, true)
243+
comm, err := pull_service.DismissReview(form.ReviewID, ctx.Repo.Repository.ID, form.Message, ctx.User, true)
238244
if err != nil {
239245
ctx.ServerError("pull_service.DismissReview", err)
240246
return

services/pull/review.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.
271271
}
272272

273273
// DismissReview dismissing stale review by repo admin
274-
func DismissReview(reviewID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
274+
func DismissReview(reviewID, repoID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
275275
review, err := models.GetReviewByID(reviewID)
276276
if err != nil {
277277
return
@@ -281,6 +281,16 @@ func DismissReview(reviewID int64, message string, doer *user_model.User, isDism
281281
return nil, fmt.Errorf("not need to dismiss this review because it's type is not Approve or change request")
282282
}
283283

284+
// load data for notify
285+
if err = review.LoadAttributes(); err != nil {
286+
return nil, err
287+
}
288+
289+
// Check if the review's repoID is the one we're currently expecting.
290+
if review.Issue.RepoID != repoID {
291+
return nil, fmt.Errorf("reviews's repository is not the same as the one we expect")
292+
}
293+
284294
if err = models.DismissReview(review, isDismiss); err != nil {
285295
return
286296
}
@@ -289,10 +299,6 @@ func DismissReview(reviewID int64, message string, doer *user_model.User, isDism
289299
return nil, nil
290300
}
291301

292-
// load data for notify
293-
if err = review.LoadAttributes(); err != nil {
294-
return
295-
}
296302
if err = review.Issue.LoadPullRequest(); err != nil {
297303
return
298304
}

0 commit comments

Comments
 (0)