Skip to content

Commit c6270bb

Browse files
Devils-Knightvarunsh-coder
authored andcommitted
[UPDATE] Pin actions to vx.y.z format (#1469)
1 parent 6039c8f commit c6270bb

File tree

7 files changed

+177
-14
lines changed

7 files changed

+177
-14
lines changed

remediation/workflow/pin/pinactions.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ func pinAction(action, jobName, inputYaml string) (string, bool) {
6868
return inputYaml, updated
6969
}
7070

71+
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
72+
if err != nil {
73+
return inputYaml, updated
74+
}
75+
7176
pinnedAction := fmt.Sprintf("%s@%s # %s", leftOfAt[0], commitSHA, tagOrBranch)
7277
updated = !strings.EqualFold(action, pinnedAction)
7378
inputYaml = strings.ReplaceAll(inputYaml, action, pinnedAction)
@@ -100,3 +105,33 @@ func isAllHex(s string) bool {
100105
}
101106
return true
102107
}
108+
109+
func getSemanticVersion(client *github.Client, owner, repo, tagOrBranch, commitSHA string) (string, error) {
110+
tags, _, err := client.Git.ListMatchingRefs(context.Background(), owner, repo, &github.ReferenceListOptions{
111+
Ref: fmt.Sprintf("tags/%s.", tagOrBranch),
112+
ListOptions: github.ListOptions{
113+
PerPage: 100,
114+
},
115+
})
116+
if err != nil {
117+
return "", err
118+
}
119+
120+
for i := len(tags) - 1; i >= 0; i-- {
121+
tag := strings.TrimPrefix(*tags[i].Ref, "refs/tags/")
122+
if *tags[i].Object.Type == "commit" {
123+
if commitSHA == *tags[i].Object.SHA {
124+
return tag, nil
125+
}
126+
} else {
127+
commitsha, _, err := client.Repositories.GetCommitSHA1(context.Background(), owner, repo, tag, "")
128+
if err != nil {
129+
return "", err
130+
}
131+
if commitSHA == commitsha {
132+
return tag, nil
133+
}
134+
}
135+
}
136+
return tagOrBranch, nil
137+
}

remediation/workflow/pin/pinactions_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,158 @@ func TestPinActions(t *testing.T) {
1919
httpmock.RegisterResponder("GET", "https://api.github.com/repos/peter-evans/close-issue/commits/v1",
2020
httpmock.NewStringResponder(200, `a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe`))
2121

22+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/peter-evans/close-issue/git/matching-refs/tags/v1.",
23+
httpmock.NewStringResponder(200,
24+
`[
25+
{
26+
"ref": "refs/tags/v1.0.3",
27+
"object": {
28+
"sha": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe",
29+
"type": "commit"
30+
}
31+
}
32+
]`))
33+
2234
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/commits/master",
2335
httpmock.NewStringResponder(200, `61b9e3751b92087fd0b06925ba6dd6314e06f089`))
2436

37+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/git/matching-refs/tags/master.",
38+
httpmock.NewStringResponder(200, `[]`))
39+
2540
httpmock.RegisterResponder("GET", "https://api.github.com/repos/elgohr/Publish-Docker-Github-Action/commits/master",
2641
httpmock.NewStringResponder(200, `8217e91c0369a5342a4ef2d612de87492410a666`))
2742

43+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/elgohr/Publish-Docker-Github-Action/git/matching-refs/tags/master.",
44+
httpmock.NewStringResponder(200, `[]`))
45+
2846
httpmock.RegisterResponder("GET", "https://api.github.com/repos/borales/actions-yarn/commits/v2.3.0",
2947
httpmock.NewStringResponder(200, `4965e1a0f0ae9c422a9a5748ebd1fb5e097d22b9`))
3048

49+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/borales/actions-yarn/git/matching-refs/tags/v2.3.0.",
50+
httpmock.NewStringResponder(200, `[]`))
51+
3152
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/commits/v1",
3253
httpmock.NewStringResponder(200, `544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9`))
3354

