Permalink
Cannot retrieve contributors at this time
97 lines (86 sloc)
3.3 KB
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/required-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.
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 Required action input | |
* @description For action inputs the core.input represents input with no value as the emptystring. | |
* This doesn't promote good type checking. Instead, use either actions-util.getOptionalInput or | |
* actions-util.getRequiredInput depending on if the input always has a value or not. The input | |
* will always have a value if it is required or has a default value. | |
* @kind problem | |
* @problem.severity error | |
* @id javascript/codeql-action/required-action-input | |
*/ | |
import javascript | |
/** | |
* A declaration of a github action. | |
*/ | |
class ActionDeclaration extends File { | |
ActionDeclaration() { | |
getRelativePath().matches("%/action.yml") | |
} | |
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 given input always has a value, either because it is required, | |
* or because it has a default value. | |
*/ | |
predicate inputAlwaysHasValue(string input) { | |
exists(YAMLMapping value | | |
value = getRootNode().(YAMLMapping).lookup("inputs").(YAMLMapping).lookup(input) and | |
(exists(value.lookup("default")) or | |
value.lookup("required").(YAMLBool).getBoolValue() = true)) | |
} | |
/** | |
* 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" | |
} | |
} | |
/** | |
* An import from "@actions/core" | |
*/ | |
class ActionsLibImport extends ImportDeclaration { | |
ActionsLibImport() { | |
getImportedPath().getValue() = "@actions/core" | |
} | |
Variable getAProvidedVariable() { | |
result = getASpecifier().getLocal().getVariable() | |
} | |
} | |
/** | |
* A call to the core.getInput method. | |
*/ | |
class CoreGetInputMethodCallExpr extends MethodCallExpr { | |
CoreGetInputMethodCallExpr() { | |
getMethodName() = "getInput" and | |
exists(ActionsLibImport libImport | | |
this.getReceiver() = libImport.getAProvidedVariable().getAnAccess() or | |
this.getReceiver().(PropAccess).getBase() = libImport.getAProvidedVariable().getAnAccess()) | |
} | |
/** | |
* The name of the input being accessed. | |
*/ | |
string getInputName() { | |
result = getArgument(0).(StringLiteral).getValue() | |
} | |
} | |
from ActionDeclaration action, CoreGetInputMethodCallExpr getInputCall, string inputName, string alternateFunction | |
where action.getAnInput() = inputName | |
// We don't want to create an alert for the users core.getInput in the getRequiredInput | |
// and getOptionalInput functions themselves, and this check here does that in a | |
// roundabout way by checking the parameter is a string literal. This should be enough | |
// and hopefully won't discount any real calls to core.getInput, but is worth noting here. | |
and getInputCall.getInputName() = inputName | |
and ((action.inputAlwaysHasValue(inputName) and alternateFunction = "getRequiredInput") | |
or (not action.inputAlwaysHasValue(inputName) and alternateFunction = "geOptionalInput")) | |
select getInputCall, "This input may be undefined. Please use actions-util.$@ instead.", alternateFunction, alternateFunction |