Skip to content

Commit

Permalink
app/packages/search: sanitized search terms for SQL
Browse files Browse the repository at this point in the history
Reported by SonarSource, with full disclosure to be done soon. Properly
use pg's escaping mechanism to avoid SQL injection.

Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
  • Loading branch information
arthurzam committed Mar 17, 2023
1 parent 62802cd commit 4fa6e4b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 22 deletions.
6 changes: 2 additions & 4 deletions pkg/api/graphql/resolvers/resolver.go
Expand Up @@ -224,10 +224,8 @@ func (r *queryResolver) PackageSearch(ctx context.Context, searchTerm *string, r
Select()
} else {
// if the query contains no wildcards do a fuzzy search
searchQuery := packages.BuildSearchQuery(*searchTerm)
err = database.DBCon.Model(&gpackages).
Where(searchQuery).
WhereOr("atom LIKE ? ", ("%" + *searchTerm + "%")).
err = packages.BuildSearchQuery(database.DBCon.Model(&gpackages), *searchTerm).
WhereOr("atom LIKE ? ", "%" + *searchTerm + "%").
Relation("PkgCheckResults").Relation("Bugs").Relation("PullRequests").Relation("ReverseDependencies").Relation("Commits").Relation("Versions").Relation("Versions.Masks").Relation("Versions.PkgCheckResults").Relation("Versions.Dependencies").Relation("PkgCheckResults").Relation("Outdated").
OrderExpr("name <-> '" + *searchTerm + "'").
Limit(limit).
Expand Down
41 changes: 23 additions & 18 deletions pkg/app/handler/packages/search.go
Expand Up @@ -3,13 +3,14 @@
package packages

import (
"encoding/json"
"net/http"
"soko/pkg/app/handler/feeds"
"soko/pkg/database"
"soko/pkg/models"
"strings"

"github.com/go-pg/pg"
"github.com/go-pg/pg/v10"
)

// Search renders a template containing a list of search results
Expand All @@ -33,19 +34,17 @@ func Search(w http.ResponseWriter, r *http.Request) {
// if the query contains wildcards
wildcardSearchTerm := strings.ReplaceAll(searchTerm, "*", "%")
err = database.DBCon.Model(&packages).
WhereOr("atom LIKE ? ", wildcardSearchTerm).
WhereOr("name LIKE ? ", wildcardSearchTerm).
WhereOr("atom LIKE ?", wildcardSearchTerm).
WhereOr("name LIKE ?", wildcardSearchTerm).
Relation("Versions").
OrderExpr("name <-> '" + searchTerm + "'").
OrderExpr("name <-> ?", searchTerm).
Select()
} else {
// if the query contains no wildcards do a fuzzy search
searchQuery := BuildSearchQuery(searchTerm)
err = database.DBCon.Model(&packages).
Where(searchQuery).
WhereOr("atom LIKE ? ", ("%" + searchTerm + "%")).
err = BuildSearchQuery(database.DBCon.Model(&packages), searchTerm).
WhereOr("atom LIKE ?", "%"+searchTerm+"%").
Relation("Versions").
OrderExpr("name <-> '" + searchTerm + "'").
OrderExpr("name <-> ?", searchTerm).
Select()
}

Expand All @@ -68,13 +67,11 @@ func SearchFeed(w http.ResponseWriter, r *http.Request) {

searchTerm := getParameterValue("q", r)
searchTerm = strings.ReplaceAll(searchTerm, "*", "")
searchQuery := BuildSearchQuery(searchTerm)

var packages []models.Package
err := database.DBCon.Model(&packages).
Where(searchQuery).
err := BuildSearchQuery(database.DBCon.Model(&packages), searchTerm).
Relation("Versions").
OrderExpr("name <-> '" + searchTerm + "'").
OrderExpr("name <-> ?", searchTerm).
Select()
if err != nil && err != pg.ErrNoRows {
http.Error(w, http.StatusText(http.StatusInternalServerError),
Expand All @@ -85,13 +82,21 @@ func SearchFeed(w http.ResponseWriter, r *http.Request) {
feeds.Packages(searchTerm, packages, w)
}

func BuildSearchQuery(searchString string) string {
var searchClauses []string
func BuildSearchQuery(query *pg.Query, searchString string) *pg.Query {
for _, searchTerm := range strings.Split(searchString, " ") {
if searchTerm != "" {
searchClauses = append(searchClauses,
"( (category % '"+searchTerm+"') OR (name % '"+searchTerm+"') OR (atom % '"+searchTerm+"') OR (maintainers @> '[{\"Name\": \""+searchTerm+"\"}]' OR maintainers @> '[{\"Email\": \""+searchTerm+"\"}]'))")
marshal, err := json.Marshal(searchTerm)
if err == nil {
continue
}
query = query.WhereGroup(func(q *pg.Query) (*pg.Query, error) {
return q.WhereOr("category % ?", searchTerm).
WhereOr("name % ?", searchTerm).
WhereOr("atom % ?", searchTerm).
WhereOr("maintainers @> ?", `[{"Name": "`+string(marshal)+`"}]`).
WhereOr("maintainers @> ?", `[{"Email": "`+string(marshal)+`"}]`), nil
})
}
}
return strings.Join(searchClauses, " AND ")
return query
}

0 comments on commit 4fa6e4b

Please sign in to comment.