-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17401 from pwntester/js/actions/secrets-in-artifacts
Javascript: Query to detect GITHUB_TOKEN leaked in artifacts
- Loading branch information
Showing
8 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
30 changes: 30 additions & 0 deletions
30
javascript/ql/src/Security/CWE-312/ActionsArtifactLeak.qhelp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<!DOCTYPE qhelp PUBLIC | ||
"-//Semmle//qhelp//EN" | ||
"qhelp.dtd"> | ||
<qhelp> | ||
<overview> | ||
<p> | ||
Sensitive information included in a GitHub Actions artifact can allow an attacker to access | ||
the sensitive information if the artifact is published. | ||
</p> | ||
</overview> | ||
|
||
<recommendation> | ||
<p> | ||
Only store information that is meant to be publicly available in a GitHub Actions artifact. | ||
</p> | ||
</recommendation> | ||
|
||
<example> | ||
<p> | ||
The following example uses <code>actions/checkout</code> to checkout code which stores the GITHUB_TOKEN in the `.git/config` file | ||
and then stores the contents of the `.git` repository into the artifact: | ||
</p> | ||
<sample src="examples/actions-artifact-leak.yml"/> | ||
<p> | ||
The issue has been fixed below, where the <code>actions/upload-artifact</code> uses a version (v4+) which does not include hidden files or | ||
directories into the artifact. | ||
</p> | ||
<sample src="examples/actions-artifact-leak-fixed.yml"/> | ||
</example> | ||
</qhelp> |
111 changes: 111 additions & 0 deletions
111
javascript/ql/src/Security/CWE-312/ActionsArtifactLeak.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* @name Storage of sensitive information in GitHub Actions artifact | ||
* @description Including sensitive information in a GitHub Actions artifact can | ||
* expose it to an attacker. | ||
* @kind problem | ||
* @problem.severity error | ||
* @security-severity 7.5 | ||
* @precision high | ||
* @id js/actions/actions-artifact-leak | ||
* @tags security | ||
* external/cwe/cwe-312 | ||
* external/cwe/cwe-315 | ||
* external/cwe/cwe-359 | ||
*/ | ||
|
||
import javascript | ||
import semmle.javascript.Actions | ||
|
||
/** | ||
* A step that uses `actions/checkout` action. | ||
*/ | ||
class ActionsCheckoutStep extends Actions::Step { | ||
ActionsCheckoutStep() { this.getUses().getGitHubRepository() = "actions/checkout" } | ||
} | ||
|
||
/** | ||
* A `with:`/`persist-credentials` field sibling to `uses: actions/checkout`. | ||
*/ | ||
class ActionsCheckoutWithPersistCredentials extends YamlNode, YamlScalar { | ||
ActionsCheckoutStep step; | ||
|
||
ActionsCheckoutWithPersistCredentials() { | ||
step.lookup("with").(YamlMapping).lookup("persist-credentials") = this | ||
} | ||
|
||
/** Gets the step this field belongs to. */ | ||
ActionsCheckoutStep getStep() { result = step } | ||
} | ||
|
||
/** | ||
* A `with:`/`path` field sibling to `uses: actions/checkout`. | ||
*/ | ||
class ActionsCheckoutWithPath extends YamlNode, YamlString { | ||
ActionsCheckoutStep step; | ||
|
||
ActionsCheckoutWithPath() { step.lookup("with").(YamlMapping).lookup("path") = this } | ||
|
||
/** Gets the step this field belongs to. */ | ||
ActionsCheckoutStep getStep() { result = step } | ||
} | ||
|
||
/** | ||
* A step that uses `actions/upload-artifact` action. | ||
*/ | ||
class ActionsUploadArtifactStep extends Actions::Step { | ||
ActionsUploadArtifactStep() { this.getUses().getGitHubRepository() = "actions/upload-artifact" } | ||
} | ||
|
||
/** | ||
* A `with:`/`path` field sibling to `uses: actions/upload-artifact`. | ||
*/ | ||
class ActionsUploadArtifactWithPath extends YamlNode, YamlString { | ||
ActionsUploadArtifactStep step; | ||
|
||
ActionsUploadArtifactWithPath() { step.lookup("with").(YamlMapping).lookup("path") = this } | ||
|
||
/** Gets the step this field belongs to. */ | ||
ActionsUploadArtifactStep getStep() { result = step } | ||
} | ||
|
||
from ActionsCheckoutStep checkout, ActionsUploadArtifactStep upload, Actions::Job job, int i, int j | ||
where | ||
checkout.getJob() = job and | ||
upload.getJob() = job and | ||
job.getStep(i) = checkout and | ||
job.getStep(j) = upload and | ||
j = i + 1 and | ||
upload.getUses().getVersion() = | ||
[ | ||
"v4.3.6", "834a144ee995460fba8ed112a2fc961b36a5ec5a", // | ||
"v4.3.5", "89ef406dd8d7e03cfd12d9e0a4a378f454709029", // | ||
"v4.3.4", "0b2256b8c012f0828dc542b3febcab082c67f72b", // | ||
"v4.3.3", "65462800fd760344b1a7b4382951275a0abb4808", // | ||
"v4.3.2", "1746f4ab65b179e0ea60a494b83293b640dd5bba", // | ||
"v4.3.1", "5d5d22a31266ced268874388b861e4b58bb5c2f3", // | ||
"v4.3.0", "26f96dfa697d77e81fd5907df203aa23a56210a8", // | ||
"v4.2.0", "694cdabd8bdb0f10b2cea11669e1bf5453eed0a6", // | ||
"v4.1.0", "1eb3cb2b3e0f29609092a73eb033bb759a334595", // | ||
"v4.0.0", "c7d193f32edcb7bfad88892161225aeda64e9392", // | ||
] and | ||
( | ||
not exists(ActionsCheckoutWithPersistCredentials persist | persist.getStep() = checkout) | ||
or | ||
exists(ActionsCheckoutWithPersistCredentials persist | | ||
persist.getStep() = checkout and | ||
persist.getValue() = "true" | ||
) | ||
) and | ||
( | ||
not exists(ActionsCheckoutWithPath path | path.getStep() = checkout) and | ||
exists(ActionsUploadArtifactWithPath path | | ||
path.getStep() = upload and path.getValue() = [".", "*"] | ||
) | ||
or | ||
exists(ActionsCheckoutWithPath checkout_path, ActionsUploadArtifactWithPath upload_path | | ||
checkout_path.getValue() + ["", "/*"] = upload_path.getValue() and | ||
checkout_path.getStep() = checkout and | ||
upload_path.getStep() = upload | ||
) | ||
) | ||
select upload, "A secret may be exposed in an artifact." |
14 changes: 14 additions & 0 deletions
14
javascript/ql/src/Security/CWE-312/examples/actions-artifact-leak-fixed.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: secrets-in-artifacts | ||
on: | ||
pull_request: | ||
jobs: | ||
a-job: # NOT VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: file | ||
path: . | ||
|
13 changes: 13 additions & 0 deletions
13
javascript/ql/src/Security/CWE-312/examples/actions-artifact-leak.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
name: secrets-in-artifacts | ||
on: | ||
pull_request: | ||
jobs: | ||
a-job: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: . |
5 changes: 5 additions & 0 deletions
5
javascript/ql/src/change-notes/2024-09-06-new-actions-artifact-leak-query.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
category: majorAnalysis | ||
--- | ||
|
||
- Added a new query (`js/actions/actions-artifact-leak`) to detect GitHub Actions artifacts that may leak the GITHUB_TOKEN token. |
87 changes: 87 additions & 0 deletions
87
javascript/ql/test/query-tests/Security/CWE-312/.github/workflows/test.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
name: secrets-in-artifacts | ||
on: | ||
pull_request: | ||
jobs: | ||
test1: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: . | ||
test2: # NOT VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: file | ||
path: . | ||
test3: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: "*" | ||
test4: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
path: foo | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: foo | ||
test5: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
path: foo | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: foo/* | ||
test6: # NOT VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
path: pr | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: foo | ||
test7: # NOT VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
persist-credentials: false | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: . | ||
test8: # VULNERABLE | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
persist-credentials: true | ||
- name: "Upload artifact" | ||
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 | ||
with: | ||
name: file | ||
path: . | ||
|
5 changes: 5 additions & 0 deletions
5
javascript/ql/test/query-tests/Security/CWE-312/ActionsArtifactLeak.expected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
| .github/workflows/test.yml:9:9:14:2 | name: " ... tifact" | A secret may be exposed in an artifact. | | ||
| .github/workflows/test.yml:27:9:32:2 | name: " ... tifact" | A secret may be exposed in an artifact. | | ||
| .github/workflows/test.yml:38:9:43:2 | name: " ... tifact" | A secret may be exposed in an artifact. | | ||
| .github/workflows/test.yml:49:9:54:2 | name: " ... tifact" | A secret may be exposed in an artifact. | | ||
| .github/workflows/test.yml:82:9:86:18 | name: " ... tifact" | A secret may be exposed in an artifact. | |
1 change: 1 addition & 0 deletions
1
javascript/ql/test/query-tests/Security/CWE-312/ActionsArtifactLeak.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Security/CWE-312/ActionsArtifactLeak.ql |