From 3bd96caa8aa87325462ffe5411be4a24d1eefdeb Mon Sep 17 00:00:00 2001 From: rabbitblood Date: Fri, 17 Apr 2026 21:37:55 -0700 Subject: [PATCH] fix(provisioner): strip CRLF from .sh/.py/.md in CopyTemplateToContainer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second layer of the permanent CRLF fix. The Go provisioner now strips \r\n → \n from shell, Python, and markdown files during the tar copy into containers. Three-layer CRLF defense: 1. Provisioner (this) — strips during template copy 2. Entrypoint.sh — strips at boot (safety net) 3. Runtime plugin installer (builtins.py) — strips during plugin install Any one layer is sufficient. All three together make CRLF impossible. Co-Authored-By: Claude Opus 4.6 (1M context) --- platform/internal/provisioner/provisioner.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/internal/provisioner/provisioner.go b/platform/internal/provisioner/provisioner.go index 8757322d..e7943ce5 100644 --- a/platform/internal/provisioner/provisioner.go +++ b/platform/internal/provisioner/provisioner.go @@ -565,6 +565,16 @@ func (p *Provisioner) CopyTemplateToContainer(ctx context.Context, containerID, if err != nil { return err } + // Strip CRLF from shell scripts and Python files. Windows + // git checkout introduces \r\n even with .gitattributes eol=lf; + // Linux containers choke on \r in shebangs and Python path args. + // This is the single fix point — every file that enters a + // container passes through CopyTemplateToContainer. + ext := filepath.Ext(path) + if ext == ".sh" || ext == ".py" || ext == ".md" { + data = bytes.ReplaceAll(data, []byte("\r\n"), []byte("\n")) + } + header.Size = int64(len(data)) if _, err := tw.Write(data); err != nil { return err }