mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 01:30:10 +08:00
109 lines
3.1 KiB
Plaintext
109 lines
3.1 KiB
Plaintext
/**
|
|
* @name Unguarded actions library use
|
|
* @description Code that runs outside of GitHub Actions tries to use a library that should only be used when running on actions.
|
|
* @kind problem
|
|
* @problem.severity error
|
|
* @id javascript/codeql-action/unguarded-action-lib
|
|
*/
|
|
|
|
import javascript
|
|
|
|
/**
|
|
* An import from a library that is meant for GitHub Actions and
|
|
* we do not want to be using outside of actions.
|
|
*/
|
|
class ActionsLibImport extends ImportDeclaration {
|
|
ActionsLibImport() {
|
|
getImportedPath().getValue().matches("@actions/%")
|
|
}
|
|
|
|
string getName() {
|
|
result = getImportedPath().getValue()
|
|
}
|
|
|
|
Variable getAProvidedVariable() {
|
|
result = getASpecifier().getLocal().getVariable()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An entrypoint to the CodeQL runner.
|
|
*/
|
|
class RunnerEntrypoint extends Function {
|
|
RunnerEntrypoint() {
|
|
getFile().getAbsolutePath().matches("%/runner.ts")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A check of whether we are in actions mode or runner mode.
|
|
*/
|
|
class ModeGuard extends IfStmt {
|
|
ModeGuard() {
|
|
getCondition().(EqualityTest).getAnOperand().(StringLiteral).getValue() = "actions" or
|
|
getCondition().(EqualityTest).getAnOperand().(StringLiteral).getValue() = "runner"
|
|
}
|
|
|
|
string getOperand() {
|
|
result = getCondition().(EqualityTest).getAnOperand().(StringLiteral).getValue()
|
|
}
|
|
|
|
predicate isPositive() {
|
|
getCondition().(EqualityTest).getPolarity() = true
|
|
}
|
|
|
|
/**
|
|
* Get the then or else block that is the "actions" path.
|
|
*/
|
|
Stmt getActionsBlock() {
|
|
(getOperand() = "actions" and isPositive() and result = getThen())
|
|
or
|
|
(getOperand() = "runner" and not isPositive() and result = getThen())
|
|
or
|
|
(getOperand() = "actions" and not isPositive() and result = getElse())
|
|
or
|
|
(getOperand() = "runner" and isPositive() and result = getElse())
|
|
}
|
|
|
|
/**
|
|
* Get an expr that is only executed on actions
|
|
*/
|
|
Expr getAnActionsExpr() {
|
|
getActionsBlock().getAChildStmt*().getAChildExpr*() = result
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Any expr that is a transitive child of the given function
|
|
* and is not only called on actions.
|
|
*/
|
|
Expr getAFunctionChildExpr(Function f) {
|
|
not exists(ModeGuard guard | guard.getAnActionsExpr() = result) and
|
|
result.getContainer() = f
|
|
}
|
|
|
|
/*
|
|
* Result is a function that is called from the body of the given function `f`
|
|
* and is not only called on actions.
|
|
*/
|
|
Function calledBy(Function f) {
|
|
exists(InvokeExpr invokeExpr |
|
|
invokeExpr = getAFunctionChildExpr(f) and
|
|
invokeExpr.getResolvedCallee() = result and
|
|
not exists(ModeGuard guard | guard.getAnActionsExpr() = invokeExpr)
|
|
)
|
|
or
|
|
// Assume outer function causes inner function to be called
|
|
(result instanceof Expr and
|
|
result.getEnclosingContainer() = f and
|
|
not exists(ModeGuard guard | guard.getAnActionsExpr() = result))
|
|
}
|
|
|
|
from VarAccess v, ActionsLibImport actionsLib, RunnerEntrypoint runnerEntry
|
|
where actionsLib.getAProvidedVariable() = v.getVariable()
|
|
and getAFunctionChildExpr(calledBy*(runnerEntry)) = v
|
|
select v, "$@ is imported from $@ and this code can be called from $@",
|
|
v, v.getName(),
|
|
actionsLib, actionsLib.getName(),
|
|
runnerEntry, "the runner"
|