diff --git a/javascript/ql/lib/semmle/javascript/Actions.qll b/javascript/ql/lib/semmle/javascript/Actions.qll index d57341da14e..4bb52cb87cb 100644 --- a/javascript/ql/lib/semmle/javascript/Actions.qll +++ b/javascript/ql/lib/semmle/javascript/Actions.qll @@ -368,13 +368,32 @@ module Actions { * script: console.log('${{ github.event.pull_request.head.sha }}') * ``` */ - class Script extends YamlNode, YamlString { - With with; + class GitHubScript extends YamlNode, YamlString { + GitHubScriptWith with; - Script() { with.lookup("script") = this } + GitHubScript() { with.lookup("script") = this } /** Gets the `with` field this field belongs to. */ - With getWith() { result = with } + GitHubScriptWith getWith() { result = with } + } + + /** + * A step that uses `actions/github-script` action. + */ + class GitHubScriptStep extends Step { + GitHubScriptStep() { this.getUses().getGitHubRepository() = "actions/github-script" } + } + + /** + * A `with:` field sibling to `uses: actions/github-script`. + */ + class GitHubScriptWith extends YamlNode, YamlMapping { + GitHubScriptStep step; + + GitHubScriptWith() { step.lookup("with") = this } + + /** Gets the step this field belongs to. */ + GitHubScriptStep getStep() { result = step } } /** diff --git a/javascript/ql/src/Security/CWE-094/ExpressionInjection.ql b/javascript/ql/src/Security/CWE-094/ExpressionInjection.ql index bd16f60d070..5b11e1e5adf 100644 --- a/javascript/ql/src/Security/CWE-094/ExpressionInjection.ql +++ b/javascript/ql/src/Security/CWE-094/ExpressionInjection.ql @@ -133,17 +133,12 @@ predicate isRunInjectable(Actions::Run run, string injection, string context) { * Holds if the `actions/github-script` contains any expression interpolation `${{ e }}`. * Sets `context` to the initial untrusted value assignment in case of `${{ env... }}` interpolation */ -predicate isScriptInjectable(Actions::Script script, string injection, string context) { - exists(Actions::Step step, Actions::Uses uses | - script.getWith().getStep() = step and - uses.getStep() = step and - uses.getGitHubRepository() = "actions/github-script" and - Actions::getASimpleReferenceExpression(script) = injection and - ( - injection = context - or - isEnvInterpolationTainted(injection, context) - ) +predicate isScriptInjectable(Actions::GitHubScript script, string injection, string context) { + Actions::getASimpleReferenceExpression(script) = injection and + ( + injection = context + or + isEnvInterpolationTainted(injection, context) ) } @@ -158,7 +153,7 @@ where run.getStep().getRuns() = runs ) or - exists(Actions::Script script | + exists(Actions::GitHubScript script | node = script and script.getWith().getStep().getRuns() = runs and isScriptInjectable(script, injection, context) @@ -184,7 +179,7 @@ where run.getStep().getJob().getWorkflow().getOn() = on ) or - exists(Actions::Script script | + exists(Actions::GitHubScript script | node = script and script.getWith().getStep().getJob().getWorkflow().getOn() = on and isScriptInjectable(script, injection, context)