diff --git a/checks/raw/dangerous_workflow.go b/checks/raw/dangerous_workflow.go index 1d8f5ca794f..6dfb232a68f 100644 --- a/checks/raw/dangerous_workflow.go +++ b/checks/raw/dangerous_workflow.go @@ -45,8 +45,12 @@ func containsUntrustedContextPattern(variable string) bool { `head_commit\.message|` + `head_commit\.author\.email|` + `head_commit\.author\.name|` + + `head_commit\.committer\.email|` + + `head_commit\.committer\.name|` + `commits.*\.author\.email|` + `commits.*\.author\.name|` + + `commits.*\.committer\.email|` + + `commits.*\.committer\.name|` + `blocked_user\.name|` + `blocked_user\.email|` + `pull_request\.head\.ref|` + diff --git a/checks/raw/dangerous_workflow_test.go b/checks/raw/dangerous_workflow_test.go index c6431b7b127..973f26a6ec7 100644 --- a/checks/raw/dangerous_workflow_test.go +++ b/checks/raw/dangerous_workflow_test.go @@ -85,6 +85,26 @@ func TestUntrustedContextVariables(t *testing.T) { variable: "github.event.commits[2].author.email", expected: true, }, + { + name: "commits committer name", + variable: "github.event.commits[2].committer.name", + expected: true, + }, + { + name: "commits committer email", + variable: "github.event.commits[2].committer.email", + expected: true, + }, + { + name: "head_commit committer name", + variable: "github.event.head_commit.committer.name", + expected: true, + }, + { + name: "head_commit committer email", + variable: "github.event.head_commit.committer.email", + expected: true, + }, { name: "blocked_user name", variable: "github.event.pull_request.organization.blocked_user.name", diff --git a/clients/githubrepo/searchCommits.go b/clients/githubrepo/searchCommits.go index cdde327dcff..83162944d2b 100644 --- a/clients/githubrepo/searchCommits.go +++ b/clients/githubrepo/searchCommits.go @@ -16,7 +16,9 @@ package githubrepo import ( "context" + "errors" "fmt" + "net/http" "strings" "github.com/google/go-github/v82/github" @@ -49,7 +51,11 @@ func (handler *searchCommitsHandler) search(request clients.SearchCommitsOptions query, &github.SearchOptions{ListOptions: github.ListOptions{PerPage: 100}}) if err != nil { - return nil, fmt.Errorf("Search.Code: %w", err) + var gerr *github.ErrorResponse + if errors.As(err, &gerr) && gerr.Response.StatusCode == http.StatusUnprocessableEntity { + return nil, nil // Return empty list on 422 + } + return nil, fmt.Errorf("Search.Commits: %w", err) } return searchCommitsResponseFrom(resp), nil diff --git a/clients/githubrepo/searchCommits_test.go b/clients/githubrepo/searchCommits_test.go index 3dd252c63c8..6be5750d69a 100644 --- a/clients/githubrepo/searchCommits_test.go +++ b/clients/githubrepo/searchCommits_test.go @@ -15,9 +15,15 @@ package githubrepo import ( + "context" "errors" + "io" + "net/http" + "strings" "testing" + "github.com/google/go-github/v82/github" + "github.com/ossf/scorecard/v5/clients" ) @@ -76,3 +82,40 @@ func TestSearchCommitsBuildQuery(t *testing.T) { }) } } + +func TestSearchCommitsHandle422(t *testing.T) { + t.Parallel() + handler := searchCommitsHandler{ + ghClient: github.NewClient(&http.Client{ + Transport: &mockErrorTransport{ + statusCode: http.StatusUnprocessableEntity, + }, + }), + ctx: context.Background(), + repourl: &Repo{ + commitSHA: clients.HeadSHA, + owner: "testowner", + repo: "testrepo", + }, + } + + commits, err := handler.search(clients.SearchCommitsOptions{Author: "testbot"}) + if err != nil { + t.Fatalf("expected no error, got: %v", err) + } + if len(commits) != 0 { + t.Fatalf("expected 0 commits, got: %d", len(commits)) + } +} + +type mockErrorTransport struct { + statusCode int +} + +func (m *mockErrorTransport) RoundTrip(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: m.statusCode, + Body: io.NopCloser(strings.NewReader(`{"message": "Validation Failed"}`)), + Header: make(http.Header), + }, nil +}