Skip to content

Commit 76b115d

Browse files
author
Alvaro Muñoz
committed
Dedup Cache poisoning and Untrusted checkout
1 parent 878317a commit 76b115d

File tree

11 files changed

+528
-1
lines changed

11 files changed

+528
-1
lines changed

ql/src/Security/CWE-349/CachePoisoning.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ where
4141
// the job writes to the cache
4242
// (No need to follow the checkout step as the cache writing is normally done after the job completes)
4343
j.getAStep() = s and
44-
s instanceof CacheWritingStep
44+
s instanceof CacheWritingStep and
45+
not s instanceof PoisonableStep
4546
or
4647
// the job executes checked-out code
4748
// (The cache specific token can be leaked even for non-privileged workflows)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
6+
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
7+
name: Deploy Jekyll site to Pages preview environment
8+
on:
9+
# Runs on pull requests targeting the default branch
10+
pull_request_target:
11+
branches: ["main"]
12+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13+
permissions:
14+
contents: read
15+
pages: write
16+
id-token: write
17+
# Allow only one concurrent deployment per PR, skipping runs queued between the run in-progress and latest queued.
18+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
19+
concurrency:
20+
group: 'pages-preview @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
21+
cancel-in-progress: false
22+
jobs:
23+
# Build job
24+
build:
25+
# Limit permissions of the GITHUB_TOKEN for untrusted code
26+
permissions:
27+
contents: read
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
32+
with:
33+
# For PRs make sure to checkout the PR branch
34+
ref: ${{ github.event.pull_request.head.ref }}
35+
repository: ${{ github.event.pull_request.head.repo.full_name }}
36+
- name: Setup Pages
37+
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
38+
- name: Build with Jekyll
39+
uses: actions/jekyll-build-pages@b178f9334b208360999a0a57b523613563698c66 # v1
40+
with:
41+
source: ./
42+
destination: ./_site
43+
- name: Upload artifact
44+
# Automatically uploads an artifact from the './_site' directory by default
45+
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
46+
# Deployment job
47+
deploy:
48+
environment:
49+
name: 'Pages Preview'
50+
url: ${{ steps.deployment.outputs.page_url }}
51+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
52+
permissions:
53+
contents: read
54+
pages: write
55+
id-token: write
56+
runs-on: ubuntu-latest
57+
needs: build
58+
steps:
59+
- name: Deploy to GitHub Pages
60+
id: deployment
61+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
62+
with:
63+
preview: 'true'
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: branch-deploy
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
# Permissions needed for reacting and adding comments for IssueOps commands
8+
permissions:
9+
pull-requests: write
10+
deployments: write
11+
contents: write
12+
checks: read
13+
14+
jobs:
15+
branch-deploy:
16+
name: branch-deploy
17+
if: # only run on pull request comments and very specific comment body string as defined in our branch-deploy settings
18+
${{ github.event.issue.pull_request &&
19+
(startsWith(github.event.comment.body, '.deploy') ||
20+
startsWith(github.event.comment.body, '.noop') ||
21+
startsWith(github.event.comment.body, '.lock') ||
22+
startsWith(github.event.comment.body, '.help') ||
23+
startsWith(github.event.comment.body, '.wcid') ||
24+
startsWith(github.event.comment.body, '.unlock')) }}
25+
runs-on: ubuntu-latest
26+
27+
steps:
28+
- name: branch-deploy
29+
id: branch-deploy
30+
uses: github/branch-deploy@v9
31+
with:
32+
trigger: ".deploy"
33+
environment: "production"
34+
sticky_locks: "true" # https://github.com/github/branch-deploy/blob/1f6516ef5092890ce75d9e97ca7cbdb628e38bdd/docs/hubot-style-deployment-locks.md
35+
36+
# Check out the ref from the output of the IssueOps command
37+
- uses: actions/checkout@v4
38+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
39+
with:
40+
ref: ${{ steps.branch-deploy.outputs.ref }}
41+
42+
- uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 # [email protected]
43+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
44+
with:
45+
bundler-cache: true
46+
47+
- name: bootstrap
48+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
49+
run: script/bootstrap
50+
51+
# Here we run a deploy. It is "gated" by the IssueOps logic and will only run if the outputs from our branch-deploy step indicate that the workflow should continue
52+
- name: deploy
53+
if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
54+
run: |
55+
set -o pipefail
56+
script/deploy | tee deploy.out
57+
bundle exec ruby script/ci/render_deploy_message.rb
58+
rm deploy.out
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Publish
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request_target:
8+
workflow_dispatch:
9+
workflow_call:
10+
11+
jobs:
12+
build-and-upload:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
steps:
17+
18+
- name: Checkout PR
19+
if: ${{ github.event_name == 'pull_request_target' }}
20+
uses: actions/checkout@v3
21+
with:
22+
ref: ${{ github.event.pull_request.head.ref }}
23+
repository: ${{ github.event.pull_request.head.repo.full_name }}
24+
25+
- name: Checkout
26+
if: ${{ github.event_name != 'pull_request_target' }}
27+
uses: actions/checkout@v3
28+
with:
29+
ref: main
30+
31+
- name: Setup Pages
32+
uses: actions/configure-pages@v1
33+
- name: Use Node.js
34+
uses: actions/setup-node@v3
35+
with:
36+
node-version: 18
37+
cache: npm
38+
- name: Update npm to latest
39+
run: npm i --prefer-online --no-fund --no-audit -g npm@latest
40+
- run: npm -v
41+
- run: npm i --ignore-scripts --no-audit --no-fund --package-lock
42+
- run: npm run build -w www
43+
- name: Upload artifact
44+
uses: actions/upload-pages-artifact@v1
45+
with:
46+
path: './workspaces/www/build'
47+
48+
deploy:
49+
runs-on: ubuntu-latest
50+
needs: build-and-upload
51+
environment:
52+
name: github-pages
53+
url: ${{ steps.deployment.outputs.page_url }}
54+
permissions:
55+
pages: write
56+
id-token: write
57+
outputs:
58+
deployment_url: ${{ steps.deployment.outputs.page_url }}
59+
steps:
60+
- name: Deploy to GitHub Pages
61+
id: deployment
62+
uses: actions/deploy-pages@v1
63+
with:
64+
preview: ${{ github.event_name == 'pull_request_target' }}

