@@ -3,6 +3,8 @@ private import codeql.actions.TaintTracking
33private import codeql.actions.dataflow.ExternalFlow
44import codeql.actions.dataflow.FlowSources
55import codeql.actions.DataFlow
6+ import codeql.actions.security.ControlChecks
7+ import codeql.actions.security.CachePoisoningQuery
68
79class CodeInjectionSink extends DataFlow:: Node {
810 CodeInjectionSink ( ) {
@@ -35,6 +37,53 @@ private module CodeInjectionConfig implements DataFlow::ConfigSig {
3537 exists ( run .getScript ( ) .getAFileReadCommand ( ) )
3638 )
3739 }
40+
41+ predicate observeDiffInformedIncrementalMode ( ) { any ( ) }
42+
43+ Location getASelectedSourceLocation ( DataFlow:: Node source ) { none ( ) }
44+
45+ Location getASelectedSinkLocation ( DataFlow:: Node sink ) {
46+ result = sink .getLocation ( )
47+ or
48+ // where clause from CodeInjectionCritical.ql
49+ exists ( Event event , RemoteFlowSource source | result = event .getLocation ( ) |
50+ inPrivilegedContext ( sink .asExpr ( ) , event ) and
51+ isSource ( source ) and
52+ source .getEventName ( ) = event .getName ( ) and
53+ not exists ( ControlCheck check | check .protects ( sink .asExpr ( ) , event , "code-injection" ) ) and
54+ // exclude cases where the sink is a JS script and the expression uses toJson
55+ not exists ( UsesStep script |
56+ script .getCallee ( ) = "actions/github-script" and
57+ script .getArgumentExpr ( "script" ) = sink .asExpr ( ) and
58+ exists ( getAToJsonReferenceExpression ( sink .asExpr ( ) .( Expression ) .getExpression ( ) , _) )
59+ )
60+ )
61+ or
62+ // where clause from CachePoisoningViaCodeInjection.ql
63+ exists ( Event event , LocalJob job , DataFlow:: Node source | result = event .getLocation ( ) |
64+ job = sink .asExpr ( ) .getEnclosingJob ( ) and
65+ job .getATriggerEvent ( ) = event and
66+ // job can be triggered by an external user
67+ event .isExternallyTriggerable ( ) and
68+ // the checkout is not controlled by an access check
69+ isSource ( source ) and
70+ not exists ( ControlCheck check | check .protects ( source .asExpr ( ) , event , "code-injection" ) ) and
71+ // excluding privileged workflows since they can be exploited in easier circumstances
72+ // which is covered by `actions/code-injection/critical`
73+ not job .isPrivilegedExternallyTriggerable ( event ) and
74+ (
75+ // the workflow runs in the context of the default branch
76+ runsOnDefaultBranch ( event )
77+ or
78+ // the workflow caller runs in the context of the default branch
79+ event .getName ( ) = "workflow_call" and
80+ exists ( ExternalJob caller |
81+ caller .getCallee ( ) = job .getLocation ( ) .getFile ( ) .getRelativePath ( ) and
82+ runsOnDefaultBranch ( caller .getATriggerEvent ( ) )
83+ )
84+ )
85+ )
86+ }
3887}
3988
4089/** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */
0 commit comments