Only serve image files on ./image
This is an addition to the existing XSS fix in the previous commit.
This commit is contained in:
parent
022603ddf9
commit
33d86e41c2
|
|
@ -328,11 +328,7 @@ func (a *ApplicationAPI) UploadApplicationImage(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := filepath.Ext(file.Filename)
|
ext := filepath.Ext(file.Filename)
|
||||||
|
if !ValidApplicationImageExt(ext) {
|
||||||
switch ext {
|
|
||||||
case ".gif", ".png", ".jpg", ".jpeg":
|
|
||||||
// ok
|
|
||||||
default:
|
|
||||||
ctx.AbortWithError(400, errors.New("invalid file extension"))
|
ctx.AbortWithError(400, errors.New("invalid file extension"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -391,3 +387,12 @@ func generateNonExistingImageName(imgDir string, gen func() string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidApplicationImageExt(ext string) bool {
|
||||||
|
switch ext {
|
||||||
|
case ".gif", ".png", ".jpg", ".jpeg":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -14,7 +16,7 @@ import (
|
||||||
"github.com/gotify/server/v2/config"
|
"github.com/gotify/server/v2/config"
|
||||||
"github.com/gotify/server/v2/database"
|
"github.com/gotify/server/v2/database"
|
||||||
"github.com/gotify/server/v2/docs"
|
"github.com/gotify/server/v2/docs"
|
||||||
"github.com/gotify/server/v2/error"
|
gerror "github.com/gotify/server/v2/error"
|
||||||
"github.com/gotify/server/v2/model"
|
"github.com/gotify/server/v2/model"
|
||||||
"github.com/gotify/server/v2/plugin"
|
"github.com/gotify/server/v2/plugin"
|
||||||
"github.com/gotify/server/v2/ui"
|
"github.com/gotify/server/v2/ui"
|
||||||
|
|
@ -24,8 +26,8 @@ import (
|
||||||
func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Configuration) (*gin.Engine, func()) {
|
func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Configuration) (*gin.Engine, func()) {
|
||||||
g := gin.New()
|
g := gin.New()
|
||||||
|
|
||||||
g.Use(gin.LoggerWithFormatter(logFormatter), gin.Recovery(), error.Handler(), location.Default())
|
g.Use(gin.LoggerWithFormatter(logFormatter), gin.Recovery(), gerror.Handler(), location.Default())
|
||||||
g.NoRoute(error.NotFound())
|
g.NoRoute(gerror.NotFound())
|
||||||
|
|
||||||
streamHandler := stream.New(time.Duration(conf.Server.Stream.PingPeriodSeconds)*time.Second, 15*time.Second, conf.Server.Stream.AllowedOrigins)
|
streamHandler := stream.New(time.Duration(conf.Server.Stream.PingPeriodSeconds)*time.Second, 15*time.Second, conf.Server.Stream.AllowedOrigins)
|
||||||
authentication := auth.Auth{DB: db}
|
authentication := auth.Auth{DB: db}
|
||||||
|
|
@ -61,7 +63,8 @@ func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Co
|
||||||
|
|
||||||
g.GET("/health", healthHandler.Health)
|
g.GET("/health", healthHandler.Health)
|
||||||
g.GET("/swagger", docs.Serve)
|
g.GET("/swagger", docs.Serve)
|
||||||
g.Static("/image", conf.UploadedImagesDir)
|
g.StaticFS("/image", &onlyImageFS{inner: gin.Dir(conf.UploadedImagesDir, false)})
|
||||||
|
|
||||||
g.GET("/docs", docs.UI)
|
g.GET("/docs", docs.UI)
|
||||||
|
|
||||||
g.Use(func(ctx *gin.Context) {
|
g.Use(func(ctx *gin.Context) {
|
||||||
|
|
@ -194,3 +197,15 @@ func logFormatter(param gin.LogFormatterParams) string {
|
||||||
param.ErrorMessage,
|
param.ErrorMessage,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type onlyImageFS struct {
|
||||||
|
inner http.FileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *onlyImageFS) Open(name string) (http.File, error) {
|
||||||
|
ext := filepath.Ext(name)
|
||||||
|
if !api.ValidApplicationImageExt(ext) {
|
||||||
|
return nil, fmt.Errorf("invalid file")
|
||||||
|
}
|
||||||
|
return fs.inner.Open(name)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue