diff --git a/config.go b/config.go index 1a409516..d8f64af6 100644 --- a/config.go +++ b/config.go @@ -36,6 +36,20 @@ func strEnvConfig(s *string, name string) { } } +func strSliceEnvConfig(s *[]string, name string) { + if env := os.Getenv(name); len(env) > 0 { + parts := strings.Split(env, ",") + + for i, p := range parts { + parts[i] = strings.TrimSpace(p) + } + + *s = parts + } + + *s = []string{} +} + func boolEnvConfig(b *bool, name string) { if env, err := strconv.ParseBool(os.Getenv(name)); err == nil { *b = env @@ -128,16 +142,6 @@ func presetFileConfig(p presets, filepath string) { } } -func sourceEnvConfig(allowedsources *[]string, name string) { - sources := []string{} - if env := os.Getenv(name); len(env) > 0 { - for _, source := range strings.Split(env, ",") { - sources = append(sources, fmt.Sprintf("%s://", strings.TrimSpace(source))) - } - } - *allowedsources = sources -} - type config struct { Bind string ReadTimeout int @@ -286,7 +290,7 @@ func configure() { } intEnvConfig(&conf.MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES") - sourceEnvConfig(&conf.AllowedSources, "IMGPROXY_ALLOWED_SOURCES") + strSliceEnvConfig(&conf.AllowedSources, "IMGPROXY_ALLOWED_SOURCES") boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE") boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED") diff --git a/docs/configuration.md b/docs/configuration.md index ad8fe20d..e6455cf2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -59,14 +59,14 @@ imgproxy does not send CORS headers by default. Specify allowed origin to enable * `IMGPROXY_ALLOW_ORIGIN`: when set, enables CORS headers with provided origin. CORS headers are disabled by default. +You can limit allowed protocols of the source URLs: + +* `IMGPROXY_ALLOWED_SOURCES`: whitelist of source image URLs prefixes divided by comma. When blank, imgproxy allows all source image URLs. Example: `s3://,https://example.com/,local://`. Default: blank. + When you use imgproxy in a development environment, it can be useful to ignore SSL verification: * `IMGPROXY_IGNORE_SSL_VERIFICATION`: when true, disables SSL verification, so imgproxy can be used in a development environment with self-signed SSL certificates. -You can limit allowed protocols of the source URLs: - -* `IMGPROXY_ALLOWED_SOURCES`: when set, limits allowed source URL protocols. Example: `https,s3,local`. Default: blank. - Also you may want imgproxy to respond with the same error message that it writes to the log: * `IMGPROXY_DEVELOPMENT_ERRORS_MODE`: when true, imgproxy will respond with detailed error messages. Not recommended for production because some errors may contain stack trace. diff --git a/processing_options_test.go b/processing_options_test.go index fb66b834..6f5b0cfd 100644 --- a/processing_options_test.go +++ b/processing_options_test.go @@ -106,6 +106,24 @@ func (s *ProcessingOptionsTestSuite) TestParsePlainURLEscapedWithBase() { assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format) } +func (s *ProcessingOptionsTestSuite) TestParseURLAllowedSource() { + conf.AllowedSources = []string{"local://", "http://images.dev/"} + + req := s.getRequest("http://example.com/unsafe/plain/http://images.dev/lorem/ipsum.jpg") + _, err := parsePath(context.Background(), req) + + require.Nil(s.T(), err) +} + +func (s *ProcessingOptionsTestSuite) TestParseURLNotAllowedSource() { + conf.AllowedSources = []string{"local://", "http://images.dev/"} + + req := s.getRequest("http://example.com/unsafe/plain/s3://images/lorem/ipsum.jpg") + _, err := parsePath(context.Background(), req) + + require.Error(s.T(), err) +} + func (s *ProcessingOptionsTestSuite) TestParsePathBasic() { req := s.getRequest("http://example.com/unsafe/fill/100/200/noea/1/plain/http://images.dev/lorem/ipsum.jpg@png") ctx, err := parsePath(context.Background(), req)