ql/test/query-tests/Security/CWE-349/CachePoisoning.expected

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,56 @@
11
edges
2+
| .github/workflows/poc2.yml:28:9:37:6 | Uses Step: branch-deploy | .github/workflows/poc2.yml:37:9:42:6 | Uses Step |
3+
| .github/workflows/poc2.yml:28:9:37:6 | Uses Step: branch-deploy | .github/workflows/poc2.yml:42:9:47:6 | Uses Step |
4+
| .github/workflows/poc2.yml:28:9:37:6 | Uses Step: branch-deploy | .github/workflows/poc2.yml:47:9:52:6 | Run Step |
5+
| .github/workflows/poc2.yml:28:9:37:6 | Uses Step: branch-deploy | .github/workflows/poc2.yml:52:9:58:24 | Run Step |
6+
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step |
7+
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:47:9:52:6 | Run Step |
8+
| .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step |
9+
| .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:47:9:52:6 | Run Step |
10+
| .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step |
11+
| .github/workflows/poc2.yml:47:9:52:6 | Run Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step |
12+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:25:7:31:4 | Uses Step |
13+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:31:7:33:4 | Uses Step |
14+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:33:7:38:4 | Uses Step |
15+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:38:7:40:4 | Run Step |
16+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:40:7:41:4 | Run Step |
17+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
18+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
19+
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
20+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:31:7:33:4 | Uses Step |
21+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:33:7:38:4 | Uses Step |
22+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:38:7:40:4 | Run Step |
23+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:40:7:41:4 | Run Step |
24+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
25+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
26+
| .github/workflows/poc3.yml:25:7:31:4 | Uses Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
27+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:33:7:38:4 | Uses Step |
28+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:38:7:40:4 | Run Step |
29+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:40:7:41:4 | Run Step |
30+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
31+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
32+
| .github/workflows/poc3.yml:31:7:33:4 | Uses Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
33+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:38:7:40:4 | Run Step |
34+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:40:7:41:4 | Run Step |
35+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
36+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
37+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
38+
| .github/workflows/poc3.yml:38:7:40:4 | Run Step | .github/workflows/poc3.yml:40:7:41:4 | Run Step |
39+
| .github/workflows/poc3.yml:38:7:40:4 | Run Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
40+
| .github/workflows/poc3.yml:38:7:40:4 | Run Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
41+
| .github/workflows/poc3.yml:38:7:40:4 | Run Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
42+
| .github/workflows/poc3.yml:40:7:41:4 | Run Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step |
43+
| .github/workflows/poc3.yml:40:7:41:4 | Run Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
44+
| .github/workflows/poc3.yml:40:7:41:4 | Run Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
45+
| .github/workflows/poc3.yml:41:7:42:4 | Run Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step |
46+
| .github/workflows/poc3.yml:41:7:42:4 | Run Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
47+
| .github/workflows/poc3.yml:42:7:43:4 | Run Step | .github/workflows/poc3.yml:43:7:48:2 | Uses Step |
48+
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | .github/workflows/poc.yml:36:9:38:6 | Uses Step |
49+
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | .github/workflows/poc.yml:38:9:43:6 | Uses Step |
50+
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | .github/workflows/poc.yml:43:9:47:2 | Uses Step |
51+
| .github/workflows/poc.yml:36:9:38:6 | Uses Step | .github/workflows/poc.yml:38:9:43:6 | Uses Step |
52+
| .github/workflows/poc.yml:36:9:38:6 | Uses Step | .github/workflows/poc.yml:43:9:47:2 | Uses Step |
53+
| .github/workflows/poc.yml:38:9:43:6 | Uses Step | .github/workflows/poc.yml:43:9:47:2 | Uses Step |
254
| .github/workflows/test1.yml:10:9:13:6 | Uses Step: comment-branch | .github/workflows/test1.yml:13:9:18:6 | Uses Step |
355
| .github/workflows/test1.yml:10:9:13:6 | Uses Step: comment-branch | .github/workflows/test1.yml:18:9:22:6 | Uses Step |
456
| .github/workflows/test1.yml:10:9:13:6 | Uses Step: comment-branch | .github/workflows/test1.yml:22:9:23:21 | Run Step |
@@ -104,6 +156,11 @@ edges
104156
| .github/workflows/test20.yml:41:7:42:4 | Run Step | .github/workflows/test20.yml:43:7:46:39 | Uses Step |
105157
| .github/workflows/test20.yml:42:7:43:4 | Run Step | .github/workflows/test20.yml:43:7:46:39 | Uses Step |
106158
#select
159+
| .github/workflows/poc3.yml:33:7:38:4 | Uses Step | .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:33:7:38:4 | Uses Step | Potential cache poisoning in the context of the default branch |
160+
| .github/workflows/poc3.yml:38:7:40:4 | Run Step | .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:38:7:40:4 | Run Step | Potential cache poisoning in the context of the default branch |
161+
| .github/workflows/poc3.yml:41:7:42:4 | Run Step | .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:41:7:42:4 | Run Step | Potential cache poisoning in the context of the default branch |
162+
| .github/workflows/poc3.yml:42:7:43:4 | Run Step | .github/workflows/poc3.yml:18:7:25:4 | Uses Step | .github/workflows/poc3.yml:42:7:43:4 | Run Step | Potential cache poisoning in the context of the default branch |
163+
| .github/workflows/poc.yml:38:9:43:6 | Uses Step | .github/workflows/poc.yml:30:9:36:6 | Uses Step | .github/workflows/poc.yml:38:9:43:6 | Uses Step | Potential cache poisoning in the context of the default branch |
107164
| .github/workflows/test1.yml:18:9:22:6 | Uses Step | .github/workflows/test1.yml:13:9:18:6 | Uses Step | .github/workflows/test1.yml:18:9:22:6 | Uses Step | Potential cache poisoning in the context of the default branch |
108165
| .github/workflows/test2.yml:14:9:18:6 | Uses Step | .github/workflows/test2.yml:11:9:14:6 | Uses Step | .github/workflows/test2.yml:14:9:18:6 | Uses Step | Potential cache poisoning in the context of the default branch |
109166
| .github/workflows/test3.yml:14:9:22:6 | Uses Step | .github/workflows/test3.yml:11:9:14:6 | Uses Step | .github/workflows/test3.yml:14:9:22:6 | Uses Step | Potential cache poisoning in the context of the default branch |
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
6+
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
7+
name: Deploy Jekyll site to Pages preview environment
8+
on:
9+
# Runs on pull requests targeting the default branch
10+
pull_request_target:
11+
branches: ["main"]
12+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13+
permissions:
14+
contents: read
15+
pages: write
16+
id-token: write
17+
# Allow only one concurrent deployment per PR, skipping runs queued between the run in-progress and latest queued.
18+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
19+
concurrency:
20+
group: 'pages-preview @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
21+
cancel-in-progress: false
22+
jobs:
23+
# Build job
24+
build:
25+
# Limit permissions of the GITHUB_TOKEN for untrusted code
26+
permissions:
27+
contents: read
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
32+
with:
33+
# For PRs make sure to checkout the PR branch
34+
ref: ${{ github.event.pull_request.head.ref }}
35+
repository: ${{ github.event.pull_request.head.repo.full_name }}
36+
- name: Setup Pages
37+
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
38+
- name: Build with Jekyll
39+
uses: actions/jekyll-build-pages@b178f9334b208360999a0a57b523613563698c66 # v1
40+
with:
41+
source: ./
42+
destination: ./_site
43+
- name: Upload artifact
44+
# Automatically uploads an artifact from the './_site' directory by default
45+
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
46+
# Deployment job
47+
deploy:
48+
environment:
49+
name: 'Pages Preview'
50+
url: ${{ steps.deployment.outputs.page_url }}
51+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
52+
permissions:
53+
contents: read
54+
pages: write
55+
id-token: write
56+
runs-on: ubuntu-latest
57+
needs: build
58+
steps:
59+
- name: Deploy to GitHub Pages
60+
id: deployment
61+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
62+
with:
63+
preview: 'true'
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: branch-deploy
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
# Permissions needed for reacting and adding comments for IssueOps commands
8+
permissions:
9+
pull-requests: write
10+
deployments: write
11+
contents: write
12+
checks: read
13+
14+
jobs:
15+
branch-deploy:
16+
name: branch-deploy
17+
if: # only run on pull request comments and very specific comment body string as defined in our branch-deploy settings
18+
${{ github.event.issue.pull_request &&
19+
(startsWith(github.event.comment.body, '.deploy') ||
20+
startsWith(github.event.comment.body, '.noop') ||
21+
startsWith(github.event.comment.body, '.lock') ||
22+
startsWith(github.event.comment.body, '.help') ||
23+
startsWith(github.event.comment.body, '.wcid') ||
24+
startsWith(github.event.comment.body, '.unlock')) }}
25+
runs-on: ubuntu-latest
26+
27+
steps:
28+
- name: branch-deploy
29+
id: branch-deploy
30+
uses: github/branch-deploy@v9
31+
with:
32+
trigger: ".deploy"
33+
environment: "production"
34+
sticky_locks: "true" # https://github.com/github/branch-deploy/blob/1f6516ef5092890ce75d9e97ca7cbdb628e38bdd/docs/hubot-style-deployment-locks.md
35+
36+
# Check out the ref from the output of the IssueOps command
37+
- uses: actions/checkout@v4
38+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
39+
with:
40+
ref: ${{ steps.branch-deploy.outputs.ref }}
41+
42+
- uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 # [email protected]
43+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
44+
with:
45+
bundler-cache: true
46+
47+
- name: bootstrap
48+
if: ${{ steps.branch-deploy.outputs.continue == 'true' }}
49+
run: script/bootstrap
50+
51+
# Here we run a deploy. It is "gated" by the IssueOps logic and will only run if the outputs from our branch-deploy step indicate that the workflow should continue
52+
- name: deploy
53+
if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
54+
run: |
55+
set -o pipefail
56+
script/deploy | tee deploy.out
57+
bundle exec ruby script/ci/render_deploy_message.rb
58+
rm deploy.out

0 commit comments

Comments
 (0)