Skip to content

Commit bfb7e8c

Browse files
Zohayb BhattiZohayb Bhatti
authored andcommitted
chore: Update SDK and fix security vulnerabilities
- Update privateer-sdk from v1.10.0 to v1.13.0 to include ToSARIF fixes - Fix template injection vulnerabilities using context.payload instead of template strings - Add repository and branch validation for workflow_run triggers - All security validations ensure workflows only run from same repo and allowed branches
1 parent 6fa2a83 commit bfb7e8c

File tree

6 files changed

+202
-14
lines changed

6 files changed

+202
-14
lines changed

.github/workflows/build-binaries.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,39 @@ jobs:
3939
arch: amd64
4040
output: github-repo-windows-amd64.exe
4141
steps:
42-
- name: Check if lint workflow passed
42+
- name: Validate workflow_run security
4343
if: github.event_name == 'workflow_run'
4444
uses: actions/github-script@v7
4545
with:
4646
script: |
47+
const workflowRun = context.payload.workflow_run;
48+
49+
// Validate workflow_run is from the same repository (not a fork)
50+
if (!workflowRun || workflowRun.repository.full_name !== context.repo.owner + '/' + context.repo.repo) {
51+
core.setFailed('Security: workflow_run must be from the same repository');
52+
return;
53+
}
54+
55+
// Validate head SHA format
56+
const headSha = workflowRun.head_sha;
57+
if (!headSha || !/^[a-f0-9]{40}$/i.test(headSha)) {
58+
core.setFailed('Invalid head SHA format');
59+
return;
60+
}
61+
62+
// Validate branch is allowed
63+
const allowedBranches = ['main', 'develop'];
64+
if (!allowedBranches.includes(workflowRun.head_branch)) {
65+
core.setFailed(`Security: workflow_run from branch '${workflowRun.head_branch}' is not allowed. Allowed branches: ${allowedBranches.join(', ')}`);
66+
return;
67+
}
68+
69+
// Check if lint workflow passed
4770
const { data: runs } = await github.rest.actions.listWorkflowRuns({
4871
owner: context.repo.owner,
4972
repo: context.repo.repo,
5073
workflow_id: 'lint.yaml',
51-
head_sha: '${{ github.event.workflow_run.head_sha }}',
74+
head_sha: headSha,
5275
per_page: 1
5376
});
5477
if (runs.workflow_runs.length > 0 && runs.workflow_runs[0].conclusion !== 'success') {

.github/workflows/docker-push.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,39 @@ jobs:
2525
runs-on: ubuntu-latest
2626
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_branch == 'main' || github.event.workflow_run.head_branch == 'develop')) }}
2727
steps:
28-
- name: Check if lint workflow passed
28+
- name: Validate workflow_run security
2929
if: github.event_name == 'workflow_run'
3030
uses: actions/github-script@v7
3131
with:
3232
script: |
33+
const workflowRun = context.payload.workflow_run;
34+
35+
// Validate workflow_run is from the same repository (not a fork)
36+
if (!workflowRun || workflowRun.repository.full_name !== context.repo.owner + '/' + context.repo.repo) {
37+
core.setFailed('Security: workflow_run must be from the same repository');
38+
return;
39+
}
40+
41+
// Validate head SHA format
42+
const headSha = workflowRun.head_sha;
43+
if (!headSha || !/^[a-f0-9]{40}$/i.test(headSha)) {
44+
core.setFailed('Invalid head SHA format');
45+
return;
46+
}
47+
48+
// Validate branch is allowed
49+
const allowedBranches = ['main', 'develop'];
50+
if (!allowedBranches.includes(workflowRun.head_branch)) {
51+
core.setFailed(`Security: workflow_run from branch '${workflowRun.head_branch}' is not allowed. Allowed branches: ${allowedBranches.join(', ')}`);
52+
return;
53+
}
54+
55+
// Check if lint workflow passed
3356
const { data: runs } = await github.rest.actions.listWorkflowRuns({
3457
owner: context.repo.owner,
3558
repo: context.repo.repo,
3659
workflow_id: 'lint.yaml',
37-
head_sha: '${{ github.event.workflow_run.head_sha }}',
60+
head_sha: headSha,
3861
per_page: 1
3962
});
4063
if (runs.workflow_runs.length > 0 && runs.workflow_runs[0].conclusion !== 'success') {

.github/workflows/integration-test.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,32 @@ jobs:
2121
runs-on: ubuntu-latest
2222
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'main') }}
2323
steps:
24+
- name: Validate workflow_run security
25+
if: github.event_name == 'workflow_run'
26+
uses: actions/github-script@v7
27+
with:
28+
script: |
29+
const workflowRun = context.payload.workflow_run;
30+
31+
// Validate workflow_run is from the same repository (not a fork)
32+
if (!workflowRun || workflowRun.repository.full_name !== context.repo.owner + '/' + context.repo.repo) {
33+
core.setFailed('Security: workflow_run must be from the same repository');
34+
return;
35+
}
36+
37+
// Validate head SHA format
38+
const headSha = workflowRun.head_sha;
39+
if (!headSha || !/^[a-f0-9]{40}$/i.test(headSha)) {
40+
core.setFailed('Invalid head SHA format');
41+
return;
42+
}
43+
44+
// Validate branch is allowed
45+
const allowedBranches = ['main'];
46+
if (!allowedBranches.includes(workflowRun.head_branch)) {
47+
core.setFailed(`Security: workflow_run from branch '${workflowRun.head_branch}' is not allowed. Allowed branches: ${allowedBranches.join(', ')}`);
48+
return;
49+
}
2450
- name: Checkout code
2551
uses: actions/checkout@v5
2652
with:

