diff --git a/embedmd/embedmd.go b/embedmd/embedmd.go index aed9eea..7195f07 100644 --- a/embedmd/embedmd.go +++ b/embedmd/embedmd.go @@ -49,6 +49,12 @@ // go, this will fail with other files like .md whose language name is markdown. // // [embedmd]:# (file.ext) +// +// Security note: embed directives, including their regular expression patterns, +// are treated as trusted input. Markdown files containing embedmd directives +// should not be sourced from untrusted contributors without careful review, as +// a crafted regular expression could match unintended content from the embedded +// file. package embedmd import ( @@ -122,7 +128,7 @@ func extract(b []byte, start, end *string) ([]byte, error) { } re, err := regexp.CompilePOSIX(s[1 : len(s)-1]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid regexp %s: %v", s, err) } loc := re.FindIndex(b) if loc == nil { diff --git a/embedmd/embedmd_test.go b/embedmd/embedmd_test.go index dba20d1..3015ab6 100644 --- a/embedmd/embedmd_test.go +++ b/embedmd/embedmd_test.go @@ -62,14 +62,24 @@ func TestExtract(t *testing.T) { start: testutil.Ptr("/func main/"), end: testutil.Ptr("/}/"), out: "func main() {\n fmt.Println(\"hello, test\")\n}"}, {name: "bad start regexp", - start: testutil.Ptr("/(/"), err: "error parsing regexp: missing closing ): `(`"}, + start: testutil.Ptr("/(/"), err: "invalid regexp /(/: error parsing regexp: missing closing ): `(`"}, {name: "bad regexp", start: testutil.Ptr("something"), err: "missing slashes (/) around \"something\""}, {name: "bad end regexp", - start: testutil.Ptr("/fmt.P/"), end: testutil.Ptr("/)/"), err: "error parsing regexp: unexpected ): `)`"}, + start: testutil.Ptr("/fmt.P/"), end: testutil.Ptr("/)/"), err: "invalid regexp /)/: error parsing regexp: unexpected ): `)`"}, {name: "start and end of line ^$", start: testutil.Ptr("/^func main/"), end: testutil.Ptr("/}$/"), out: "func main() {\n fmt.Println(\"hello, test\")\n}"}, + + // Error message quality: invalid patterns should include the pattern string. + {name: "invalid regexp shows pattern in error", + start: testutil.Ptr("/[invalid/"), err: "invalid regexp /[invalid/: error parsing regexp: missing closing ]: `[invalid`"}, + // Missing slashes should report the raw value. + {name: "missing slashes reports value", + start: testutil.Ptr("noSlashes"), err: "missing slashes (/) around \"noSlashes\""}, + // Valid pattern regression: correctly matches a simple pattern. + {name: "valid pattern still works", + start: testutil.Ptr("/fmt\\.Println/"), out: "fmt.Println"}, } for _, tt := range tc {