Skip to content

Commit

Permalink
Fixes #7698.
Browse files Browse the repository at this point in the history
markup: Allow installed arbitrary Asciidoc extension via path validation.
  • Loading branch information
gzagatti committed Jan 24, 2021
1 parent 0004a73 commit d5c5c2f
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 22 deletions.
2 changes: 2 additions & 0 deletions docs/content/en/content-management/formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Below are all the AsciiDoc related settings in Hugo with their default values:

{{< code-toggle config="markup.asciidocExt" />}}

Notice that for security concerns only extensions that do not have path separators (either `\`, `/` or `.`) are allowed. That means that extensions can only be invoked if they are in one's ruby's `$LOAD_PATH` (ie. most likely, the extension has been installed by the user). Any extension declared relative to the website's path will not be accepted.

Example of how to set extensions and attributes:

```
Expand Down
12 changes: 0 additions & 12 deletions markup/asciidocext/asciidocext_config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,6 @@ var (
FailureLevel: "fatal",
}

AllowedExtensions = map[string]bool{
"asciidoctor-html5s": true,
"asciidoctor-bibtex": true,
"asciidoctor-diagram": true,
"asciidoctor-interdoc-reftext": true,
"asciidoctor-katex": true,
"asciidoctor-latex": true,
"asciidoctor-mathematical": true,
"asciidoctor-question": true,
"asciidoctor-rouge": true,
}

AllowedSafeMode = map[string]bool{
"unsafe": true,
"safe": true,
Expand Down
6 changes: 3 additions & 3 deletions markup/asciidocext/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package asciidocext

import (
"bytes"
"strings"
"path/filepath"

"github.com/gohugoio/hugo/htesting"
Expand Down Expand Up @@ -105,11 +106,10 @@ func (a *asciidocConverter) parseArgs(ctx converter.DocumentContext) []string {
args = a.appendArg(args, "-b", cfg.Backend, asciidocext_config.CliDefault.Backend, asciidocext_config.AllowedBackend)

for _, extension := range cfg.Extensions {
if !asciidocext_config.AllowedExtensions[extension] {
a.cfg.Logger.Errorln("Unsupported asciidoctor extension was passed in. Extension `" + extension + "` ignored.")
if strings.LastIndexAny(extension, `\/.`) > -1 {
a.cfg.Logger.Errorln("Unsupported asciidoctor extension was passed in. Extension `" + extension + "` ignored. Only installed asciidoctor extensions are allowed.")
continue
}

args = append(args, "-r", extension)
}

Expand Down
46 changes: 39 additions & 7 deletions markup/asciidocext/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestAsciidoctorDisallowedArgs(t *testing.T) {
cfg := viper.New()
mconf := markup_config.Default
mconf.AsciidocExt.Backend = "disallowed-backend"
mconf.AsciidocExt.Extensions = []string{"disallowed-extension"}
mconf.AsciidocExt.Extensions = []string{"./disallowed-extension"}
mconf.AsciidocExt.Attributes = map[string]string{"outdir": "disallowed-attribute"}
mconf.AsciidocExt.SafeMode = "disallowed-safemode"
mconf.AsciidocExt.FailureLevel = "disallowed-failurelevel"
Expand All @@ -115,14 +115,11 @@ func TestAsciidoctorDisallowedArgs(t *testing.T) {
c.Assert(args, qt.DeepEquals, expected)
}

func TestAsciidoctorDiagramArgs(t *testing.T) {
func TestAsciidoctorArbitraryExtension(t *testing.T) {
c := qt.New(t)
cfg := viper.New()
mconf := markup_config.Default
mconf.AsciidocExt.NoHeaderOrFooter = true
mconf.AsciidocExt.Extensions = []string{"asciidoctor-html5s", "asciidoctor-diagram"}
mconf.AsciidocExt.Backend = "html5s"
mconf.AsciidocExt.Trace = false
mconf.AsciidocExt.Extensions = []string{"arbitrary-extension"}
p, err := Provider.New(
converter.ProviderConfig{
Cfg: cfg,
Expand All @@ -139,10 +136,45 @@ func TestAsciidoctorDiagramArgs(t *testing.T) {
c.Assert(ac, qt.Not(qt.IsNil))

args := ac.parseArgs(converter.DocumentContext{})
expected := []string{"-b", "html5s", "-r", "asciidoctor-html5s", "-r", "asciidoctor-diagram", "--no-header-footer"}
expected := []string{"-r", "arbitrary-extension", "--no-header-footer"}
c.Assert(args, qt.DeepEquals, expected)
}

func TestAsciidoctorDisallowedExtension(t *testing.T) {
c := qt.New(t)
cfg := viper.New()
for _, disallowedExtension := range []string{
`foo-bar//`,
`foo-bar\\ `,
`../../foo-bar`,
`/foo-bar`,
`C:\foo-bar`,
`foo-bar.rb`,
`foo.bar`,
} {
mconf := markup_config.Default
mconf.AsciidocExt.Extensions = []string{disallowedExtension}
p, err := Provider.New(
converter.ProviderConfig{
Cfg: cfg,
MarkupConfig: mconf,
Logger: loggers.NewErrorLogger(),
},
)
c.Assert(err, qt.IsNil)

conv, err := p.New(converter.DocumentContext{})
c.Assert(err, qt.IsNil)

ac := conv.(*asciidocConverter)
c.Assert(ac, qt.Not(qt.IsNil))

args := ac.parseArgs(converter.DocumentContext{})
expected := []string{"--no-header-footer"}
c.Assert(args, qt.DeepEquals, expected)
}
}

func TestAsciidoctorWorkingFolderCurrent(t *testing.T) {
c := qt.New(t)
cfg := viper.New()
Expand Down

0 comments on commit d5c5c2f

Please sign in to comment.