summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-07-25 00:12:40 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-07-25 11:27:25 +0200
commite5f229974166402f51e4ee0695ffb4d1e09fa174 (patch)
tree44dc7adc4fd02cb563583afaff6ddaa781821e2f /hugolib
parent87a07282a2f01779e098cde0aaee1bae34dc32e6 (diff)
Block symlink dir traversal for /static
This is in line with how it behaved before, but it was lifted a little for the project mount for Hugo Modules, but that could create hard-to-detect loops.
Diffstat (limited to 'hugolib')
-rwxr-xr-xhugolib/data/hugo.toml1
-rw-r--r--hugolib/filesystems/basefs.go36
-rw-r--r--hugolib/filesystems/basefs_test.go10
-rw-r--r--hugolib/hugo_modules_test.go32
-rw-r--r--hugolib/hugo_sites_build_test.go3
-rw-r--r--hugolib/pages_capture_test.go2
6 files changed, 58 insertions, 26 deletions
diff --git a/hugolib/data/hugo.toml b/hugolib/data/hugo.toml
deleted file mode 100755
index eb1dbc42c..000000000
--- a/hugolib/data/hugo.toml
+++ /dev/null
@@ -1 +0,0 @@
-slogan = "Hugo Rocks!" \ No newline at end of file
diff --git a/hugolib/filesystems/basefs.go b/hugolib/filesystems/basefs.go
index 47ae5d0e0..d7dd80630 100644
--- a/hugolib/filesystems/basefs.go
+++ b/hugolib/filesystems/basefs.go
@@ -23,6 +23,8 @@ import (
"strings"
"sync"
+ "github.com/gohugoio/hugo/common/loggers"
+
"github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
@@ -295,8 +297,11 @@ func WithBaseFs(b *BaseFs) func(*BaseFs) error {
}
// NewBase builds the filesystems used by Hugo given the paths and options provided.NewBase
-func NewBase(p *paths.Paths, options ...func(*BaseFs) error) (*BaseFs, error) {
+func NewBase(p *paths.Paths, logger *loggers.Logger, options ...func(*BaseFs) error) (*BaseFs, error) {
fs := p.Fs
+ if logger == nil {
+ logger = loggers.NewWarningLogger()
+ }
publishFs := afero.NewBasePathFs(fs.Destination, p.AbsPublishDir)
@@ -314,7 +319,7 @@ func NewBase(p *paths.Paths, options ...func(*BaseFs) error) (*BaseFs, error) {
return b, nil
}
- builder := newSourceFilesystemsBuilder(p, b)
+ builder := newSourceFilesystemsBuilder(p, logger, b)
sourceFilesystems, err := builder.Build()
if err != nil {
return nil, errors.Wrap(err, "build filesystems")
@@ -327,15 +332,16 @@ func NewBase(p *paths.Paths, options ...func(*BaseFs) error) (*BaseFs, error) {
}
type sourceFilesystemsBuilder struct {
+ logger *loggers.Logger
p *paths.Paths
sourceFs afero.Fs
result *SourceFilesystems
theBigFs *filesystemsCollector
}
-func newSourceFilesystemsBuilder(p *paths.Paths, b *BaseFs) *sourceFilesystemsBuilder {
+func newSourceFilesystemsBuilder(p *paths.Paths, logger *loggers.Logger, b *BaseFs) *sourceFilesystemsBuilder {
sourceFs := hugofs.NewBaseFileDecorator(p.Fs.Source)
- return &sourceFilesystemsBuilder{p: p, sourceFs: sourceFs, theBigFs: b.theBigFs, result: &SourceFilesystems{}}
+ return &sourceFilesystemsBuilder{p: p, logger: logger, sourceFs: sourceFs, theBigFs: b.theBigFs, result: &SourceFilesystems{}}
}
func (b *sourceFilesystemsBuilder) newSourceFilesystem(fs afero.Fs, dirs []hugofs.FileMetaInfo) *SourceFilesystem {
@@ -415,7 +421,7 @@ func (b *sourceFilesystemsBuilder) Build() (*SourceFilesystems, error) {
ms[k] = sfs
}
} else {
- bfs := afero.NewBasePathFs(b.theBigFs.overlayMounts, files.ComponentFolderStatic)
+ bfs := afero.NewBasePathFs(b.theBigFs.overlayMountsStatic, files.ComponentFolderStatic)
ms[""] = b.newSourceFilesystem(bfs, b.result.StaticDirs)
}
@@ -432,7 +438,7 @@ func (b *sourceFilesystemsBuilder) createMainOverlayFs(p *paths.Paths) (*filesys
collector := &filesystemsCollector{
sourceProject: b.sourceFs,
- sourceModules: hugofs.NewNoSymlinkFs(b.sourceFs),
+ sourceModules: hugofs.NewNoSymlinkFs(b.sourceFs, b.logger, false),
overlayDirs: make(map[string][]hugofs.FileMetaInfo),
staticPerLanguage: staticFsMap,
}
@@ -475,6 +481,10 @@ func (b *sourceFilesystemsBuilder) isContentMount(mnt modules.Mount) bool {
return strings.HasPrefix(mnt.Target, files.ComponentFolderContent)
}
+func (b *sourceFilesystemsBuilder) isStaticMount(mnt modules.Mount) bool {
+ return strings.HasPrefix(mnt.Target, files.ComponentFolderStatic)
+}
+
func (b *sourceFilesystemsBuilder) createModFs(
collector *filesystemsCollector,
md mountsDescriptor) error {
@@ -482,6 +492,7 @@ func (b *sourceFilesystemsBuilder) createModFs(
var (
fromTo []hugofs.RootMapping
fromToContent []hugofs.RootMapping
+ fromToStatic []hugofs.RootMapping
)
absPathify := func(path string) string {
@@ -544,6 +555,8 @@ OUTER:
if isContentMount {
fromToContent = append(fromToContent, rm)
+ } else if b.isStaticMount(mount) {
+ fromToStatic = append(fromToStatic, rm)
} else {
fromTo = append(fromTo, rm)
}
@@ -553,6 +566,7 @@ OUTER:
if !md.isMainProject {
modBase = collector.sourceModules
}
+ sourceStatic := hugofs.NewNoSymlinkFs(modBase, b.logger, true)
rmfs, err := hugofs.NewRootMappingFs(modBase, fromTo...)
if err != nil {
@@ -562,17 +576,22 @@ OUTER:
if err != nil {
return err
}
+ rmfsStatic, err := hugofs.NewRootMappingFs(sourceStatic, fromToStatic...)
+ if err != nil {
+ return err
+ }
// We need to keep the ordered list of directories for watching and
// some special merge operations (data, i18n).
collector.addDirs(rmfs)
collector.addDirs(rmfsContent)
+ collector.addDirs(rmfsStatic)
if collector.staticPerLanguage != nil {
for _, l := range b.p.Languages {
lang := l.Lang
- lfs := rmfs.Filter(func(rm hugofs.RootMapping) bool {
+ lfs := rmfsStatic.Filter(func(rm hugofs.RootMapping) bool {
rlang := rm.Meta.Lang()
return rlang == "" || rlang == lang
})
@@ -599,12 +618,14 @@ OUTER:
if collector.overlayMounts == nil {
collector.overlayMounts = rmfs
collector.overlayMountsContent = rmfsContent
+ collector.overlayMountsStatic = rmfsStatic
collector.overlayFull = afero.NewBasePathFs(modBase, md.dir)
collector.overlayResources = afero.NewBasePathFs(modBase, getResourcesDir())
} else {
collector.overlayMounts = afero.NewCopyOnWriteFs(collector.overlayMounts, rmfs)
collector.overlayMountsContent = hugofs.NewLanguageCompositeFs(collector.overlayMountsContent, rmfsContent)
+ collector.overlayMountsStatic = hugofs.NewLanguageCompositeFs(collector.overlayMountsStatic, rmfsStatic)
collector.overlayFull = afero.NewCopyOnWriteFs(collector.overlayFull, afero.NewBasePathFs(modBase, md.dir))
collector.overlayResources = afero.NewCopyOnWriteFs(collector.overlayResources, afero.NewBasePathFs(modBase, getResourcesDir()))
}
@@ -639,6 +660,7 @@ type filesystemsCollector struct {
overlayMounts afero.Fs
overlayMountsContent afero.Fs
+ overlayMountsStatic afero.Fs
overlayFull afero.Fs
overlayResources afero.Fs
diff --git a/hugolib/filesystems/basefs_test.go b/hugolib/filesystems/basefs_test.go
index eccbe00f2..e4efa68e2 100644
--- a/hugolib/filesystems/basefs_test.go
+++ b/hugolib/filesystems/basefs_test.go
@@ -124,7 +124,7 @@ theme = ["atheme"]
p, err := paths.New(fs, v)
assert.NoError(err)
- bfs, err := NewBase(p)
+ bfs, err := NewBase(p, nil)
assert.NoError(err)
assert.NotNil(bfs)
@@ -206,7 +206,7 @@ func TestNewBaseFsEmpty(t *testing.T) {
p, err := paths.New(fs, v)
assert.NoError(err)
- bfs, err := NewBase(p)
+ bfs, err := NewBase(p, nil)
assert.NoError(err)
assert.NotNil(bfs)
assert.NotNil(bfs.Archetypes.Fs)
@@ -263,7 +263,7 @@ func TestRealDirs(t *testing.T) {
p, err := paths.New(fs, v)
assert.NoError(err)
- bfs, err := NewBase(p)
+ bfs, err := NewBase(p, nil)
assert.NoError(err)
assert.NotNil(bfs)
@@ -300,7 +300,7 @@ func TestStaticFs(t *testing.T) {
p, err := paths.New(fs, v)
assert.NoError(err)
- bfs, err := NewBase(p)
+ bfs, err := NewBase(p, nil)
assert.NoError(err)
sfs := bfs.StaticFs("en")
@@ -344,7 +344,7 @@ func TestStaticFsMultiHost(t *testing.T) {
p, err := paths.New(fs, v)
assert.NoError(err)
- bfs, err := NewBase(p)
+ bfs, err := NewBase(p, nil)
assert.NoError(err)
enFs := bfs.StaticFs("en")
checkFileContent(enFs, "f1.txt", assert, "Hugo Rocks!")
diff --git a/hugolib/hugo_modules_test.go b/hugolib/hugo_modules_test.go
index dc0da2e1c..171bbb347 100644
--- a/hugolib/hugo_modules_test.go
+++ b/hugolib/hugo_modules_test.go
@@ -443,6 +443,7 @@ weight = 2
`
b := newTestSitesBuilder(t).WithNothingAdded().WithWorkingDir(workDir)
+ b.WithLogger(loggers.NewErrorLogger())
b.Fs = fs
b.WithConfigFile("toml", config)
@@ -457,35 +458,46 @@ weight = 2
bfs := b.H.BaseFs
- for _, componentFs := range []afero.Fs{
+ for i, componentFs := range []afero.Fs{
+ bfs.Static[""].Fs,
bfs.Archetypes.Fs,
bfs.Content.Fs,
bfs.Data.Fs,
bfs.Assets.Fs,
- bfs.Static[""].Fs,
bfs.I18n.Fs} {
- for i, id := range []string{"mod", "project"} {
+ if i != 0 {
+ continue
+ }
+
+ for j, id := range []string{"mod", "project"} {
+
+ statCheck := func(fs afero.Fs, filename string, isDir bool) {
+ shouldFail := j == 0
+ if !shouldFail && i == 0 {
+ // Static dirs only supports symlinks for files
+ shouldFail = isDir
+ }
- statCheck := func(fs afero.Fs, filename string) {
- shouldFail := i == 0
_, err := fs.Stat(filepath.FromSlash(filename))
+
if err != nil {
- if strings.HasSuffix(filename, "toml") && strings.Contains(err.Error(), "files not supported") {
+ if i > 0 && strings.HasSuffix(filename, "toml") && strings.Contains(err.Error(), "files not supported") {
// OK
return
}
}
+
if shouldFail {
assert.Error(err)
- assert.Equal(hugofs.ErrPermissionSymlink, err)
+ assert.Equal(hugofs.ErrPermissionSymlink, err, filename)
} else {
- assert.NoError(err)
+ assert.NoError(err, filename)
}
}
- statCheck(componentFs, fmt.Sprintf("realsym%s", id))
- statCheck(componentFs, fmt.Sprintf("real/datasym%s.toml", id))
+ statCheck(componentFs, fmt.Sprintf("realsym%s", id), true)
+ statCheck(componentFs, fmt.Sprintf("real/datasym%s.toml", id), false)
}
}
diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go
index 6ff8ae4d2..876f21cfa 100644
--- a/hugolib/hugo_sites_build_test.go
+++ b/hugolib/hugo_sites_build_test.go
@@ -2,7 +2,6 @@ package hugolib
import (
"fmt"
- "os"
"strings"
"testing"
@@ -1282,7 +1281,7 @@ func readFileFromFs(t testing.TB, fs afero.Fs, filename string) string {
root = helpers.FilePathSeparator + root
}
- helpers.PrintFs(fs, root, os.Stdout)
+ //helpers.PrintFs(fs, root, os.Stdout)
t.Fatalf("Failed to read file: %s", err)
}
return string(b)
diff --git a/hugolib/pages_capture_test.go b/hugolib/pages_capture_test.go
index f8a7833be..38391f85c 100644
--- a/hugolib/pages_capture_test.go
+++ b/hugolib/pages_capture_test.go
@@ -52,7 +52,7 @@ func TestPagesCapture(t *testing.T) {
writeFile("pages/page2.md")
writeFile("pages/page.png")
- ps, err := helpers.NewPathSpec(hugofs.NewFrom(fs, cfg), cfg)
+ ps, err := helpers.NewPathSpec(hugofs.NewFrom(fs, cfg), cfg, loggers.NewErrorLogger())
assert.NoError(err)
sourceSpec := source.NewSourceSpec(ps, fs)