55+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/git/matching-refs/tags/v1.",
56+
httpmock.NewStringResponder(200,
57+
`[
58+
{
59+
"ref": "refs/tags/v1.0.0",
60+
"node_id": "MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MS4wLjA=",
61+
"url": "https://api.github.com/repos/actions/checkout/git/refs/tags/v1.0.0",
62+
"object": {
63+
"sha": "af513c7a016048ae468971c52ed77d9562c7c819",
64+
"type": "commit",
65+
"url": "https://api.github.com/repos/actions/checkout/git/commits/af513c7a016048ae468971c52ed77d9562c7c819"
66+
}
67+
},
68+
{
69+
"ref": "refs/tags/v1.1.0",
70+
"node_id": "MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MS4xLjA=",
71+
"url": "https://api.github.com/repos/actions/checkout/git/refs/tags/v1.1.0",
72+
"object": {
73+
"sha": "ec3afacf7f605c9fc12c70bc1c9e1708ddb99eca",
74+
"type": "tag",
75+
"url": "https://api.github.com/repos/actions/checkout/git/tags/ec3afacf7f605c9fc12c70bc1c9e1708ddb99eca"
76+
}
77+
},
78+
{
79+
"ref": "refs/tags/v1.2.0",
80+
"node_id": "MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MS4yLjA=",
81+
"url": "https://api.github.com/repos/actions/checkout/git/refs/tags/v1.2.0",
82+
"object": {
83+
"sha": "a2ca40438991a1ab62db1b7cad0fd4e36a2ac254",
84+
"type": "tag",
85+
"url": "https://api.github.com/repos/actions/checkout/git/tags/a2ca40438991a1ab62db1b7cad0fd4e36a2ac254"
86+
}
87+
}
88+
]`),
89+
)
90+
91+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/checkout/commits/v1.2.0",
92+
httpmock.NewStringResponder(200, `544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9`))
93+
3494
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/setup-node/commits/v1",
3595
httpmock.NewStringResponder(200, `f1f314fca9dfce2769ece7d933488f076716723e`))
3696

97+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/actions/setup-node/git/matching-refs/tags/v1.",
98+
httpmock.NewStringResponder(200,
99+
`[
100+
{
101+
"ref": "refs/tags/v1.4.6",
102+
"object": {
103+
"sha": "f1f314fca9dfce2769ece7d933488f076716723e",
104+
"type": "commit"
105+
}
106+
}
107+
]`))
108+
37109
httpmock.RegisterResponder("GET", "https://api.github.com/repos/JS-DevTools/npm-publish/commits/v1",
38110
httpmock.NewStringResponder(200, `0f451a94170d1699fd50710966d48fb26194d939`))
39111

112+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/JS-DevTools/npm-publish/git/matching-refs/tags/v1.",
113+
httpmock.NewStringResponder(200,
114+
`[
115+
{
116+
"ref": "refs/tags/v1.4.3",
117+
"object": {
118+
"sha": "0f451a94170d1699fd50710966d48fb26194d939",
119+
"type": "commit"
120+
}
121+
}
122+
]`))
123+
40124
httpmock.RegisterResponder("GET", "https://api.github.com/repos/brandedoutcast/publish-nuget/commits/v2",
41125
httpmock.NewStringResponder(200, `c12b8546b67672ee38ac87bea491ac94a587f7cc`))
42126

127+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/brandedoutcast/publish-nuget/git/matching-refs/tags/v2.",
128+
httpmock.NewStringResponder(200,
129+
`[
130+
{
131+
"ref": "refs/tags/v2.5.3",
132+
"node_id": "MDM6UmVmMjI4MTk2ODk5OnJlZnMvdGFncy92Mi41LjM=",
133+
"url": "https://api.github.com/repos/brandedoutcast/publish-nuget/git/refs/tags/v2.5.3",
134+
"object": {
135+
"sha": "4637c3bdd3fb4c052235299664c57b14c398cbd0",
136+
"type": "commit",
137+
"url": "https://api.github.com/repos/brandedoutcast/publish-nuget/git/commits/4637c3bdd3fb4c052235299664c57b14c398cbd0"
138+
}
139+
},
140+
{
141+
"ref": "refs/tags/v2.5.4",
142+
"node_id": "MDM6UmVmMjI4MTk2ODk5OnJlZnMvdGFncy92Mi41LjQ=",
143+
"url": "https://api.github.com/repos/brandedoutcast/publish-nuget/git/refs/tags/v2.5.4",
144+
"object": {
145+
"sha": "108c10b32aa03efa5f71af6a233dc2e8e32845cb",
146+
"type": "commit",
147+
"url": "https://api.github.com/repos/brandedoutcast/publish-nuget/git/commits/108c10b32aa03efa5f71af6a233dc2e8e32845cb"
148+
}
149+
},
150+
{
151+
"ref": "refs/tags/v2.5.5",
152+
"object": {
153+
"sha": "c12b8546b67672ee38ac87bea491ac94a587f7cc",
154+
"type": "commit"
155+
}
156+
}
157+
]`))
158+
43159
httpmock.RegisterResponder("GET", "https://api.github.com/repos/rohith/publish-nuget/commits/v2",
44160
httpmock.NewStringResponder(200, `c12b8546b67672ee38ac87bea491ac94a587f7cc`))
45161