.github/workflows/security-scan.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,39 @@ jobs:
1919
runs-on: ubuntu-latest
2020
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
2121
steps:
22-
- name: Check if lint workflow passed
22+
- name: Validate workflow_run security
2323
if: github.event_name == 'workflow_run'
2424
uses: actions/github-script@v7
2525
with:
2626
script: |
27+
const workflowRun = context.payload.workflow_run;
28+
29+
// Validate workflow_run is from the same repository (not a fork)
30+
if (!workflowRun || workflowRun.repository.full_name !== context.repo.owner + '/' + context.repo.repo) {
31+
core.setFailed('Security: workflow_run must be from the same repository');
32+
return;
33+
}
34+
35+
// Validate head SHA format
36+
const headSha = workflowRun.head_sha;
37+
if (!headSha || !/^[a-f0-9]{40}$/i.test(headSha)) {
38+
core.setFailed('Invalid head SHA format');
39+
return;
40+
}
41+
42+
// Validate branch is allowed
43+
const allowedBranches = ['main', 'develop'];
44+
if (!allowedBranches.includes(workflowRun.head_branch)) {
45+
core.setFailed(`Security: workflow_run from branch '${workflowRun.head_branch}' is not allowed. Allowed branches: ${allowedBranches.join(', ')}`);
46+
return;
47+
}
48+
49+
// Check if lint workflow passed
2750
const { data: runs } = await github.rest.actions.listWorkflowRuns({
2851
owner: context.repo.owner,
2952
repo: context.repo.repo,
3053
workflow_id: 'lint.yaml',
31-
head_sha: '${{ github.event.workflow_run.head_sha }}',
54+
head_sha: headSha,
3255
per_page: 1
3356
});
3457
if (runs.workflow_runs.length > 0 && runs.workflow_runs[0].conclusion !== 'success') {

go.mod

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,45 @@ require (
77
github.com/migueleliasweb/go-github-mock v1.4.0
88
github.com/ossf/gemara v0.13.0
99
github.com/ossf/si-tooling/v2 v2.0.5-0.20250508212737-7ddcc8c43db9
10-
github.com/privateerproj/privateer-sdk v1.10.0
10+
github.com/privateerproj/privateer-sdk v1.13.0
1111
github.com/rhysd/actionlint v1.7.8
1212
github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7
1313
golang.org/x/oauth2 v0.32.0
1414
)
1515

1616
require (
17+
dario.cat/mergo v1.0.0 // indirect
18+
github.com/Microsoft/go-winio v0.6.2 // indirect
19+
github.com/ProtonMail/go-crypto v1.1.6 // indirect
20+
github.com/cloudflare/circl v1.6.1 // indirect
21+
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
1722
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
1823
github.com/defenseunicorns/go-oscal v0.7.0 // indirect
24+
github.com/emirpasic/gods v1.18.1 // indirect
25+
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
26+
github.com/go-git/go-billy/v5 v5.6.2 // indirect
27+
github.com/go-git/go-git/v5 v5.16.3 // indirect
1928
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
2029
github.com/goccy/go-yaml v1.18.0 // indirect
30+
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
2131
github.com/google/go-github/v71 v71.0.0 // indirect
2232
github.com/google/go-github/v73 v73.0.0 // indirect
2333
github.com/google/go-querystring v1.1.0 // indirect
2434
github.com/google/uuid v1.6.0 // indirect
2535
github.com/gorilla/mux v1.8.1 // indirect
36+
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
37+
github.com/kevinburke/ssh_config v1.2.0 // indirect
38+
github.com/pjbgf/sha1cd v0.3.2 // indirect
2639
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
2740
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
41+
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
42+
github.com/skeema/knownhosts v1.3.1 // indirect
43+
github.com/xanzy/ssh-agent v0.3.3 // indirect
2844
go.yaml.in/yaml/v3 v3.0.4 // indirect
2945
go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect
46+
golang.org/x/crypto v0.37.0 // indirect
3047
golang.org/x/time v0.11.0 // indirect
48+
gopkg.in/warnings.v0 v0.1.2 // indirect
3149
)
3250

3351
require (
@@ -58,7 +76,7 @@ require (
5876
github.com/spf13/viper v1.21.0 // indirect
5977
github.com/stretchr/testify v1.11.1
6078
github.com/subosito/gotenv v1.6.0 // indirect
61-
golang.org/x/net v0.38.0 // indirect
79+
golang.org/x/net v0.39.0 // indirect
6280
golang.org/x/sync v0.17.0 // indirect
6381
golang.org/x/sys v0.36.0 // indirect
6482
golang.org/x/text v0.28.0 // indirect

0 commit comments

Comments
 (0)