diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-07-25 00:12:40 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-07-25 11:27:25 +0200 |
commit | e5f229974166402f51e4ee0695ffb4d1e09fa174 (patch) | |
tree | 44dc7adc4fd02cb563583afaff6ddaa781821e2f /hugolib | |
parent | 87a07282a2f01779e098cde0aaee1bae34dc32e6 (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-x | hugolib/data/hugo.toml | 1 | ||||
-rw-r--r-- | hugolib/filesystems/basefs.go | 36 | ||||
-rw-r--r-- | hugolib/filesystems/basefs_test.go | 10 | ||||
-rw-r--r-- | hugolib/hugo_modules_test.go | 32 | ||||
-rw-r--r-- | hugolib/hugo_sites_build_test.go | 3 | ||||
-rw-r--r-- | hugolib/pages_capture_test.go | 2 |
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) |