add codeql actions query with data extension sample

This commit is contained in:
Michael Hohn
2025-06-25 14:04:25 -07:00
committed by =Michael Hohn
parent 8ccd26872a
commit 3ce1d8d252
10 changed files with 133 additions and 25 deletions

View File

@@ -0,0 +1,61 @@
// /**
// * @name Empty block
// * @kind problem
// * @problem.severity warning
// * @id go/example/empty-block
// */
// import actions
// select 1
/**
* @name Unpinned tag for a non-immutable Action in workflow
* @description Using a tag for a non-immutable Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack.
* @kind problem
* @security-severity 5.0
* @problem.severity warning
* @precision medium
* @id actions/unpinned-tag
* @tags security
* actions
* external/cwe/cwe-829
*/
import actions
import codeql.actions.security.UseOfUnversionedImmutableAction
bindingset[version]
private predicate isPinnedCommit(string version) { version.regexpMatch("^[A-Fa-f0-9]{40}$") }
bindingset[nwo]
private predicate isTrustedOwner(string nwo) {
// Gets the segment before the first '/' in the name with owner(nwo) string
trustedActionsOwnerDataModel(nwo.substring(0, nwo.indexOf("/")))
}
bindingset[version]
private predicate isPinnedContainer(string version) {
version.regexpMatch("^sha256:[A-Fa-f0-9]{64}$")
}
bindingset[nwo]
private predicate isContainerImage(string nwo) { nwo.regexpMatch("^docker://.+") }
from UsesStep uses, string nwo, string version, Workflow workflow, string name
where
uses.getCallee() = nwo 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 isTrustedOwner(nwo) and
not (if isContainerImage(nwo) then isPinnedContainer(version) else isPinnedCommit(version)) and
not isImmutableAction(uses, nwo)
select uses.getCalleeNode(),
"Unpinned 3rd party Action '" + name + "' step $@ uses '" + nwo + "' with ref '" + version +
"', not a pinned commit hash", uses, uses.toString()

View File

@@ -0,0 +1,9 @@
extensions:
- addsTo:
pack: codeql/actions-all
extensible: trustedActionsOwnerDataModel
data:
- ["actions"]
- ["github"]
- ["advanced-security"]
- ["company-x"]

View File

@@ -0,0 +1,11 @@
# Change 'getting-started' to the name of a user or organization that you have write access to.
name: getting-started/codeql-extra-queries-actions
version: 0.0.0
extractor: actions
dependencies:
# This uses the latest version of the codeql/go-all library.
# You may want to change to a more precise semver string.
codeql/actions-all: "*"
dataExtensions:
- exclusions.yml

View File

@@ -0,0 +1,11 @@
# tests/tests.testproj/.github/workflows/ci.yml
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@latest # Unpinned — should be flagged

View File

@@ -0,0 +1 @@
none

View File

@@ -0,0 +1 @@
UnpinnedActionsTag.ql

View File

@@ -0,0 +1,11 @@
# tests/tests.testproj/.github/workflows/ci.yml
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@latest # Unpinned — should be flagged

View File

@@ -0,0 +1,12 @@
name: Untrusted workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Untrusted step
uses: dodgycorp/bad-action@latest # This should trigger the query

View File

@@ -0,0 +1,12 @@
name: Untrusted workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Untrusted step
uses: company-X/bad-action@latest # This should trigger the query