Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/queries/undeclared-action-input.ql
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
103 lines (91 sloc)
2.89 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @name Undeclared action input | |
* @description Code tries to use an input parameter that is not defined for this action. | |
Perhaps this code is shared by multiple actions. | |
* @kind problem | |
* @problem.severity error | |
* @id javascript/codeql-action/undeclared-action-input | |
*/ | |
import javascript | |
/** | |
* A declaration of a github action, including its inputs and entrypoint. | |
*/ | |
class ActionDeclaration extends File { | |
ActionDeclaration() { | |
getRelativePath().matches("%/action.yml") | |
} | |
/** | |
* The name of the action. | |
*/ | |
string getName() { | |
result = getRelativePath().regexpCapture("(.*)/action.yml", 1) | |
} | |
YAMLDocument getRootNode() { | |
result.getFile() = this | |
} | |
/** | |
* The name of any input to this action. | |
*/ | |
string getAnInput() { | |
result = getRootNode().(YAMLMapping).lookup("inputs").(YAMLMapping).getKey(_).(YAMLString).getValue() | |
} | |
/** | |
* The function that is the entrypoint to this action. | |
*/ | |
FunctionDeclStmt getEntrypoint() { | |
result.getFile().getRelativePath() = getRootNode(). | |
(YAMLMapping).lookup("runs"). | |
(YAMLMapping).lookup("main"). | |
(YAMLString).getValue().regexpReplaceAll("\\.\\./lib/(.*)\\.js", "src/$1.ts") and | |
result.getName() = "run" | |
} | |
} | |
/** | |
* A function declared on CodeQL interface from codeql.ts | |
*/ | |
class CodeQLFunction extends Function { | |
CodeQLFunction() { | |
exists(Function getCodeQLForCmd, ObjectExpr obj | | |
getCodeQLForCmd.getName() = "getCodeQLForCmd" and | |
obj = getCodeQLForCmd.getAStmt().(ReturnStmt).getExpr() and | |
obj.getAProperty().getInit() = this) | |
} | |
} | |
/** | |
* Any expr that is a transitive child of the given function. | |
*/ | |
Expr getAFunctionChildExpr(Function f) { | |
result.getContainer() = f | |
} | |
/* | |
* Result is a function that is called from the body of the given function `f` | |
*/ | |
Function calledBy(Function f) { | |
result = getAFunctionChildExpr(f).(InvokeExpr).getResolvedCallee() | |
or | |
// Assume outer function causes inner function to be called, | |
// except for the special case of the CodeQL functions. | |
(result.getEnclosingContainer() = f and not result instanceof CodeQLFunction) | |
or | |
// Handle calls to CodeQL functions by name | |
getAFunctionChildExpr(f).(InvokeExpr).getCalleeName() = result.(CodeQLFunction).getName() | |
} | |
/** | |
* A call to the core.getInput method. | |
*/ | |
class GetInputMethodCallExpr extends MethodCallExpr { | |
GetInputMethodCallExpr() { | |
getMethodName() = "getInput" | |
} | |
/** | |
* The name of the input being accessed. | |
*/ | |
string getInputName() { | |
result = getArgument(0).(StringLiteral).getValue() | |
} | |
} | |
from ActionDeclaration action, GetInputMethodCallExpr getInputCall, string inputName | |
where getAFunctionChildExpr(calledBy*(action.getEntrypoint())) = getInputCall and | |
inputName = getInputCall.getInputName() and | |
not inputName = action.getAnInput() | |
select getInputCall, "The $@ input is not defined for the $@ action", inputName, inputName, action, action.getName() |