aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Zamarin <arthurzam@gentoo.org>2023-03-17 21:47:34 +0200
committerArthur Zamarin <arthurzam@gentoo.org>2023-03-17 21:47:34 +0200
commit4fa6e4b619c0362728955b6ec56eab0e0cbf1e23 (patch)
tree9a55b4887ce140ea438e9a3b12a9066412e6d72f
parentupdate/packages: override upstream info on update (diff)
downloadsoko-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.go6
-rw-r--r--pkg/app/handler/packages/search.go41
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
}