Skip to content

Commit

Permalink
Merge pull request #6742 from Checkmarx/run_injection_query
Browse files Browse the repository at this point in the history
feat(query): github workflows run injection query
  • Loading branch information
asofsilva authored Sep 27, 2023
2 parents 23bd758 + 75d1ec4 commit 2e88de4
Show file tree
Hide file tree
Showing 18 changed files with 488 additions and 1 deletion.
11 changes: 11 additions & 0 deletions assets/queries/cicd/github/run_block_injection/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "20f14e1a-a899-4e79-9f09-b6a84cd4649b",
"queryName": "Run Block Injection",
"severity": "HIGH",
"category": "Insecure Configurations",
"descriptionText": "GitHub Actions workflows can be triggered by a variety of events. Every workflow trigger is provided with a GitHub context that contains information about the triggering event, such as which user triggered it, the branch name, and other event context details. Some of this event data, like the base repository name, hash value of a changeset, or pull request number, is unlikely to be controlled or used for injection by the user that triggered the event.",
"descriptionUrl": "https://securitylab.github.com/research/github-actions-untrusted-input/",
"platform": "CICD",
"descriptionID": "02044a75",
"cloudProvider": "common"
}
186 changes: 186 additions & 0 deletions assets/queries/cicd/github/run_block_injection/query.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package Cx

import data.generic.common as common_lib

CxPolicy[result] {

input.document[i].on["pull_request_target"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.head_ref",
"github.event.pull_request.body",
"github.event.pull_request.head.label",
"github.event.pull_request.head.ref",
"github.event.pull_request.head.repo.default_branch",
"github.event.pull_request.head.repo.description",
"github.event.pull_request.head.repo.homepage",
"github.event.pull_request.title"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["issues"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.event.issue.body",
"github.event.issue.title"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["issue_comment"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.event.comment.body",
"github.event.issue.body",
"github.event.issue.title"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["discussion"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.event.discussion.body",
"github.event.discussion.title"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["discussion_comment"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.event.comment.body",
"github.event.discussion.body",
"github.event.discussion.title"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["workflow_run"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.event.workflow.path",
"github.event.workflow_run.head_branch",
"github.event.workflow_run.head_commit.author.email",
"github.event.workflow_run.head_commit.author.name",
"github.event.workflow_run.head_commit.message",
"github.event.workflow_run.head_repository.description"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}

CxPolicy[result] {

input.document[i].on["author"]
run := input.document[i].jobs[j].steps[k].run

patterns := [
"github.*.authors.name",
"github.*.authors.email"
]

matched = containsPatterns(run, patterns)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("run={{%s}}", [run]),
"issueType": "IncorrectValue",
"keyExpectedValue": "Run block does not contain dangerous input controlled by user.",
"keyActualValue": "Run block contains dangerous input controlled by user.",
"searchLine": common_lib.build_search_line(["jobs", j, "steps", k, "run"],[]),
"searchValue": matched[m]
}
}



containsPatterns(str, patterns) = matched {
matched := {pattern |
pattern := patterns[_]
regex.match(pattern, str)
}
}

29 changes: 29 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: check-go-coverage

on:
pull_request_target:
branches: [master]

jobs:
coverage:
name: Check Go coverage
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go 1.20.x
uses: actions/setup-go@v4
with:
go-version: 1.20.x
- name: Run test metrics script
id: testcov
run: |
make test-coverage-report | tee test-results
echo "coverage=$(cat test-results | grep "Total coverage: " test-results | cut -d ":" -f 2 | bc)" >> $GITHUB_ENV
- name: Checks if Go coverage is at least 80%
if: env.coverage < 80
run: |
echo "Go coverage is lower than 80%: ${{ env.coverage }}%"
exit 1
15 changes: 15 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Issue Workflow

on:
issues:
types:
- opened

jobs:
process_issue:
runs-on: ubuntu-latest
steps:
- name: Greet the New Issue
run: |
# Echo a simple sentence
echo "Hello, a new issue has been opened!"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Discussion Workflow

on:
discussion:
types:
- created

jobs:
process_discussion:
runs-on: ubuntu-latest
steps:
- name: Greet the New Discussion
run: |
echo "Hello, a new discussion has been created!"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative4.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Issue Comment Workflow

on:
issue_comment:
types:
- created

jobs:
process_issue_comment:
runs-on: ubuntu-latest
steps:
- name: Greet the New Issue Comment
run: |
echo "Hello, a new issue comment has been created!"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative5.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Discussion Comment Workflow

on:
discussion_comment:
types:
- created

jobs:
process_discussion_comment:
runs-on: ubuntu-latest
steps:
- name: Greet the New Discussion Comment
run: |
echo "Hello, a new discussion comment has been created!"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative6.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Author Workflow

on:
author:
types:
- created

jobs:
process_author:
runs-on: ubuntu-latest
steps:
- name: Greet the New Author
run: |
echo "Hello, a new author has been created!"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/negative7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Workflow Run Workflow

on:
workflow_run:
workflows:
- "Your Workflow Name" # Replace with the name of your specific workflow

jobs:
process_workflow_run:
runs-on: ubuntu-latest
steps:
- name: Greet the New Workflow Run
run: |
echo "Hello, a new workflow run has started for 'Your Workflow Name'!"
39 changes: 39 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/positive1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Web Page To Markdown
on:
issues:
types: [opened]
jobs:
WebPageToMarkdown:
runs-on: ubuntu-latest
steps:
- name: Does the issue need to be converted to markdown
run: |
if [ "${{ github.event.issue.body }}" ]; then
if [[ "${{ github.event.issue.title }}" =~ ^\[Auto\]* ]]; then
:
else
echo "This issue does not need to generate a markdown file." 1>&2
exit 1;
fi;
else
echo "The description of the issue is empty." 1>&2
exit 1;
fi;
shell: bash
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
- name: Crawl pages and generate Markdown files
uses: freeCodeCamp-China/[email protected]
with:
newsLink: '${{ github.event.issue.Body }}'
markDownFilePath: './chinese/articles/'
githubToken: ${{ github.token }}
- name: Git Auto Commit
uses: stefanzweifel/[email protected]
with:
commit_message: '${{ github.event.issue.title }}'
file_pattern: chinese/articles/*.md
commit_user_name: PageToMarkdown Bot
commit_user_email: [email protected]
15 changes: 15 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/positive2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Pull Request Workflow

on:
pull_request_target:
types:
- opened

jobs:
process_pull_request:
runs-on: ubuntu-latest
steps:
- name: Echo Pull Request Body
run: |
echo "Pull Request Body: ${{ github.event.pull_request.body }}"
14 changes: 14 additions & 0 deletions assets/queries/cicd/github/run_block_injection/test/positive3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Issue Comment Workflow

on:
issue_comment:
types:
- created

jobs:
process_issue_comment:
runs-on: ubuntu-latest
steps:
- name: Echo Issue Comment Body
run: |
echo "Issue Comment Body: ${{ github.event.comment.body }}"
Loading

0 comments on commit 2e88de4

Please sign in to comment.