diff --git a/lib/kamal/env_file.rb b/lib/kamal/env_file.rb index 36c251be5..2bad30f1e 100644 --- a/lib/kamal/env_file.rb +++ b/lib/kamal/env_file.rb @@ -23,22 +23,13 @@ def to_io private def docker_env_file_line(key, value) - "#{key}=#{escape_docker_env_file_value(value)}\n" - end + value = value.to_s - # Escape a value to make it safe to dump in a docker file. - def escape_docker_env_file_value(value) - # keep non-ascii(UTF-8) characters as it is - value.to_s.scan(/[\x00-\x7F]+|[^\x00-\x7F]+/).map do |part| - part.ascii_only? ? escape_docker_env_file_ascii_value(part) : part - end.join - end + # Docker env files don't support escape sequences, so newlines and null + # bytes cannot be represented. Raise an error rather than silently corrupt. + raise ArgumentError, "Env file values cannot contain newlines" if value.include?("\n") + raise ArgumentError, "Env file values cannot contain null bytes" if value.include?("\0") - def escape_docker_env_file_ascii_value(value) - # Doublequotes are treated literally in docker env files - # so remove leading and trailing ones and unescape any others - value.to_s.dump[1..-2] - .gsub(/\\"/, "\"") - .gsub(/\\#/, "#") + "#{key}=#{value}\n" end end diff --git a/test/env_file_test.rb b/test/env_file_test.rb index 34d31ad69..19380f898 100644 --- a/test/env_file_test.rb +++ b/test/env_file_test.rb @@ -57,21 +57,21 @@ class EnvFileTest < ActiveSupport::TestCase "foo" => "hello\\nthere" } - assert_equal "foo=hello\\\\nthere\n", \ + # Literal backslash-n should be preserved, not double-escaped + assert_equal "foo=hello\\nthere\n", \ Kamal::EnvFile.new(env).to_s ensure ENV.delete "PASSWORD" end - test "to_s newline" do + test "to_s newline raises" do env = { "foo" => "hello\nthere" } - assert_equal "foo=hello\\nthere\n", \ + assert_raises ArgumentError do Kamal::EnvFile.new(env).to_s - ensure - ENV.delete "PASSWORD" + end end test "stringIO conversion" do