diff --git a/remediation/workflow/maintainedactions/getlatestrelease.go b/remediation/workflow/maintainedactions/getlatestrelease.go index 4ba0068eb..af5359b87 100644 --- a/remediation/workflow/maintainedactions/getlatestrelease.go +++ b/remediation/workflow/maintainedactions/getlatestrelease.go @@ -32,7 +32,7 @@ func getMajorVersion(version string) string { func GetLatestRelease(ownerRepo string) (string, error) { splitOnSlash := strings.Split(ownerRepo, "/") - if len(splitOnSlash) != 2 { + if len(splitOnSlash) < 2 { return "", fmt.Errorf("invalid owner/repo format: %s", ownerRepo) } owner := splitOnSlash[0] diff --git a/remediation/workflow/maintainedactions/maintainedActions.go b/remediation/workflow/maintainedactions/maintainedActions.go index 1c0d0ff86..e0d6e3feb 100644 --- a/remediation/workflow/maintainedactions/maintainedActions.go +++ b/remediation/workflow/maintainedactions/maintainedActions.go @@ -81,7 +81,7 @@ func ReplaceActions(inputYaml string, customerMaintainedActions map[string]strin if newAction, ok := actionMap[actionName]; ok { latestVersion, err := GetLatestRelease(newAction) if err != nil { - return "", updated, fmt.Errorf("unable to get latest release: %v", err) + return inputYaml, updated, fmt.Errorf("unable to get latest release: %v", err) } replacements = append(replacements, replacement{ jobName: jobName, diff --git a/remediation/workflow/maintainedactions/maintainedActions.json b/remediation/workflow/maintainedactions/maintainedActions.json index 273ce0616..f155c82d3 100644 --- a/remediation/workflow/maintainedactions/maintainedActions.json +++ b/remediation/workflow/maintainedactions/maintainedActions.json @@ -493,5 +493,14 @@ }, "score": 10, "image": "https://avatars.githubusercontent.com/u/88700172?v=4" + }, + { + "name": "step-security/actions-cache/restore", + "description": "GitHub Action to restore cache", + "forkedFrom": { + "name": "tespkg/actions-cache/restore" + }, + "score": 10, + "image": "https://avatars.githubusercontent.com/u/88700172?v=4" } ] \ No newline at end of file diff --git a/remediation/workflow/maintainedactions/maintainedactions_test.go b/remediation/workflow/maintainedactions/maintainedactions_test.go index 9040483aa..ffbb7f46b 100644 --- a/remediation/workflow/maintainedactions/maintainedactions_test.go +++ b/remediation/workflow/maintainedactions/maintainedactions_test.go @@ -41,6 +41,14 @@ func TestReplaceActions(t *testing.T) { "created_at": "2023-01-01T00:00:00Z" }`)) + httpmock.RegisterResponder("GET", "https://api.github.com/repos/step-security/actions-cache/releases/latest", + httpmock.NewStringResponder(200, `{ + "tag_name": "v1.0.0", + "name": "v1.0.0", + "body": "Release notes", + "created_at": "2023-01-01T00:00:00Z" + }`)) + tests := []struct { name string inputFile string diff --git a/remediation/workflow/secureworkflow.go b/remediation/workflow/secureworkflow.go index 22fb3c302..44c1c07a8 100644 --- a/remediation/workflow/secureworkflow.go +++ b/remediation/workflow/secureworkflow.go @@ -133,6 +133,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d if replaceMaintainedActions { secureWorkflowReponse.FinalOutput, replacedMaintainedActions, err = maintainedactions.ReplaceActions(secureWorkflowReponse.FinalOutput, maintainedActionsMap) if err != nil { + log.Printf("Error replacing maintained actions: %v", err) secureWorkflowReponse.HasErrors = true } } diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index bb1e3bbee..da0d84540 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -186,6 +186,28 @@ func TestSecureWorkflow(t *testing.T) { } ]`)) + httpmock.RegisterResponder("GET", "https://api.github.com/repos/step-security/actions-cache/commits/v1", + httpmock.NewStringResponder(200, `d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0a1b2c3`)) + + httpmock.RegisterResponder("GET", "https://api.github.com/repos/step-security/actions-cache/git/matching-refs/tags/v1.", + httpmock.NewStringResponder(200, `[ + { + "ref": "refs/tags/v1.0.0", + "object": { + "sha": "d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0a1b2c3", + "type": "commit" + } + } + ]`)) + + httpmock.RegisterResponder("GET", "https://api.github.com/repos/step-security/actions-cache/releases/latest", + httpmock.NewStringResponder(200, `{ + "tag_name": "v1.0.0", + "name": "v1.0.0", + "body": "Release notes", + "created_at": "2023-01-01T00:00:00Z" + }`)) + tests := []struct { fileName string wantPinnedActions bool @@ -244,7 +266,6 @@ func TestSecureWorkflow(t *testing.T) { t.Errorf("unable to load the file %s", err) } output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, []string{}, false, actionMap) - } else { output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) } @@ -275,6 +296,10 @@ func TestSecureWorkflow(t *testing.T) { t.Errorf("test failed %s did not match expected PinnedActions value. Expected:%v Actual:%v", test.fileName, test.wantPinnedActions, output.PinnedActions) } + if output.AddedMaintainedActions != test.wantAddedMaintainedActions { + t.Errorf("test failed %s did not match expected AddedMaintainedActions value. Expected:%v Actual:%v", test.fileName, test.wantAddedMaintainedActions, output.AddedMaintainedActions) + } + } } diff --git a/testfiles/maintainedActions/input/oneJob.yml b/testfiles/maintainedActions/input/oneJob.yml index 4a28c9e49..939d87c02 100644 --- a/testfiles/maintainedActions/input/oneJob.yml +++ b/testfiles/maintainedActions/input/oneJob.yml @@ -14,4 +14,10 @@ jobs: do_not_skip: '["release"]' - uses: chetan/git-restore-mtime-action@v1 with: - pattern: '**/*' \ No newline at end of file + pattern: '**/*' + - uses: tespkg/actions-cache/restore@v1 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- \ No newline at end of file diff --git a/testfiles/maintainedActions/output/oneJob.yml b/testfiles/maintainedActions/output/oneJob.yml index ce73bf408..e3ed9c165 100644 --- a/testfiles/maintainedActions/output/oneJob.yml +++ b/testfiles/maintainedActions/output/oneJob.yml @@ -14,4 +14,10 @@ jobs: do_not_skip: '["release"]' - uses: step-security/git-restore-mtime-action@v2 with: - pattern: '**/*' \ No newline at end of file + pattern: '**/*' + - uses: step-security/actions-cache/restore@v1 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- \ No newline at end of file diff --git a/testfiles/secureworkflow/input/oneJob.yml b/testfiles/secureworkflow/input/oneJob.yml index 6201dd2c7..6cc0cca20 100644 --- a/testfiles/secureworkflow/input/oneJob.yml +++ b/testfiles/secureworkflow/input/oneJob.yml @@ -23,4 +23,11 @@ jobs: - uses: github/super-linter@v3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DISABLE_ERRORS: true \ No newline at end of file + DISABLE_ERRORS: true + - uses: tespkg/actions-cache/restore@v1 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + \ No newline at end of file diff --git a/testfiles/secureworkflow/output/oneJob.yml b/testfiles/secureworkflow/output/oneJob.yml index 91ec1376d..e8d874fd7 100644 --- a/testfiles/secureworkflow/output/oneJob.yml +++ b/testfiles/secureworkflow/output/oneJob.yml @@ -33,4 +33,11 @@ jobs: - uses: github/super-linter@34b2f8032d759425f6b42ea2e52231b33ae05401 # v3.17.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DISABLE_ERRORS: true \ No newline at end of file + DISABLE_ERRORS: true + - uses: step-security/actions-cache/restore@d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0a1b2c3 # v1.0.0 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + \ No newline at end of file