mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Fix url validation in webhook add/edit API (#34492)
This commit is contained in:
		| @@ -15,6 +15,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
|  | 	"code.gitea.io/gitea/modules/validation" | ||||||
| 	webhook_module "code.gitea.io/gitea/modules/webhook" | 	webhook_module "code.gitea.io/gitea/modules/webhook" | ||||||
| 	"code.gitea.io/gitea/services/context" | 	"code.gitea.io/gitea/services/context" | ||||||
| 	webhook_service "code.gitea.io/gitea/services/webhook" | 	webhook_service "code.gitea.io/gitea/services/webhook" | ||||||
| @@ -92,6 +93,10 @@ func checkCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) | |||||||
| 		ctx.APIError(http.StatusUnprocessableEntity, "Invalid content type") | 		ctx.APIError(http.StatusUnprocessableEntity, "Invalid content type") | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  | 	if !validation.IsValidURL(form.Config["url"]) { | ||||||
|  | 		ctx.APIError(http.StatusUnprocessableEntity, "Invalid url") | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -324,6 +329,10 @@ func EditRepoHook(ctx *context.APIContext, form *api.EditHookOption, hookID int6 | |||||||
| func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webhook) bool { | func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webhook) bool { | ||||||
| 	if form.Config != nil { | 	if form.Config != nil { | ||||||
| 		if url, ok := form.Config["url"]; ok { | 		if url, ok := form.Config["url"]; ok { | ||||||
|  | 			if !validation.IsValidURL(url) { | ||||||
|  | 				ctx.APIError(http.StatusUnprocessableEntity, "Invalid url") | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
| 			w.URL = url | 			w.URL = url | ||||||
| 		} | 		} | ||||||
| 		if ct, ok := form.Config["content_type"]; ok { | 		if ct, ok := form.Config["content_type"]; ok { | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								routers/api/v1/utils/hook_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								routers/api/v1/utils/hook_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | // Copyright 2025 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package utils | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/models/unittest" | ||||||
|  | 	"code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/services/contexttest" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestTestHookValidation(t *testing.T) { | ||||||
|  | 	unittest.PrepareTestEnv(t) | ||||||
|  |  | ||||||
|  | 	t.Run("Test Validation", func(t *testing.T) { | ||||||
|  | 		ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/hooks") | ||||||
|  | 		contexttest.LoadRepo(t, ctx, 1) | ||||||
|  | 		contexttest.LoadRepoCommit(t, ctx) | ||||||
|  | 		contexttest.LoadUser(t, ctx, 2) | ||||||
|  |  | ||||||
|  | 		checkCreateHookOption(ctx, &structs.CreateHookOption{ | ||||||
|  | 			Type: "gitea", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"content_type": "json", | ||||||
|  | 				"url":          "https://example.com/webhook", | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 		assert.Equal(t, 0, ctx.Resp.WrittenStatus()) // not written yet | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test Validation with invalid URL", func(t *testing.T) { | ||||||
|  | 		ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/hooks") | ||||||
|  | 		contexttest.LoadRepo(t, ctx, 1) | ||||||
|  | 		contexttest.LoadRepoCommit(t, ctx) | ||||||
|  | 		contexttest.LoadUser(t, ctx, 2) | ||||||
|  |  | ||||||
|  | 		checkCreateHookOption(ctx, &structs.CreateHookOption{ | ||||||
|  | 			Type: "gitea", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"content_type": "json", | ||||||
|  | 				"url":          "example.com/webhook", | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 		assert.Equal(t, http.StatusUnprocessableEntity, ctx.Resp.WrittenStatus()) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test Validation with invalid webhook type", func(t *testing.T) { | ||||||
|  | 		ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/hooks") | ||||||
|  | 		contexttest.LoadRepo(t, ctx, 1) | ||||||
|  | 		contexttest.LoadRepoCommit(t, ctx) | ||||||
|  | 		contexttest.LoadUser(t, ctx, 2) | ||||||
|  |  | ||||||
|  | 		checkCreateHookOption(ctx, &structs.CreateHookOption{ | ||||||
|  | 			Type: "unknown", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"content_type": "json", | ||||||
|  | 				"url":          "example.com/webhook", | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 		assert.Equal(t, http.StatusUnprocessableEntity, ctx.Resp.WrittenStatus()) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test Validation with empty content type", func(t *testing.T) { | ||||||
|  | 		ctx, _ := contexttest.MockAPIContext(t, "user2/repo1/hooks") | ||||||
|  | 		contexttest.LoadRepo(t, ctx, 1) | ||||||
|  | 		contexttest.LoadRepoCommit(t, ctx) | ||||||
|  | 		contexttest.LoadUser(t, ctx, 2) | ||||||
|  |  | ||||||
|  | 		checkCreateHookOption(ctx, &structs.CreateHookOption{ | ||||||
|  | 			Type: "unknown", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"url": "https://example.com/webhook", | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 		assert.Equal(t, http.StatusUnprocessableEntity, ctx.Resp.WrittenStatus()) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								routers/api/v1/utils/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								routers/api/v1/utils/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // Copyright 2018 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package utils | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/models/unittest" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | 	webhook_service "code.gitea.io/gitea/services/webhook" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestMain(m *testing.M) { | ||||||
|  | 	unittest.MainTest(m, &unittest.TestOptions{ | ||||||
|  | 		SetUp: func() error { | ||||||
|  | 			setting.LoadQueueSettings() | ||||||
|  | 			return webhook_service.Init() | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user