fix(misconf): wrap legacy ENV values in quotes to preserve spaces (#9497)

Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
This commit is contained in:
Nikita Pivkin
2025-09-22 17:58:47 +06:00
committed by GitHub
parent 842ebdcb4a
commit 267a9700fa
2 changed files with 31 additions and 2 deletions

View File

@@ -103,8 +103,10 @@ func imageConfigToDockerfile(cfg *v1.ConfigFile) []byte {
case strings.HasPrefix(h.CreatedBy, "HEALTHCHECK"):
// HEALTHCHECK instruction
createdBy = buildHealthcheckInstruction(cfg.Config.Healthcheck)
case strings.HasPrefix(h.CreatedBy, "ENV"):
createdBy = restoreEnvLine(h.CreatedBy)
default:
for _, prefix := range []string{"ARG", "ENV", "ENTRYPOINT"} {
for _, prefix := range []string{"ARG", "ENTRYPOINT"} {
if strings.HasPrefix(h.CreatedBy, prefix) {
createdBy = h.CreatedBy
break
@@ -169,6 +171,22 @@ func normalizeCopyCreatedBy(input string) string {
return copyInRe.ReplaceAllString(input, `$1 `)
}
// restoreEnvLine normalizes a Dockerfile ENV instruction from image history.
//
// Legacy Dockerfiles may use ENV in the form: "ENV key val1 val2".
// Docker stores this in image history as: "ENV key=val1 val2".
// This can cause parsing errors, because extra tokens are treated as separate keys.
// restoreEnvLine converts such lines into a valid `ENV <key>="<value>"` format
// and wraps the value in quotes to preserve internal spaces and tabs.
// e.g. `ENV tags=latest v0.0.0` -> `ENV key="latest v0.0.0"`
func restoreEnvLine(createdBy string) string {
k, v, ok := strings.Cut(createdBy, "=")
if !ok {
return createdBy
}
return fmt.Sprintf("%s=%q", k, v)
}
func (a *historyAnalyzer) Required(_ types.OS) bool {
return true
}

View File

@@ -430,7 +430,7 @@ func Test_ImageConfigToDockerfile(t *testing.T) {
},
},
expected: `ARG TAG=latest
ENV TAG=latest
ENV TAG="latest"
ENTRYPOINT ["/bin/sh" "-c" "echo test"]
`,
},
@@ -458,6 +458,17 @@ HEALTHCHECK NONE
ENTRYPOINT ["/bin/sh"]
`,
},
{
name: "legacy env format",
input: &v1.ConfigFile{
History: []v1.History{
{
CreatedBy: "ENV TEST=foo bar",
},
},
},
expected: "ENV TEST=\"foo bar\"\n",
},
}
for _, tt := range tests {