I have a simple Golang Gin API that uses MongoDB as the backend database. My team is using GitHub CodeQL, so we want to be sure we are following the best standards. However, we continue to get this error for all of our query endpoints:
Database query built from user-controlled sources
Here is a simplified sample endpoint:
func (l LogHandler) GetLogByFQDN(ctx *gin.Context) {
// Bind
var request dtos.GetLogRequest
if err := ctx.BindJSON(&data); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, validator.DecryptErrors(err))
return
}
// Prepare MongoDB query
col := getCollection("logs")
filter := bson.M{"config.fqdn": bson.M{"$eq": request.fqdn}}
// Execute MongoDB query
var data Log
err := col.FindOne(context.TODO(), filter).Decode(&data)
if err != nil {
...
}
ctx.JSON(
http.StatusOK,
data,
)
}
The following resource advised to use $eq, so the code has been updated above, but still the issue persists.
https://codeql.github.com/codeql-query-help/javascript/js-sql-injection/
I have also tried adding my own sanitation function after bind, which would remove bad characters such as:
$,{,},,
However, this has also not resolved the issue.
I can just ignore these errors and move forward, but it would be great to clear this up for our build pipelines.
You are creating a MongoDB filter using the
request.fqdnvalue that comes... straight from user input:If an attacker has control over the
request.fqdn, they might be able to construct a value that modifies your query in unexpected ways, leading to a potential NoSQL injection attack.The warning from CodeQL is trying to alert you to this potential vulnerability.
You can try and use a library like
go-playground/validator/v10to validate the fqdn from the request. If it is not a valid FQDN, you would need to return a 400 error to the user.Make sure you have a
fqdntag in yourGetLogRequeststruct like:If the error persists, consider CodeQL uses static analysis to determine the flow of potentially tainted (i.e., user-controlled) data through your code. Even if your code is safe in practice, if CodeQL detects a flow of tainted data into a sensitive operation, it can still flag it.
One way to approach this is to split the logic into separate functions:
You can try and, first, separate the validation and sanitation:
Then modify your handler to use the
validateAndSanitizeFQDN()function:By making this separation clearer, you are giving static analysis tools like CodeQL a better chance to understand that user input is being validated and sanitized before it affects the MongoDB query.
The OP Kyle Barnes adds in the comments: