Files
api/.github/codeql/custom-queries/javascript/graphql-injection.ql
2025-05-14 20:21:52 -04:00

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"