From 5747ed93a09b81e3bebe49a509bc909c842af027 Mon Sep 17 00:00:00 2001 From: GGOBP Date: Thu, 3 Sep 2026 09:24:35 +0900 Subject: [PATCH] Lock PAT transport as inert request data Fixes glendix-labs/mendraw#1 --- src/mxpak/config/env_reader.gleam | 27 +++++++++++++++++++++---- test/config_test.gleam | 33 +++++++++++++++++++++++++++++++ test/registry_test.gleam | 16 +++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/mxpak/config/env_reader.gleam b/src/mxpak/config/env_reader.gleam index 7c43a47..a788e6f 100644 --- a/src/mxpak/config/env_reader.gleam +++ b/src/mxpak/config/env_reader.gleam @@ -57,8 +57,27 @@ fn read_from_dotenv( } } -fn strip_quotes(s: String) -> String { - s - |> string.replace("\"", "") - |> string.replace("'", "") +fn strip_quotes(value value: String) -> String { + case + string.length(value) >= 2 + && string.starts_with(value, "\"") + && string.ends_with(value, "\"") + { + True -> + value + |> string.drop_start(1) + |> string.drop_end(1) + False -> + case + string.length(value) >= 2 + && string.starts_with(value, "'") + && string.ends_with(value, "'") + { + True -> + value + |> string.drop_start(1) + |> string.drop_end(1) + False -> value + } + } } diff --git a/test/config_test.gleam b/test/config_test.gleam index 943ca1d..56f2428 100644 --- a/test/config_test.gleam +++ b/test/config_test.gleam @@ -335,6 +335,39 @@ pub fn env_reader_quoted_value_test() -> Nil { Nil } +/// Verifies hostile dotenv values are preserved as inert data. +pub fn env_reader_hostile_value_test() -> Nil { + let dir = "build/test_tmp/env3" + simplifile.create_directory_all(dir) + |> should.be_ok + simplifile.write( + dir <> "/.env", + "MENDIX_PAT=$(touch /tmp/mendraw-pwned)`id`'a\"b&whoami\n", + ) + |> should.be_ok + env_reader.get("MENDIX_PAT", dir) + |> should.be_ok + |> should.equal(option.Some("$(touch /tmp/mendraw-pwned)`id`'a\"b&whoami")) + simplifile.delete(dir) + |> should.be_ok + Nil +} + +/// Verifies only one surrounding quote pair is removed. +pub fn env_reader_inner_quotes_are_preserved_test() -> Nil { + let dir = "build/test_tmp/env4" + simplifile.create_directory_all(dir) + |> should.be_ok + simplifile.write(dir <> "/.env", "KEY=\"a\"b\"\n") + |> should.be_ok + env_reader.get("KEY", dir) + |> should.be_ok + |> should.equal(option.Some("a\"b")) + simplifile.delete(dir) + |> should.be_ok + Nil +} + /// Verifies env reader missing file behavior. pub fn env_reader_missing_file_test() -> Nil { env_reader.get("KEY", "build/test_tmp/no_env") diff --git a/test/registry_test.gleam b/test/registry_test.gleam index a9995a3..1349d61 100644 --- a/test/registry_test.gleam +++ b/test/registry_test.gleam @@ -33,6 +33,22 @@ pub fn content_page_request_invalid_bounds_test() -> Nil { |> should.equal(Error(content_api.InvalidPageBounds(offset: -1, limit: 0))) } +/// Verifies hostile tokens stay inert request data instead of shell input. +pub fn hostile_pat_is_carried_verbatim_test() -> Nil { + let hostile = "$(touch /tmp/mendraw-pwned)`id`'a\"b&whoami" + let request = + content_api.content_page_request(hostile, 0, 40) + |> should.be_ok + request.headers + |> list.key_find("authorization") + |> should.equal(Ok("MxToken " <> hostile)) + let versions_request = content_api.versions_request(hostile, 7) + versions_request.headers + |> list.key_find("authorization") + |> should.equal(Ok("MxToken " <> hostile)) + Nil +} + /// Verifies the Sans-IO response decoder filters unsupported content types. pub fn content_page_response_contract_test() -> Nil { let body =