diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index fc02e94d8c..a7e64e1e46 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "runtime/trace" + "strings" "sync" "google.golang.org/grpc" @@ -208,8 +209,21 @@ func (g *generator) ProcessResult(ctx context.Context, combo config.CombinedSett files[file.Name] = string(file.Contents) } g.m.Lock() + + // out is specified by the user, not a plugin + absout := filepath.Join(g.dir, out) + for n, source := range files { filename := filepath.Join(g.dir, out, n) + // filepath.Join calls filepath.Clean which should remove all "..", but + // double check to make sure + if strings.Contains(filename, "..") { + return fmt.Errorf("invalid file output path: %s", filename) + } + // The output file must be contained inside the output directory + if !strings.HasPrefix(filename, absout) { + return fmt.Errorf("invalid file output path: %s", filename) + } g.output[filename] = source } g.m.Unlock() diff --git a/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/query.sql b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/query.sql new file mode 100644 index 0000000000..75e38b2caf --- /dev/null +++ b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/query.sql @@ -0,0 +1,19 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/schema.sql b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/schema.sql new file mode 100644 index 0000000000..b4fad78497 --- /dev/null +++ b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/sqlc.json b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/sqlc.json new file mode 100644 index 0000000000..bb84bddebf --- /dev/null +++ b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/sqlc.json @@ -0,0 +1,25 @@ +{ + "version": "2", + "sql": [ + { + "schema": "schema.sql", + "queries": "query.sql", + "engine": "postgresql", + "codegen": [ + { + "out": "gen", + "plugin": "test" + } + ] + } + ], + "plugins": [ + { + "name": "test", + "wasm": { + "url": "https://github.com/sqlc-dev/sqlc-gen-unsafe-paths/releases/download/v0.1.1/sqlc-gen-unsafe-paths.wasm", + "sha256": "e53ac951dd41b1e4c365e757d9735886f7c8e92f2056ce0be9a5cfcf677c45d9" + } + } + ] +} diff --git a/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/stderr.txt b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/stderr.txt new file mode 100644 index 0000000000..8d664b0612 --- /dev/null +++ b/internal/endtoend/testdata/wasm_plugin_sqlc_gen_unsafe_paths/stderr.txt @@ -0,0 +1,2 @@ +# package test +error generating code: invalid file output path: /tmp/unsafe.txt