diff options
| author | 2023-03-17 21:47:34 +0200 | |
|---|---|---|
| committer | 2023-03-17 21:47:34 +0200 | |
| commit | 4fa6e4b619c0362728955b6ec56eab0e0cbf1e23 (patch) | |
| tree | 9a55b4887ce140ea438e9a3b12a9066412e6d72f | |
| parent | update/packages: override upstream info on update (diff) | |
| download | soko-4fa6e4b619c0362728955b6ec56eab0e0cbf1e23.tar.gz soko-4fa6e4b619c0362728955b6ec56eab0e0cbf1e23.tar.bz2 soko-4fa6e4b619c0362728955b6ec56eab0e0cbf1e23.zip | |
app/packages/search: sanitized search terms for SQL
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>
| -rw-r--r-- | pkg/api/graphql/resolvers/resolver.go | 6 | ||||
| -rw-r--r-- | pkg/app/handler/packages/search.go | 41 |
2 files changed, 25 insertions, 22 deletions
diff --git a/pkg/api/graphql/resolvers/resolver.go b/pkg/api/graphql/resolvers/resolver.go index 879a764..6f09074 100644 --- a/pkg/api/graphql/resolvers/resolver.go +++ b/pkg/api/graphql/resolvers/resolver.go @@ -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). diff --git a/pkg/app/handler/packages/search.go b/pkg/app/handler/packages/search.go index d325856..5e78f36 100644 --- a/pkg/app/handler/packages/search.go +++ b/pkg/app/handler/packages/search.go @@ -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 @@ -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() } @@ -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), @@ -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 } |
