mirror of
https://github.com/unraid/api.git
synced 2025-12-30 21:19:49 -06:00
77 lines
2.1 KiB
Plaintext
77 lines
2.1 KiB
Plaintext
/**
|
|
* @name Potential GraphQL Injection
|
|
* @description User-controlled input used directly in GraphQL queries may lead to injection vulnerabilities.
|
|
* @kind path-problem
|
|
* @problem.severity error
|
|
* @precision high
|
|
* @id js/graphql-injection
|
|
* @tags security
|
|
* external/cwe/cwe-943
|
|
*/
|
|
|
|
import javascript
|
|
import DataFlow::PathGraph
|
|
|
|
class GraphQLQueryExecution extends DataFlow::CallNode {
|
|
GraphQLQueryExecution() {
|
|
exists(string name |
|
|
name = this.getCalleeName() and
|
|
(
|
|
name = "execute" or
|
|
name = "executeQuery" or
|
|
name = "query" or
|
|
name.regexpMatch("(?i).*graphql.*query.*")
|
|
)
|
|
)
|
|
}
|
|
|
|
DataFlow::Node getQuery() {
|
|
result = this.getArgument(0)
|
|
}
|
|
}
|
|
|
|
class UserControlledInput extends DataFlow::Node {
|
|
UserControlledInput() {
|
|
exists(DataFlow::ParameterNode param |
|
|
param.getName().regexpMatch("(?i).*(query|request|input|args|variables|params).*") and
|
|
this = param
|
|
)
|
|
or
|
|
exists(DataFlow::PropRead prop |
|
|
prop.getPropertyName().regexpMatch("(?i).*(query|request|input|args|variables|params).*") and
|
|
this = prop
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Holds if `node` is a string concatenation.
|
|
*/
|
|
predicate isStringConcatenation(DataFlow::Node node) {
|
|
exists(BinaryExpr concat |
|
|
concat.getOperator() = "+" and
|
|
concat.flow() = node
|
|
)
|
|
}
|
|
|
|
class GraphQLInjectionConfig extends TaintTracking::Configuration {
|
|
GraphQLInjectionConfig() { this = "GraphQLInjectionConfig" }
|
|
|
|
override predicate isSource(DataFlow::Node source) {
|
|
source instanceof UserControlledInput
|
|
}
|
|
|
|
override predicate isSink(DataFlow::Node sink) {
|
|
exists(GraphQLQueryExecution exec | sink = exec.getQuery())
|
|
}
|
|
|
|
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
|
// Add any GraphQL-specific taint steps if needed
|
|
isStringConcatenation(succ) and
|
|
succ.(DataFlow::BinaryExprNode).getAnOperand() = pred
|
|
}
|
|
}
|
|
|
|
from GraphQLInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
|
where config.hasFlowPath(source, sink)
|
|
select sink.getNode(), source, sink, "GraphQL query may contain user-controlled input from $@.", source.getNode(), "user input" |