@@ -33,11 +33,9 @@ private class ActionsCheckoutPathInput extends NormalizableFilepath {
3333
3434private class ExecutionPathInput extends NormalizableFilepath {
3535 ExecutionPathInput ( ) {
36- exists ( LocalScriptExecutionRunStep step | this = step .getPath ( ) )
36+ exists ( LocalScriptExecutionRunStep step | this = trimQuotes ( step .getRawPath ( ) ) )
3737 or
38- exists ( LocalActionUsesStep step | this = step .getPath ( ) )
39- or
40- this = "GITHUB_WORKSPACE/"
38+ exists ( LocalActionUsesStep step | this = step .getCallee ( ) )
4139 }
4240}
4341
@@ -60,19 +58,26 @@ private string getNormalizedActionsCheckoutPath(PRHeadCheckoutStep checkout) {
6058bindingset [ path]
6159private string getNormalizedExecutionPath ( string path ) {
6260 exists ( ExecutionPathInput executionPath , string normalized |
63- executionPath = path and
61+ executionPath = trimQuotes ( path ) and
6462 not executionPath .regexpMatch ( ".*\\$\\{\\{.*" ) and
6563 normalized = executionPath .getNormalizedPath ( ) and
66- ( normalized = "GITHUB_WORKSPACE" or normalized .matches ( "GITHUB_WORKSPACE/%" ) ) and
67- result = normalized
64+ not normalized .matches ( "/%" ) and
65+ normalized != ".." and
66+ not normalized .matches ( "../%" ) and
67+ if normalized = "."
68+ then result = "GITHUB_WORKSPACE"
69+ else (
70+ normalized .regexpMatch ( "^[^$/~].*" ) and
71+ result = "GITHUB_WORKSPACE/" + normalized
72+ )
6873 )
6974}
7075
71- bindingset [ checkout, path]
72- private predicate checkoutContainsPath ( PRHeadCheckoutStep checkout , string path ) {
76+ bindingset [ checkout, rawPath , path]
77+ private predicate checkoutContainsPath ( PRHeadCheckoutStep checkout , string rawPath , string path ) {
7378 exists ( string root , string candidate |
7479 root = getNormalizedActionsCheckoutPath ( checkout ) and
75- candidate = getNormalizedExecutionPath ( path ) and
80+ candidate = getNormalizedExecutionPath ( rawPath ) and
7681 // Canonicalize both paths so dot segments cannot enter or escape the checkout while still
7782 // passing a lexical prefix check.
7883 ( candidate = root or candidate .indexOf ( root + "/" ) = 0 )
98103 (
99104 // Check if the poisonable step is a local script execution step
100105 // and the path of the command or script matches the path of the downloaded artifact
101- checkoutContainsPath ( checkout , poisonable .( LocalScriptExecutionRunStep ) .getPath ( ) )
106+ checkoutContainsPath ( checkout , poisonable .( LocalScriptExecutionRunStep ) .getRawPath ( ) ,
107+ poisonable .( LocalScriptExecutionRunStep ) .getPath ( ) )
102108 or
103109 // Checking the path for non local script execution steps is very difficult
104110 not poisonable instanceof LocalScriptExecutionRunStep
@@ -111,7 +117,8 @@ where
111117 not poisonable instanceof LocalActionUsesStep and
112118 checkoutUsesWorkspaceRoot ( checkout )
113119 or
114- checkoutContainsPath ( checkout , poisonable .( LocalActionUsesStep ) .getPath ( ) )
120+ checkoutContainsPath ( checkout , poisonable .( LocalActionUsesStep ) .getCallee ( ) ,
121+ poisonable .( LocalActionUsesStep ) .getPath ( ) )
115122 )
116123 ) and
117124 // the checkout occurs in a privileged context
0 commit comments