Merge pull request #19166 from yoff/actions/add-actions-permissions-MaD-model

actions: add MaD model for permissions needed by actions
This commit is contained in:
Aditya Sharad
2025-04-03 01:24:04 +05:30
committed by GitHub
8 changed files with 108 additions and 6 deletions

View File

@@ -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, e.g. `actions/checkout`
* - permission: permission name, e.g. `contents: read`
*/
predicate actionsPermissionsDataModel(string action, string permission) {
Extensions::actionsPermissionsDataModel(action, permission)
}

View File

@@ -77,3 +77,14 @@ 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.
* - 'action' is the name of the action without any version information.
* E.g. for the action selector `actions/checkout@v2`, `action` is `actions/checkout`.
* - `permission` is of the form `scope-name: read|write`, for example `contents: read`.
* - see https://github.com/actions/checkout?tab=readme-ov-file#recommended-permissions
* for an example of recommended permissions.
* - see https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token for documentation of token permissions.
*/
extensible predicate actionsPermissionsDataModel(string action, string permission);

View 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

View File

@@ -14,7 +14,19 @@
import actions
from Job job
Step stepInJob(Job job) { result = job.(LocalJob).getAStep() }
string jobNeedsPermission(Job job) {
actionsPermissionsDataModel(stepInJob(job).(UsesStep).getCallee(), result)
}
/** Gets a suggestion for the minimal token permissions for `job`, as a JSON string. */
string permissionsForJob(Job job) {
result =
"{" + concat(string permission | permission = jobNeedsPermission(job) | permission, ", ") + "}"
}
from Job job, string permissions
where
not exists(job.getPermissions()) and
not exists(job.getEnclosingWorkflow().getPermissions()) and
@@ -22,5 +34,8 @@ 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 limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: "
+ permissions

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Alerts produced by the query `actions/missing-workflow-permissions` now include a minimal set of recommended permissions in the alert message, based on well-known actions seen within the workflow file.

View 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

View File

@@ -0,0 +1,10 @@
on:
workflow_call:
workflow_dispatch:
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v2

View File

@@ -1,3 +1,5 @@
| .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 limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read} |
| .github/workflows/perms2.yml:6:5:10:2 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read} |
| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read} |
| .github/workflows/perms6.yml:7:5:11:39 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read, id-token: write, pages: write} |
| .github/workflows/perms7.yml:7:5:10:38 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {} |