mirror of
https://github.com/github/codeql.git
synced 2026-01-04 10:10:20 +01:00
unversioned immutable actions wip
This commit is contained in:
@@ -119,6 +119,17 @@ predicate vulnerableActionsDataModel(
|
||||
Extensions::vulnerableActionsDataModel(action, vulnerable_version, vulnerable_sha, fixed_version)
|
||||
}
|
||||
|
||||
/**
|
||||
* MaD models for vulnerable actions
|
||||
* Fields:
|
||||
* - action: action name
|
||||
*/
|
||||
predicate immutableActionsDataModel(
|
||||
string action
|
||||
) {
|
||||
Extensions::immutableActionsDataModel(action)
|
||||
}
|
||||
|
||||
/**
|
||||
* MaD models for untrusted git commands
|
||||
* Fields:
|
||||
|
||||
@@ -58,6 +58,13 @@ extensible predicate vulnerableActionsDataModel(
|
||||
string action, string vulnerable_version, string vulnerable_sha, string fixed_version
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds for actions that are known to be immutable.
|
||||
*/
|
||||
extensible predicate immutableActionsDataModel(
|
||||
string action
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds for git commands that may introduce untrusted data when called on an attacker controlled branch.
|
||||
*/
|
||||
|
||||
22
ql/lib/ext/config/immutable_actions.yml
Normal file
22
ql/lib/ext/config/immutable_actions.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: github/actions-all
|
||||
extensible: immutableActionsDataModel
|
||||
data:
|
||||
- ["actions/checkout"]
|
||||
- ["actions/cache"]
|
||||
- ["actions/setup-node"]
|
||||
- ["actions/upload-artifact"]
|
||||
- ["actions/setup-python"]
|
||||
- ["actions/download-artifact"]
|
||||
- ["actions/github-script"]
|
||||
- ["actions/setup-java"]
|
||||
- ["actions/setup-go"]
|
||||
- ["actions/upload-pages-artifact"]
|
||||
- ["actions/deploy-pages"]
|
||||
- ["actions/setup-dotnet"]
|
||||
- ["actions/stale"]
|
||||
- ["actions/labeler"]
|
||||
- ["actions/create-github-app-token"]
|
||||
- ["actions/configure-pages"]
|
||||
- ["octokit/request-action"]
|
||||
27
ql/src/Security/CWE-829/UnversionedImmutableAction.md
Normal file
27
ql/src/Security/CWE-829/UnversionedImmutableAction.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Unpinned tag for 3rd party Action in workflow
|
||||
|
||||
## Description
|
||||
|
||||
Using a tag for a 3rd party Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack.
|
||||
|
||||
## Recommendations
|
||||
|
||||
Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload. When selecting a SHA, you should verify it is from the action's repository and not a repository fork.
|
||||
|
||||
## Examples
|
||||
|
||||
### Incorrect Usage
|
||||
|
||||
```yaml
|
||||
- uses: tj-actions/changed-files@v44
|
||||
```
|
||||
|
||||
### Correct Usage
|
||||
|
||||
```yaml
|
||||
- uses: tj-actions/changed-files@c65cd883420fd2eb864698a825fc4162dd94482c # v44
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Using third-party actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-third-party-actions)
|
||||
38
ql/src/Security/CWE-829/UnversionedImmutableAction.ql
Normal file
38
ql/src/Security/CWE-829/UnversionedImmutableAction.ql
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @name Unversioned Immutable Action
|
||||
* @description Using an Immutable Action without a semantic version tag opts out of the protections of Immutable Action
|
||||
* @kind problem
|
||||
* @security-severity 5.0
|
||||
* @problem.severity recommendation
|
||||
* @precision high
|
||||
* @id actions/unversioned-immutable-action
|
||||
* @tags security
|
||||
* actions
|
||||
* external/cwe/cwe-829
|
||||
*/
|
||||
|
||||
import actions
|
||||
|
||||
bindingset[version]
|
||||
private predicate isSemanticVersioned(string version) { version.regexpMatch("^v[0-9]+(\\.[0-9]+)*(\\.[xX])?$") }
|
||||
|
||||
bindingset[repo]
|
||||
private predicate isTrustedOrg(string repo) {
|
||||
exists(string org | org in ["actions", "github", "advanced-security", "octokit"] | repo.matches(org + "/%"))
|
||||
}
|
||||
|
||||
from UsesStep uses, string repo, string version, Workflow workflow, string name
|
||||
where
|
||||
uses.getCallee() = repo and
|
||||
uses.getEnclosingWorkflow() = workflow and
|
||||
(
|
||||
workflow.getName() = name
|
||||
or
|
||||
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
|
||||
) and
|
||||
uses.getVersion() = version and
|
||||
not isTrustedOrg(repo) and
|
||||
not isPinnedCommit(version)
|
||||
select uses.getCalleeNode(),
|
||||
"Unpinned 3rd party Action '" + name + "' step $@ uses '" + repo + "' with ref '" + version +
|
||||
"', not a pinned commit hash", uses, uses.toString()
|
||||
Reference in New Issue
Block a user