From 095f56a5b1c8d10059d6c1fa737f364ff6a4d9fb Mon Sep 17 00:00:00 2001 From: DarthSim Date: Mon, 25 Mar 2024 18:39:33 +0300 Subject: [PATCH] Check bucket name and object key in S3, GCS, ABS, and Swift integrations --- CHANGELOG.md | 3 +++ transport/azure/azure.go | 19 +++++++++++++++++-- transport/gcs/gcs.go | 22 ++++++++++++++++++++-- transport/s3/s3.go | 22 ++++++++++++++++++++-- transport/swift/swift.go | 15 +++++++++++++++ 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61cbf5de..26b3d007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Add - Add [IMGPROXY_ALWAYS_RASTERIZE_SVG](https://docs.imgproxy.net/latest/configuration/options#IMGPROXY_ALWAYS_RASTERIZE_SVG) config. +### Change +- Respond with 404 when the bucket/container name or object key is empty in an S3, Google Cloud Storage, Azure Blob Storage, or OpenStack Object Storage (Swift) URL. + ## [3.23.0] - 2024-03-11 ### Add - Add request ID, processing/info options, and source image URL to error reports. diff --git a/transport/azure/azure.go b/transport/azure/azure.go index b91dbbd6..968363bb 100644 --- a/transport/azure/azure.go +++ b/transport/azure/azure.go @@ -84,7 +84,22 @@ func New() (http.RoundTripper, error) { func (t transport) RoundTrip(req *http.Request) (*http.Response, error) { container := req.URL.Host - key := req.URL.Path + key := strings.TrimPrefix(req.URL.Path, "/") + + if len(container) == 0 || len(key) == 0 { + body := strings.NewReader("Invalid ABS URL: container name or object key is empty") + return &http.Response{ + StatusCode: http.StatusNotFound, + Proto: "HTTP/1.0", + ProtoMajor: 1, + ProtoMinor: 0, + Header: http.Header{}, + ContentLength: int64(body.Len()), + Body: io.NopCloser(body), + Close: false, + Request: req, + }, nil + } statusCode := http.StatusOK @@ -112,7 +127,7 @@ func (t transport) RoundTrip(req *http.Request) (*http.Response, error) { statusCode = http.StatusPartialContent } - result, err := t.client.DownloadStream(req.Context(), container, strings.TrimPrefix(key, "/"), opts) + result, err := t.client.DownloadStream(req.Context(), container, key, opts) if err != nil { if azError, ok := err.(*azcore.ResponseError); !ok || azError.StatusCode < 100 || azError.StatusCode == 301 { return nil, err diff --git a/transport/gcs/gcs.go b/transport/gcs/gcs.go index 0f9cb5c2..ca09ec4e 100644 --- a/transport/gcs/gcs.go +++ b/transport/gcs/gcs.go @@ -77,8 +77,26 @@ func New() (http.RoundTripper, error) { } func (t transport) RoundTrip(req *http.Request) (*http.Response, error) { - bkt := t.client.Bucket(req.URL.Host) - obj := bkt.Object(strings.TrimPrefix(req.URL.Path, "/")) + bucket := req.URL.Host + key := strings.TrimPrefix(req.URL.Path, "/") + + if len(bucket) == 0 || len(key) == 0 { + body := strings.NewReader("Invalid GCS URL: bucket name or object key is empty") + return &http.Response{ + StatusCode: http.StatusNotFound, + Proto: "HTTP/1.0", + ProtoMajor: 1, + ProtoMinor: 0, + Header: http.Header{}, + ContentLength: int64(body.Len()), + Body: io.NopCloser(body), + Close: false, + Request: req, + }, nil + } + + bkt := t.client.Bucket(bucket) + obj := bkt.Object(key) if g, err := strconv.ParseInt(req.URL.RawQuery, 10, 64); err == nil && g > 0 { obj = obj.Generation(g) diff --git a/transport/s3/s3.go b/transport/s3/s3.go index 5f72a46e..82444866 100644 --- a/transport/s3/s3.go +++ b/transport/s3/s3.go @@ -94,9 +94,27 @@ func New() (http.RoundTripper, error) { } func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { + bucket := req.URL.Host + key := strings.TrimPrefix(req.URL.Path, "/") + + if len(bucket) == 0 || len(key) == 0 { + body := strings.NewReader("Invalid S3 URL: bucket name or object key is empty") + return &http.Response{ + StatusCode: http.StatusNotFound, + Proto: "HTTP/1.0", + ProtoMajor: 1, + ProtoMinor: 0, + Header: http.Header{}, + ContentLength: int64(body.Len()), + Body: io.NopCloser(body), + Close: false, + Request: req, + }, nil + } + input := &s3.GetObjectInput{ - Bucket: aws.String(req.URL.Host), - Key: aws.String(strings.TrimPrefix(req.URL.Path, "/")), + Bucket: aws.String(bucket), + Key: aws.String(key), } if len(req.URL.RawQuery) > 0 { diff --git a/transport/swift/swift.go b/transport/swift/swift.go index ba00e498..c1def357 100644 --- a/transport/swift/swift.go +++ b/transport/swift/swift.go @@ -54,6 +54,21 @@ func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error) container := req.URL.Host objectName := strings.TrimPrefix(req.URL.Path, "/") + if len(container) == 0 || len(objectName) == 0 { + body := strings.NewReader("Invalid Swift URL: container name or object name is empty") + return &http.Response{ + StatusCode: http.StatusNotFound, + Proto: "HTTP/1.0", + ProtoMajor: 1, + ProtoMinor: 0, + Header: http.Header{}, + ContentLength: int64(body.Len()), + Body: io.NopCloser(body), + Close: false, + Request: req, + }, nil + } + reqHeaders := make(swift.Headers) if r := req.Header.Get("Range"); len(r) > 0 { reqHeaders["Range"] = r