mirror of
https://github.com/github/codeql.git
synced 2026-04-24 08:15:14 +02:00
ruby: add MaD model for permissions needed by actions
Use this to suggest minimal set of nedded permissions
This commit is contained in:
@@ -242,6 +242,8 @@ class Step extends AstNode instanceof StepImpl {
|
||||
|
||||
If getIf() { result = super.getIf() }
|
||||
|
||||
AstNode getUses() { result = super.getUses() }
|
||||
|
||||
StepsContainer getContainer() { result = super.getContainer() }
|
||||
|
||||
Step getNextStep() { result = super.getNextStep() }
|
||||
|
||||
@@ -1194,6 +1194,8 @@ class StepImpl extends AstNodeImpl, TStepNode {
|
||||
/** Gets the value of the `if` field in this step, if any. */
|
||||
IfImpl getIf() { result.getNode() = n.lookup("if") }
|
||||
|
||||
AstNodeImpl getUses() { result.getNode() = n.lookup("uses") }
|
||||
|
||||
/** Gets the Runs or LocalJob that this step is in. */
|
||||
StepsContainerImpl getContainer() {
|
||||
result = this.getParentNode().(RunsImpl) or
|
||||
|
||||
@@ -154,3 +154,13 @@ predicate untrustedGitCommandDataModel(string cmd_regex, string flag) {
|
||||
predicate untrustedGhCommandDataModel(string cmd_regex, string flag) {
|
||||
Extensions::untrustedGhCommandDataModel(cmd_regex, flag)
|
||||
}
|
||||
|
||||
/**
|
||||
* MaD models for permissions needed by actions
|
||||
* Fields:
|
||||
* - action: action name
|
||||
* - permission: permission name
|
||||
*/
|
||||
predicate actionsPermissionsDataModel(string action, string permission) {
|
||||
Extensions::actionsPermissionsDataModel(action, permission)
|
||||
}
|
||||
|
||||
@@ -77,3 +77,8 @@ extensible predicate untrustedGitCommandDataModel(string cmd_regex, string flag)
|
||||
* Holds for gh commands that may introduce untrusted data
|
||||
*/
|
||||
extensible predicate untrustedGhCommandDataModel(string cmd_regex, string flag);
|
||||
|
||||
/**
|
||||
* Holds if `action` needs `permission` to run.
|
||||
*/
|
||||
extensible predicate actionsPermissionsDataModel(string action, string permission);
|
||||
|
||||
37
actions/ql/lib/ext/config/actions_permissions.yml
Normal file
37
actions/ql/lib/ext/config/actions_permissions.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/actions-all
|
||||
extensible: actionsPermissionsDataModel
|
||||
data:
|
||||
- ["actions/checkout", "contents: read"]
|
||||
- ["actions/setup-node", "contents: read"]
|
||||
- ["actions/setup-python", "contents: read"]
|
||||
- ["actions/setup-java", "contents: read"]
|
||||
- ["actions/setup-go", "contents: read"]
|
||||
- ["actions/setup-dotnet", "contents: read"]
|
||||
- ["actions/labeler", "contents: read"]
|
||||
- ["actions/labeler", "pull-requests: write"]
|
||||
- ["actions/attest", "id-token: write"]
|
||||
- ["actions/attest", "attestations: write"]
|
||||
# No permissions needed for actions/add-to-project
|
||||
- ["actions/dependency-review-action", "contents: read"]
|
||||
- ["actions/attest-sbom", "id-token: write"]
|
||||
- ["actions/attest-sbom", "attestations: write"]
|
||||
- ["actions/stale", "contents: write"]
|
||||
- ["actions/stale", "issues: write"]
|
||||
- ["actions/stale", "pull-requests: write"]
|
||||
- ["actions/attest-build-provenance", "id-token: write"]
|
||||
- ["actions/attest-build-provenance", "attestations: write"]
|
||||
- ["actions/jekyll-build-pages", "contents: read"]
|
||||
- ["actions/jekyll-build-pages", "pages: write"]
|
||||
- ["actions/jekyll-build-pages", "id-token: write"]
|
||||
- ["actions/publish-action", "contents: write"]
|
||||
- ["actions/versions-package-tools", "contents: read"]
|
||||
- ["actions/versions-package-tools", "actions: read"]
|
||||
- ["actions/reusable-workflows", "contents: read"]
|
||||
- ["actions/reusable-workflows", "actions: read"]
|
||||
# TODO: Add permissions for actions/download-artifact
|
||||
# TODO: Add permissions for actions/upload-artifact
|
||||
# TODO: Add permissions for actions/cache
|
||||
|
||||
|
||||
@@ -14,7 +14,28 @@
|
||||
|
||||
import actions
|
||||
|
||||
from Job job
|
||||
Step stepInJob(Job job) { result = job.(LocalJob).getAStep() }
|
||||
|
||||
bindingset[fullActionSelector]
|
||||
string versionedAction(string fullActionSelector) {
|
||||
result = fullActionSelector.substring(0, fullActionSelector.indexOf("@"))
|
||||
or
|
||||
not exists(fullActionSelector.indexOf("@")) and
|
||||
result = fullActionSelector
|
||||
}
|
||||
|
||||
string stepUses(Step step) { result = step.getUses().(ScalarValue).getValue() }
|
||||
|
||||
string jobNeedsPersmission(Job job) {
|
||||
actionsPermissionsDataModel(versionedAction(stepUses(stepInJob(job))), result)
|
||||
}
|
||||
|
||||
string permissionsForJob(Job job) {
|
||||
result =
|
||||
"{" + concat(string permission | permission = jobNeedsPersmission(job) | permission, ", ") + "}"
|
||||
}
|
||||
|
||||
from Job job, string permissions
|
||||
where
|
||||
not exists(job.getPermissions()) and
|
||||
not exists(job.getEnclosingWorkflow().getPermissions()) and
|
||||
@@ -22,5 +43,7 @@ where
|
||||
exists(Event e |
|
||||
e = job.getATriggerEvent() and
|
||||
not e.getName() = "workflow_call"
|
||||
)
|
||||
select job, "Actions Job or Workflow does not set permissions"
|
||||
) and
|
||||
permissions = permissionsForJob(job)
|
||||
select job,
|
||||
"Actions Job or Workflow does not set permissions. A minimal set might be " + permissions
|
||||
|
||||
13
actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml
vendored
Normal file
13
actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/jekyll-build-pages
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| .github/workflows/perms1.yml:6:5:9:32 | Job: build | Actions Job or Workflow does not set permissions |
|
||||
| .github/workflows/perms2.yml:6:5:10:2 | Job: build | Actions Job or Workflow does not set permissions |
|
||||
| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions Job or Workflow does not set permissions |
|
||||
| .github/workflows/perms1.yml:6:5:9:32 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
|
||||
| .github/workflows/perms2.yml:6:5:10:2 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
|
||||
| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
|
||||
| .github/workflows/perms6.yml:7:5:11:39 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read, id-token: write, pages: write} |
|
||||
|
||||
Reference in New Issue
Block a user