From 436be5c20bdd0790c170c70815e8bcd431f6f6c9 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 10 Jul 2026 19:36:53 -0400 Subject: [PATCH 1/7] Add implementation for technique to customize environmentCheck in actions queries --- actions/ql/lib/actions.qll | 2 ++ actions/ql/lib/codeql/actions/config/Config.qll | 16 ++++++++++++++++ .../codeql/actions/config/ConfigExtensions.qll | 12 ++++++++++++ .../codeql/actions/security/ControlChecks.qll | 14 +++++++++++++- actions/ql/lib/ext/config/customize_checks.yml | 9 +++++++++ .../ql/lib/ext/config/deployment_environment.yml | 6 ++++++ 6 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 actions/ql/lib/ext/config/customize_checks.yml create mode 100644 actions/ql/lib/ext/config/deployment_environment.yml diff --git a/actions/ql/lib/actions.qll b/actions/ql/lib/actions.qll index 2c1d1cee9259..a1ee60b1694d 100644 --- a/actions/ql/lib/actions.qll +++ b/actions/ql/lib/actions.qll @@ -1 +1,3 @@ import codeql.actions.Ast + +abstract class CustomEnvEnable extends Environment { } diff --git a/actions/ql/lib/codeql/actions/config/Config.qll b/actions/ql/lib/codeql/actions/config/Config.qll index e6359c142582..72f1b7614594 100644 --- a/actions/ql/lib/codeql/actions/config/Config.qll +++ b/actions/ql/lib/codeql/actions/config/Config.qll @@ -164,3 +164,19 @@ predicate untrustedGhCommandDataModel(string cmd_regex, string flag) { predicate actionsPermissionsDataModel(string action, string permission) { Extensions::actionsPermissionsDataModel(action, permission) } + +/** + * MaD models for deployment environments + * Fields: + * - name: deployment environment name, e.g. `Public CI` + */ +predicate enabledDeploymentEnvironmentDataModel(string name) { + Extensions::enabledDeploymentEnvironmentDataModel(name) +} + +/** + * `EnvironmentCheck` implementation model. + */ +predicate selectDeploymentEnvironmentDataModel(string selected) { + Extensions::selectDeploymentEnvironmentDataModel(selected) +} diff --git a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll index 87a919359404..e0ca6a4da340 100644 --- a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll +++ b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll @@ -88,3 +88,15 @@ extensible predicate untrustedGhCommandDataModel(string cmd_regex, string flag); * - 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); + +/** + * Holds for deployment environments that exist for a given repository. + * Requires this to be externally supplied but once done can be used to + * toggle precision of whether that suffices or not as a control check. + */ +extensible predicate enabledDeploymentEnvironmentDataModel(string name); + +/** + * Selects which deployment environments model to use to implement `EnvironmentCheck`. + */ +extensible predicate selectDeploymentEnvironmentDataModel(string mechanism); diff --git a/actions/ql/lib/codeql/actions/security/ControlChecks.qll b/actions/ql/lib/codeql/actions/security/ControlChecks.qll index 4d3dbc38c657..e95b2271f811 100644 --- a/actions/ql/lib/codeql/actions/security/ControlChecks.qll +++ b/actions/ql/lib/codeql/actions/security/ControlChecks.qll @@ -277,10 +277,22 @@ abstract class LabelCheck extends ControlCheck { } class EnvironmentCheck extends ControlCheck instanceof Environment { + EnvironmentCheck() { + exists(string selected | + selectDeploymentEnvironmentDataModel(selected) and + if selected = "EnvironmentCheckMaD" + then enabledDeploymentEnvironmentDataModel(this.(Environment).getName()) + else + if selected = "EnvironmentCheckCustomQL" + then this instanceof CustomEnvEnable + else this instanceof Environment + ) + } + // Environment checks are not effective against any mutable attacks // they do actually protect against untrusted code execution (sha) override predicate protectsCategoryAndEvent(string category, string event) { - event = actor_is_attacker_event() and category = any_category() + event = actor_is_attacker_event() and category = toctou_category() or event = actor_not_attacker_event() and category = non_toctou_category() } diff --git a/actions/ql/lib/ext/config/customize_checks.yml b/actions/ql/lib/ext/config/customize_checks.yml new file mode 100644 index 000000000000..c630d8be80c7 --- /dev/null +++ b/actions/ql/lib/ext/config/customize_checks.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/actions-all + extensible: selectDeploymentEnvironmentDataModel + data: + # The possible values this can take are: + # EnvironmentCheckCustomQL - for a custom QL implementation for the sufficient EnvironmentCheck. + # EnvironmentCheckMaD - for a custom MaD list of deployment environments that are relevant to a database. + - [""] \ No newline at end of file diff --git a/actions/ql/lib/ext/config/deployment_environment.yml b/actions/ql/lib/ext/config/deployment_environment.yml new file mode 100644 index 000000000000..6517614139e0 --- /dev/null +++ b/actions/ql/lib/ext/config/deployment_environment.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/actions-all + extensible: enabledDeploymentEnvironmentDataModel + data: + - [""] \ No newline at end of file From cdffef8684c2f2608eee4f691b536a7882310468 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 10 Jul 2026 19:58:23 -0400 Subject: [PATCH 2/7] Fix accidental change in ControlChecks.qll --- actions/ql/lib/codeql/actions/security/ControlChecks.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ql/lib/codeql/actions/security/ControlChecks.qll b/actions/ql/lib/codeql/actions/security/ControlChecks.qll index e95b2271f811..4a68d50549dc 100644 --- a/actions/ql/lib/codeql/actions/security/ControlChecks.qll +++ b/actions/ql/lib/codeql/actions/security/ControlChecks.qll @@ -292,7 +292,7 @@ class EnvironmentCheck extends ControlCheck instanceof Environment { // Environment checks are not effective against any mutable attacks // they do actually protect against untrusted code execution (sha) override predicate protectsCategoryAndEvent(string category, string event) { - event = actor_is_attacker_event() and category = toctou_category() + event = actor_is_attacker_event() and category = any_category() or event = actor_not_attacker_event() and category = non_toctou_category() } From 57903295aa20d83d70de38d9e270ab3098c50b4d Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 21 Jul 2026 16:03:50 -0400 Subject: [PATCH 3/7] Address review comments --- actions/ql/lib/actions.qll | 2 -- actions/ql/lib/codeql/actions/config/Config.qll | 7 ------- .../lib/codeql/actions/config/ConfigExtensions.qll | 5 ----- .../lib/codeql/actions/security/ControlChecks.qll | 13 ++++--------- actions/ql/lib/ext/config/customize_checks.yml | 9 --------- .../ql/lib/ext/config/deployment_environment.yml | 3 +-- 6 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 actions/ql/lib/ext/config/customize_checks.yml diff --git a/actions/ql/lib/actions.qll b/actions/ql/lib/actions.qll index a1ee60b1694d..2c1d1cee9259 100644 --- a/actions/ql/lib/actions.qll +++ b/actions/ql/lib/actions.qll @@ -1,3 +1 @@ import codeql.actions.Ast - -abstract class CustomEnvEnable extends Environment { } diff --git a/actions/ql/lib/codeql/actions/config/Config.qll b/actions/ql/lib/codeql/actions/config/Config.qll index 72f1b7614594..27e24514c091 100644 --- a/actions/ql/lib/codeql/actions/config/Config.qll +++ b/actions/ql/lib/codeql/actions/config/Config.qll @@ -173,10 +173,3 @@ predicate actionsPermissionsDataModel(string action, string permission) { predicate enabledDeploymentEnvironmentDataModel(string name) { Extensions::enabledDeploymentEnvironmentDataModel(name) } - -/** - * `EnvironmentCheck` implementation model. - */ -predicate selectDeploymentEnvironmentDataModel(string selected) { - Extensions::selectDeploymentEnvironmentDataModel(selected) -} diff --git a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll index e0ca6a4da340..f8cdc8e66c6a 100644 --- a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll +++ b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll @@ -95,8 +95,3 @@ extensible predicate actionsPermissionsDataModel(string action, string permissio * toggle precision of whether that suffices or not as a control check. */ extensible predicate enabledDeploymentEnvironmentDataModel(string name); - -/** - * Selects which deployment environments model to use to implement `EnvironmentCheck`. - */ -extensible predicate selectDeploymentEnvironmentDataModel(string mechanism); diff --git a/actions/ql/lib/codeql/actions/security/ControlChecks.qll b/actions/ql/lib/codeql/actions/security/ControlChecks.qll index 4a68d50549dc..7bde120e432a 100644 --- a/actions/ql/lib/codeql/actions/security/ControlChecks.qll +++ b/actions/ql/lib/codeql/actions/security/ControlChecks.qll @@ -278,15 +278,10 @@ abstract class LabelCheck extends ControlCheck { class EnvironmentCheck extends ControlCheck instanceof Environment { EnvironmentCheck() { - exists(string selected | - selectDeploymentEnvironmentDataModel(selected) and - if selected = "EnvironmentCheckMaD" - then enabledDeploymentEnvironmentDataModel(this.(Environment).getName()) - else - if selected = "EnvironmentCheckCustomQL" - then this instanceof CustomEnvEnable - else this instanceof Environment - ) + // if there are any custom tuples use those + if enabledDeploymentEnvironmentDataModel(_) + then enabledDeploymentEnvironmentDataModel(this.(Environment).getName()) + else this instanceof Environment } // Environment checks are not effective against any mutable attacks diff --git a/actions/ql/lib/ext/config/customize_checks.yml b/actions/ql/lib/ext/config/customize_checks.yml deleted file mode 100644 index c630d8be80c7..000000000000 --- a/actions/ql/lib/ext/config/customize_checks.yml +++ /dev/null @@ -1,9 +0,0 @@ -extensions: - - addsTo: - pack: codeql/actions-all - extensible: selectDeploymentEnvironmentDataModel - data: - # The possible values this can take are: - # EnvironmentCheckCustomQL - for a custom QL implementation for the sufficient EnvironmentCheck. - # EnvironmentCheckMaD - for a custom MaD list of deployment environments that are relevant to a database. - - [""] \ No newline at end of file diff --git a/actions/ql/lib/ext/config/deployment_environment.yml b/actions/ql/lib/ext/config/deployment_environment.yml index 6517614139e0..eed2911c2758 100644 --- a/actions/ql/lib/ext/config/deployment_environment.yml +++ b/actions/ql/lib/ext/config/deployment_environment.yml @@ -2,5 +2,4 @@ extensions: - addsTo: pack: codeql/actions-all extensible: enabledDeploymentEnvironmentDataModel - data: - - [""] \ No newline at end of file + data: [] \ No newline at end of file From 854b5e8d8b169248840d83c318fdb9f3e9dfb184 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 22 Jul 2026 10:27:25 -0400 Subject: [PATCH 4/7] Add ControlCheck library test --- .../basic/.github/workflows/controlcheck.yml | 16 ++++++++++++++++ .../basic/controlchecktest.expected | 1 + .../library-tests/basic/controlchecktest.ext.yml | 8 ++++++++ .../test/library-tests/basic/controlchecktest.ql | 5 +++++ 4 files changed, 30 insertions(+) create mode 100644 actions/ql/test/library-tests/basic/.github/workflows/controlcheck.yml create mode 100644 actions/ql/test/library-tests/basic/controlchecktest.expected create mode 100644 actions/ql/test/library-tests/basic/controlchecktest.ext.yml create mode 100644 actions/ql/test/library-tests/basic/controlchecktest.ql diff --git a/actions/ql/test/library-tests/basic/.github/workflows/controlcheck.yml b/actions/ql/test/library-tests/basic/.github/workflows/controlcheck.yml new file mode 100644 index 000000000000..bd8ba15784b4 --- /dev/null +++ b/actions/ql/test/library-tests/basic/.github/workflows/controlcheck.yml @@ -0,0 +1,16 @@ +on: + pull_request_target: + types: [Created] +jobs: + test1: + environment: EnvironmentInRepo + runs-on: ubuntu-latest + steps: + - name: Test 1 + run: echo "test1" + test2: + environment: EnvironmentNotInRepo + runs-on: ubuntu-latest + steps: + - name: Test 2 + run: echo "test2" \ No newline at end of file diff --git a/actions/ql/test/library-tests/basic/controlchecktest.expected b/actions/ql/test/library-tests/basic/controlchecktest.expected new file mode 100644 index 000000000000..ac2f7ac38aa1 --- /dev/null +++ b/actions/ql/test/library-tests/basic/controlchecktest.expected @@ -0,0 +1 @@ +| .github/workflows/controlcheck.yml:6:18:6:34 | EnvironmentInRepo | diff --git a/actions/ql/test/library-tests/basic/controlchecktest.ext.yml b/actions/ql/test/library-tests/basic/controlchecktest.ext.yml new file mode 100644 index 000000000000..c20b01db5a22 --- /dev/null +++ b/actions/ql/test/library-tests/basic/controlchecktest.ext.yml @@ -0,0 +1,8 @@ +extensions: + - addsTo: + pack: codeql/actions-all + extensible: enabledDeploymentEnvironmentDataModel + data: + # assumed to exist in a repo where controlcheck.yml exists + # realisitically would need to be manually/externally provided + - ["EnvironmentInRepo"] \ No newline at end of file diff --git a/actions/ql/test/library-tests/basic/controlchecktest.ql b/actions/ql/test/library-tests/basic/controlchecktest.ql new file mode 100644 index 000000000000..1daba58fe749 --- /dev/null +++ b/actions/ql/test/library-tests/basic/controlchecktest.ql @@ -0,0 +1,5 @@ +import actions +import codeql.actions.security.ControlChecks + +from ControlCheck c +select c From 07e3e346dd8028d553d748e9ac9dbc32750b2d2c Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 22 Jul 2026 12:00:39 -0400 Subject: [PATCH 5/7] Add change note ControlCheck change --- .../2026-07-22-environment-check-sanitizer-mad.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 actions/ql/lib/change-notes/2026-07-22-environment-check-sanitizer-mad.md diff --git a/actions/ql/lib/change-notes/2026-07-22-environment-check-sanitizer-mad.md b/actions/ql/lib/change-notes/2026-07-22-environment-check-sanitizer-mad.md new file mode 100644 index 000000000000..ef901cdc7603 --- /dev/null +++ b/actions/ql/lib/change-notes/2026-07-22-environment-check-sanitizer-mad.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added an option to `EnvironmentCheck` to become specified by a MaD model, otherwise it will continue as the default it previously was. Without adding models to `actions/ql/lib/ext/config/deployment_environment.yml` the behavior of every query will be unchanged. When models are added queries using `ControlCheck` may find more results in cases where an enironment is no longer a sufficient sanitizer. \ No newline at end of file From 5927a8683a9ab26b3df1ce8f05fb3ea2f10d2d39 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 22 Jul 2026 12:01:34 -0400 Subject: [PATCH 6/7] Fix spelling mistake in doc --- actions/ql/test/library-tests/basic/controlchecktest.ext.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ql/test/library-tests/basic/controlchecktest.ext.yml b/actions/ql/test/library-tests/basic/controlchecktest.ext.yml index c20b01db5a22..96ded8ff2b2c 100644 --- a/actions/ql/test/library-tests/basic/controlchecktest.ext.yml +++ b/actions/ql/test/library-tests/basic/controlchecktest.ext.yml @@ -4,5 +4,5 @@ extensions: extensible: enabledDeploymentEnvironmentDataModel data: # assumed to exist in a repo where controlcheck.yml exists - # realisitically would need to be manually/externally provided + # realistically would need to be manually/externally provided - ["EnvironmentInRepo"] \ No newline at end of file From a9d1b4be39cba19643c84ec25bdcb8e1e54be519 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 22 Jul 2026 12:05:13 -0400 Subject: [PATCH 7/7] Improve doc --- actions/ql/lib/codeql/actions/config/ConfigExtensions.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll index f8cdc8e66c6a..4ee438fc63cb 100644 --- a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll +++ b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll @@ -90,8 +90,10 @@ extensible predicate untrustedGhCommandDataModel(string cmd_regex, string flag); extensible predicate actionsPermissionsDataModel(string action, string permission); /** - * Holds for deployment environments that exist for a given repository. + * Holds for deployment environments that exist with `name` for a given repository. + * * - 'name' is the name of the environment defined. + * E.g. for the deployment environment `environment: EnvironmentInRepo`, `name` is `EnvironmentInRepo`. * Requires this to be externally supplied but once done can be used to - * toggle precision of whether that suffices or not as a control check. + * toggle precision of whether that suffices or not as a control check by contributing to `EnvironmentCheck`. */ extensible predicate enabledDeploymentEnvironmentDataModel(string name);