diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index a7285493..6f1845fe 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "os" - "path/filepath" "regexp" "strings" @@ -261,8 +260,15 @@ func getSemanticVersion(client *github.Client, owner, repo, tagOrBranch, commitS // Function to check if an action matches any pattern in the list func ActionExists(actionName string, patterns []string) bool { for _, pattern := range patterns { - // Use filepath.Match to match the pattern - matched, err := filepath.Match(pattern, actionName) + // Convert glob pattern to regex for path matching + // Replace * with [^/]* to match within a path segment + // Replace **/ with .* to match across path segments + regexPattern := strings.ReplaceAll(pattern, "**", "§§") + regexPattern = strings.ReplaceAll(regexPattern, "*", "[^/]*") + regexPattern = strings.ReplaceAll(regexPattern, "§§", ".*") + regexPattern = "^" + regexPattern + "($|/)" + + matched, err := regexp.MatchString(regexPattern, actionName) if err != nil { // Handle invalid patterns fmt.Printf("Error matching pattern: %v\n", err) diff --git a/remediation/workflow/pin/pinactions_test.go b/remediation/workflow/pin/pinactions_test.go index c600cda4..19263e19 100644 --- a/remediation/workflow/pin/pinactions_test.go +++ b/remediation/workflow/pin/pinactions_test.go @@ -33,6 +33,21 @@ func TestPinActions(t *testing.T) { } ]`)) + httpmock.RegisterResponder("GET", "https://api.github.com/repos/evans/shield/commits/v1", + httpmock.NewStringResponder(200, `a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbd`)) + + httpmock.RegisterResponder("GET", "https://api.github.com/repos/evans/shield/git/matching-refs/tags/v1.", + httpmock.NewStringResponder(200, + `[ + { + "ref": "refs/tags/v1.0.3", + "object": { + "sha": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbd", + "type": "commit" + } + } + ]`)) + httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/commits/master", httpmock.NewStringResponder(200, `61b9e3751b92087fd0b06925ba6dd6314e06f089`)) @@ -308,10 +323,9 @@ func TestPinActions(t *testing.T) { {fileName: "actionwithcomment.yml", wantUpdated: true, pinToImmutable: true}, {fileName: "repeatedactionwithcomment.yml", wantUpdated: true, pinToImmutable: true}, {fileName: "immutableaction-1.yml", wantUpdated: true, pinToImmutable: true}, - {fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*"}, pinToImmutable: true}, + {fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*", "praveen/*", "aman-*/*", "*/seperate*", "starc/*"}, pinToImmutable: true}, {fileName: "donotpintoimmutable.yml", wantUpdated: true, pinToImmutable: false}, {fileName: "invertedcommas.yml", wantUpdated: true, pinToImmutable: false}, - {fileName: "pinusingmap.yml", wantUpdated: true, pinToImmutable: true}, } for _, tt := range tests { @@ -330,6 +344,7 @@ func TestPinActions(t *testing.T) { actionCommitMap = map[string]string{ "peter-evans-test/close-issue@v1": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53vam", "peter-check/close-issue@v1.2.3": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53tom", + "evans/shield-test/@v1.2.5": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53cat", } } @@ -374,3 +389,36 @@ func Test_isAbsolute(t *testing.T) { }) } } + +func TestActionExists(t *testing.T) { + result := ActionExists("actions/checkout", []string{"actions/checkout"}) + t.Log(result) + if !result { + t.Errorf("ActionExists returned false for actions/checkout") + } + + result = ActionExists("actions/checkout", []string{"actions/*"}) + t.Log(result) + if !result { + t.Errorf("ActionExists returned false for actions/checkout") + } + + result = ActionExists("actions/checkout/something", []string{"actions/*"}) + t.Log(result) + if !result { + t.Errorf("ActionExists returned true for actions/checkout/something") + } + + result = ActionExists("step-security/checkout/something", []string{"step-*/*"}) + t.Log(result) + if !result { + t.Errorf("ActionExists returned true for actions/checkout/something") + } + + result = ActionExists("step-security/checkout-release/something", []string{"*/checkout-*"}) + t.Log(result) + if !result { + t.Errorf("ActionExists returned true for actions/checkout/something") + } + +} diff --git a/testfiles/pinactions/input/basic.yml b/testfiles/pinactions/input/basic.yml index c62a6485..7b2e4686 100644 --- a/testfiles/pinactions/input/basic.yml +++ b/testfiles/pinactions/input/basic.yml @@ -11,6 +11,12 @@ jobs: steps: - name: Close Issue uses: peter-evans/close-issue@v1 + with: + issue-number: 1 + comment: Auto-closing issue + + - name: test case + uses: evans/shield/@v1 with: issue-number: 1 comment: Auto-closing issue \ No newline at end of file diff --git a/testfiles/pinactions/input/exemptaction.yml b/testfiles/pinactions/input/exemptaction.yml index 3a80dc79..3912c757 100644 --- a/testfiles/pinactions/input/exemptaction.yml +++ b/testfiles/pinactions/input/exemptaction.yml @@ -38,6 +38,38 @@ jobs: - name: publish on version change id: publish_nuget uses: rohith/publish-nuget@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: praveen/publish-nuget/to-version@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 3 + id: publish_nuget + uses: aman-action/move/to-main@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: smith/seperate/from-version@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: starc/swing/from-version/@v2 with: PROJECT_FILE_PATH: Core/Core.csproj NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} diff --git a/testfiles/pinactions/input/pinusingmap.yml b/testfiles/pinactions/input/pinusingmap.yml index c9807f98..f45dce5d 100644 --- a/testfiles/pinactions/input/pinusingmap.yml +++ b/testfiles/pinactions/input/pinusingmap.yml @@ -23,6 +23,12 @@ jobs: - name: Close Issue uses: peter-check/close-issue@v1.2.3 + with: + issue-number: 1 + comment: Auto-closing issue + + - name: test case + uses: evans/shield-test/@v1.2.5 with: issue-number: 1 comment: Auto-closing issue \ No newline at end of file diff --git a/testfiles/pinactions/output/basic.yml b/testfiles/pinactions/output/basic.yml index 39f5bbb5..4721f665 100644 --- a/testfiles/pinactions/output/basic.yml +++ b/testfiles/pinactions/output/basic.yml @@ -11,6 +11,12 @@ jobs: steps: - name: Close Issue uses: peter-evans/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe # v1.0.3 + with: + issue-number: 1 + comment: Auto-closing issue + + - name: test case + uses: evans/shield/@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbd # v1.0.3 with: issue-number: 1 comment: Auto-closing issue \ No newline at end of file diff --git a/testfiles/pinactions/output/exemptaction.yml b/testfiles/pinactions/output/exemptaction.yml index 4c986d6f..820732e8 100644 --- a/testfiles/pinactions/output/exemptaction.yml +++ b/testfiles/pinactions/output/exemptaction.yml @@ -38,6 +38,38 @@ jobs: - name: publish on version change id: publish_nuget uses: rohith/publish-nuget@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: praveen/publish-nuget/to-version@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 3 + id: publish_nuget + uses: aman-action/move/to-main@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: smith/seperate/from-version@v2 + with: + PROJECT_FILE_PATH: Core/Core.csproj + NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} + NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json + + - name: publish on version change 2 + id: publish_nuget + uses: starc/swing/from-version/@v2 with: PROJECT_FILE_PATH: Core/Core.csproj NUGET_KEY: ${{ secrets.GITHUB_TOKEN }} diff --git a/testfiles/pinactions/output/pinusingmap.yml b/testfiles/pinactions/output/pinusingmap.yml index ebaced2d..bd13dd35 100644 --- a/testfiles/pinactions/output/pinusingmap.yml +++ b/testfiles/pinactions/output/pinusingmap.yml @@ -23,6 +23,12 @@ jobs: - name: Close Issue uses: peter-check/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53tom # v1.2.3 + with: + issue-number: 1 + comment: Auto-closing issue + + - name: test case + uses: evans/shield-test/@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53cat # v1.2.5 with: issue-number: 1 comment: Auto-closing issue \ No newline at end of file