From 27e5a0faba95f41b0826a84454d65250cbeac983 Mon Sep 17 00:00:00 2001 From: Francesc Campoy Date: Fri, 10 Apr 2026 19:41:45 -0700 Subject: [PATCH] Remove stdin mode: require explicit file arguments Without a base directory there is no boundary to enforce for path traversal checks, so any embed directive passed via stdin can read arbitrary files on the host. Additionally, stdin mode has little practical utility because local file paths embedded in a document have no anchor without a known base directory. This commit removes the stdin-reading path entirely. Calling embedmd with no file arguments now exits with an error instead of blocking on stdin. The `stdin` package-level variable and all associated branches in `embed` are deleted; `TestEmbedStreams` is replaced by `TestEmbedNoPaths` which verifies the new error behaviour. Follow-up to #84. --- main.go | 27 ++++---------------------- main_test.go | 55 ++++++++-------------------------------------------- 2 files changed, 12 insertions(+), 70 deletions(-) diff --git a/main.go b/main.go index 4218595..d7cd0b3 100644 --- a/main.go +++ b/main.go @@ -19,8 +19,8 @@ // markdown is rendered, so they can be kept in the file as pointers // to the origin of the embedded text. // -// The command receives a list of markdown files, if none is given it -// reads from the standard input. +// The command receives a list of markdown files to process. At least one +// file must be provided; reading from standard input is not supported. // // embedmd supports two flags: // -d: will print the difference of the input file with what the output @@ -77,10 +77,7 @@ func main() { } } -var ( - stdout io.Writer = os.Stdout - stdin io.Reader = os.Stdin -) +var stdout io.Writer = os.Stdout func embed(paths []string, rewrite, doDiff bool) (foundDiff bool, err error) { if rewrite && doDiff { @@ -88,23 +85,7 @@ func embed(paths []string, rewrite, doDiff bool) (foundDiff bool, err error) { } if len(paths) == 0 { - if rewrite { - return false, fmt.Errorf("error: cannot use -w with standard input") - } - if !doDiff { - return false, embedmd.Process(stdout, stdin) - } - - var out, in bytes.Buffer - if err := embedmd.Process(&out, io.TeeReader(stdin, &in)); err != nil { - return false, err - } - d, err := diff(in.String(), out.String()) - if err != nil || len(d) == 0 { - return false, err - } - fmt.Fprintf(stdout, "%s", d) - return true, nil + return false, fmt.Errorf("error: no markdown files provided") } for _, path := range paths { diff --git a/main_test.go b/main_test.go index 76c4bb7..35211f3 100644 --- a/main_test.go +++ b/main_test.go @@ -23,63 +23,24 @@ import ( "github.com/campoy/embedmd/internal/testutil" ) -func TestEmbedStreams(t *testing.T) { +func TestEmbedNoPaths(t *testing.T) { tc := []struct { - name string - in, out string - err string - d, w bool - foundDiff bool + name string + err string + d, w bool }{ - {name: "just some text", - in: "# hello\ntest\n", - out: "# hello\ntest\n", - }, - {name: "can't rewrite stdin", - w: true, - err: "error: cannot use -w with standard input", + {name: "no files provided", + err: "error: no markdown files provided", }, {name: "can't diff and rewrite", w: true, d: true, err: "error: cannot use -w and -d simultaneously", }, - {name: "empty diff", - d: true, - in: "# hello\ntest\n", - foundDiff: false, - }, - {name: "non empty diff", - d: true, - in: "# hello\ntest", - out: `@@ -1,2 +1,3 @@ - # hello - test -+ -`, - foundDiff: true, - }, } - defer func(r io.Reader, w io.Writer) { stdin, stdout = r, w }(stdin, stdout) - for _, tt := range tc { - stdin = strings.NewReader(tt.in) - buf := &bytes.Buffer{} - stdout = buf - foundDiff, err := embed(nil, tt.w, tt.d) - if !testutil.EqErr(t, tt.name, err, tt.err) { - continue - } - if got := buf.String(); tt.out != got { - t.Errorf("case [%s] expected output\n%q\n; got\n%q", tt.name, tt.out, got) - } - if tt.d && foundDiff != tt.foundDiff { - if foundDiff { - t.Errorf("case [%s] expected to find a diff, but didn't", tt.name) - } else { - t.Errorf("case [%s] didn't expect to find a diff, but did", tt.name) - } - } + _, err := embed(nil, tt.w, tt.d) + testutil.EqErr(t, tt.name, err, tt.err) } }