From 6551e6a91d247d2a5fd82f6a41cbb1804e486fa2 Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 1 Apr 2026 21:22:30 +0000 Subject: [PATCH] fix(api): reject malformed workflow requests --- pkg/api/provider.go | 8 +++++++- pkg/api/provider_test.go | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/api/provider.go b/pkg/api/provider.go index 8e4b07e..7b372a6 100644 --- a/pkg/api/provider.go +++ b/pkg/api/provider.go @@ -6,6 +6,8 @@ package api import ( + "errors" + stdio "io" "io/fs" "net/http" @@ -545,7 +547,11 @@ func (p *BuildProvider) generateReleaseWorkflow(c *gin.Context) { var req releaseWorkflowRequest if err := c.ShouldBindJSON(&req); err != nil { - req.Path = "" + // Empty bodies are valid; malformed JSON is not. + if !errors.Is(err, stdio.EOF) { + c.JSON(http.StatusBadRequest, api.Fail("invalid_request", err.Error())) + return + } } path := req.Path diff --git a/pkg/api/provider_test.go b/pkg/api/provider_test.go index cf2d019..d86a4cc 100644 --- a/pkg/api/provider_test.go +++ b/pkg/api/provider_test.go @@ -257,6 +257,28 @@ func TestProvider_GenerateReleaseWorkflow_OutputAlias_Good(t *testing.T) { assert.Contains(t, content, "workflow_dispatch:") } +func TestProvider_GenerateReleaseWorkflow_InvalidJSON_Bad(t *testing.T) { + gin.SetMode(gin.TestMode) + + projectDir := t.TempDir() + p := NewProvider(projectDir, nil) + + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/release/workflow", bytes.NewBufferString(`{"path":`)) + request.Header.Set("Content-Type", "application/json") + + ctx, _ := gin.CreateTestContext(recorder) + ctx.Request = request + + p.generateReleaseWorkflow(ctx) + + assert.Equal(t, http.StatusBadRequest, recorder.Code) + + path := build.ReleaseWorkflowPath(projectDir) + _, err := io.Local.Read(path) + assert.Error(t, err) +} + func TestProvider_DiscoverProject_Good(t *testing.T) { gin.SetMode(gin.TestMode)