1515import javascript
1616import semmle.javascript.Actions
1717
18+ /**
19+ * A `script:` field within an Actions `with:` specific to `actions/github-script` action.
20+ *
21+ * For example:
22+ * ```
23+ * uses: actions/github-script@v3
24+ * with:
25+ * script: console.log('${{ github.event.pull_request.head.sha }}')
26+ * ```
27+ */
28+ class GitHubScript extends YamlNode , YamlString {
29+ GitHubScriptWith with ;
30+
31+ GitHubScript ( ) { with .lookup ( "script" ) = this }
32+
33+ /** Gets the `with` field this field belongs to. */
34+ GitHubScriptWith getWith ( ) { result = with }
35+ }
36+
37+ /**
38+ * A step that uses `actions/github-script` action.
39+ */
40+ class GitHubScriptStep extends Actions:: Step {
41+ GitHubScriptStep ( ) { this .getUses ( ) .getGitHubRepository ( ) = "actions/github-script" }
42+ }
43+
44+ /**
45+ * A `with:` field sibling to `uses: actions/github-script`.
46+ */
47+ class GitHubScriptWith extends YamlNode , YamlMapping {
48+ GitHubScriptStep step ;
49+
50+ GitHubScriptWith ( ) { step .lookup ( "with" ) = this }
51+
52+ /** Gets the step this field belongs to. */
53+ GitHubScriptStep getStep ( ) { result = step }
54+ }
55+
1856bindingset [ context]
1957private predicate isExternalUserControlledIssue ( string context ) {
2058 context .regexpMatch ( "\\bgithub\\s*\\.\\s*event\\s*\\.\\s*issue\\s*\\.\\s*title\\b" ) or
@@ -133,7 +171,7 @@ predicate isRunInjectable(Actions::Run run, string injection, string context) {
133171 * Holds if the `actions/github-script` contains any expression interpolation `${{ e }}`.
134172 * Sets `context` to the initial untrusted value assignment in case of `${{ env... }}` interpolation
135173 */
136- predicate isScriptInjectable ( Actions :: GitHubScript script , string injection , string context ) {
174+ predicate isScriptInjectable ( GitHubScript script , string injection , string context ) {
137175 Actions:: getASimpleReferenceExpression ( script ) = injection and
138176 (
139177 injection = context
@@ -152,7 +190,7 @@ YamlNode getInjectableCompositeActionNode(Actions::Runs runs, string injection,
152190 run .getStep ( ) .getRuns ( ) = runs
153191 )
154192 or
155- exists ( Actions :: GitHubScript script |
193+ exists ( GitHubScript script |
156194 isScriptInjectable ( script , injection , context ) and
157195 result = script and
158196 script .getWith ( ) .getStep ( ) .getRuns ( ) = runs
@@ -169,7 +207,7 @@ YamlNode getInjectableWorkflowNode(Actions::On on, string injection, string cont
169207 run .getStep ( ) .getJob ( ) .getWorkflow ( ) .getOn ( ) = on
170208 )
171209 or
172- exists ( Actions :: GitHubScript script |
210+ exists ( GitHubScript script |
173211 isScriptInjectable ( script , injection , context ) and
174212 result = script and
175213 script .getWith ( ) .getStep ( ) .getJob ( ) .getWorkflow ( ) .getOn ( ) = on
0 commit comments