162+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/rohith/publish-nuget/git/matching-refs/tags/v2.",
163+
httpmock.NewStringResponder(200,
164+
`[
165+
{
166+
"ref": "refs/tags/v2.5.5",
167+
"object": {
168+
"sha": "c12b8546b67672ee38ac87bea491ac94a587f7cc",
169+
"type": "commit"
170+
}
171+
}
172+
]`))
173+
46174
tests := []struct {
47175
fileName string
48176
wantUpdated bool

testfiles/pinactions/output/basic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010

1111
steps:
1212
- name: Close Issue
13-
uses: peter-evans/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe # v1
13+
uses: peter-evans/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe # v1.0.3
1414
with:
1515
issue-number: 1
1616
comment: Auto-closing issue

testfiles/pinactions/output/dockeraction.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
13+
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
1414
- name: Integration test
1515
uses: docker://ghcr.io/step-security/integration-test/int:latest
1616
env:

testfiles/pinactions/output/localaction.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
build:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
14+
- uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6
1515
with:
1616
node-version: 12.x
17-
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
17+
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
1818
- run: npm ci
1919
- run: npm run build
2020
- run: npm run format-check
@@ -32,7 +32,7 @@ jobs:
3232
steps:
3333
# Clone this repo
3434
- name: Checkout
35-
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
35+
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
3636

3737
# Basic checkout
3838
- name: Checkout basic
@@ -150,7 +150,7 @@ jobs:
150150
steps:
151151
# Clone this repo
152152
- name: Checkout
153-
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
153+
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
154154

155155
# Basic checkout using git
156156
- name: Checkout basic
@@ -182,7 +182,7 @@ jobs:
182182
steps:
183183
# Clone this repo
184184
- name: Checkout
185-
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
185+
uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
186186

187187
# Basic checkout using git
188188
- name: Checkout basic

testfiles/pinactions/output/multipleactions.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ jobs:
44
publish:
55
runs-on: ubuntu-latest
66
steps:
7-
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
8-
- uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
7+
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
8+
- uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6
99
with:
1010
node-version: 10
1111
- run: npm install
1212
- run: npm test
13-
- uses: JS-DevTools/npm-publish@0f451a94170d1699fd50710966d48fb26194d939 # v1
13+
- uses: JS-DevTools/npm-publish@0f451a94170d1699fd50710966d48fb26194d939 # v1.4.3
1414
with:
1515
token: ${{ secrets.GITHUB_TOKEN }}
1616
registry: https://npm.pkg.github.com

testfiles/pinactions/output/multiplejobs.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
name: build, pack & publish
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
11+
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
1212

1313
# - name: Setup dotnet
1414
# uses: actions/setup-dotnet@v1
@@ -18,7 +18,7 @@ jobs:
1818
# Publish
1919
- name: publish on version change
2020
id: publish_nuget
21-
uses: brandedoutcast/publish-nuget@c12b8546b67672ee38ac87bea491ac94a587f7cc # v2
21+
uses: brandedoutcast/publish-nuget@c12b8546b67672ee38ac87bea491ac94a587f7cc # v2.5.5
2222
with:
2323
PROJECT_FILE_PATH: Core/Core.csproj
2424
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}
@@ -27,7 +27,7 @@ jobs:
2727
name: build, pack & publish
2828
runs-on: ubuntu-latest
2929
steps:
30-
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1
30+
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
3131

3232
# - name: Setup dotnet
3333
# uses: actions/setup-dotnet@v1
@@ -37,7 +37,7 @@ jobs:
3737
# Publish
3838
- name: publish on version change
3939
id: publish_nuget
40-
uses: rohith/publish-nuget@c12b8546b67672ee38ac87bea491ac94a587f7cc # v2
40+
uses: rohith/publish-nuget@c12b8546b67672ee38ac87bea491ac94a587f7cc # v2.5.5
4141
with:
4242
PROJECT_FILE_PATH: Core/Core.csproj
4343
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)