summaryrefslogtreecommitdiff
path: root/internal/processor/markdown_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-27 08:33:38 +0300
committerPaul Buetow <paul@buetow.org>2026-04-27 08:33:44 +0300
commit257057748a2cf2070fbeb722a94772857b5d014f (patch)
treecd3110920d12d2b22ba4918898aa4437799d1bba /internal/processor/markdown_test.go
parent8b37e6e04035f9f8a3d01701dae121cdc67cbf43 (diff)
processor: reject markdown image refs with path separators or parent traversal
findLocalImages used filepath.Base(ref) after stat succeeded, which caused subdirectory or parent-directory references to pass the scan but then fail during copy because the basename was looked up in the wrong directory. Fix: add isSimpleImageRef helper that accepts only flat filenames (no path separators, no .. traversal). findLocalImages now returns the ref unchanged, matching what copyLocalImages and claimedByMarkdown expect. Added tests for isSimpleImageRef and negative findLocalImages cases for subdirectory and parent-directory references.
Diffstat (limited to 'internal/processor/markdown_test.go')
-rw-r--r--internal/processor/markdown_test.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/processor/markdown_test.go b/internal/processor/markdown_test.go
index 2445b53..c53874d 100644
--- a/internal/processor/markdown_test.go
+++ b/internal/processor/markdown_test.go
@@ -9,6 +9,33 @@ import (
"codeberg.org/snonux/snonux/internal/config"
)
+func TestIsSimpleImageRef(t *testing.T) {
+ t.Parallel()
+
+ cases := []struct {
+ ref string
+ want bool
+ }{
+ {"img.png", true},
+ {"a.png", true},
+ {"sub/img.png", false},
+ {"a/b/c.png", false},
+ {"../img.png", false},
+ {"img/../other.png", false},
+ {"/etc/passwd", false},
+ }
+
+ for _, c := range cases {
+ t.Run(c.ref, func(t *testing.T) {
+ t.Parallel()
+ got := isSimpleImageRef(c.ref)
+ if got != c.want {
+ t.Fatalf("isSimpleImageRef(%q) = %v; want %v", c.ref, got, c.want)
+ }
+ })
+ }
+}
+
func TestFindLocalImages(t *testing.T) {
t.Parallel()
@@ -42,6 +69,38 @@ func TestFindLocalImages(t *testing.T) {
}
})
+ t.Run("subdir ref ignored even if file exists", func(t *testing.T) {
+ t.Parallel()
+ dir := t.TempDir()
+ if err := os.MkdirAll(filepath.Join(dir, "sub"), 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(filepath.Join(dir, "sub", "photo.png"), []byte("x"), 0o644); err != nil {
+ t.Fatal(err)
+ }
+ got := findLocalImages(`![](sub/photo.png)`, dir)
+ if len(got) != 0 {
+ t.Fatalf("expected no locals for subdir ref, got %v", got)
+ }
+ })
+
+ t.Run("parent traversal ref ignored even if file exists", func(t *testing.T) {
+ t.Parallel()
+ // Create a layout where ../photo.png from dir would resolve to a real file.
+ base := t.TempDir()
+ dir := filepath.Join(base, "inbox")
+ if err := os.MkdirAll(dir, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(filepath.Join(base, "photo.png"), []byte("x"), 0o644); err != nil {
+ t.Fatal(err)
+ }
+ got := findLocalImages(`![](../photo.png)`, dir)
+ if len(got) != 0 {
+ t.Fatalf("expected no locals for traversal ref, got %v", got)
+ }
+ })
+
tests := []struct {
name string
md string
@@ -62,6 +121,7 @@ func TestFindLocalImages(t *testing.T) {
want: []string{"z.gif"},
wantLen: 1,
},
+
}
for _, tt := range tests {