diff --git a/.changeset/fix-from-copy-option-parsing.md b/.changeset/fix-from-copy-option-parsing.md new file mode 100644 index 0000000..a9b21ff --- /dev/null +++ b/.changeset/fix-from-copy-option-parsing.md @@ -0,0 +1,5 @@ +--- +"@docker-doctor/cli": patch +--- + +Fix `FROM` and `COPY`/`ADD` instruction parsing in rules to correctly skip option flags (e.g. `--platform`, `--chown`), preventing false-positive diagnostics or layer ordering check failures. diff --git a/packages/core/src/rules/image-size.ts b/packages/core/src/rules/image-size.ts index a502c8d..23e8d4a 100644 --- a/packages/core/src/rules/image-size.ts +++ b/packages/core/src/rules/image-size.ts @@ -16,8 +16,9 @@ export const preferSlimBase: DockerfileRule = { for (const inst of instructions) { if (inst.instruction === "FROM") { - const [imagePart] = inst.args.split(/\s+/u); - if (imagePart === "scratch") { + const parts = inst.args.split(/\s+/u); + const imagePart = parts.find((p) => !p.startsWith("--")); + if (!imagePart || imagePart === "scratch") { continue; } diff --git a/packages/core/src/rules/performance.ts b/packages/core/src/rules/performance.ts index 3b96d30..750ce18 100644 --- a/packages/core/src/rules/performance.ts +++ b/packages/core/src/rules/performance.ts @@ -57,8 +57,11 @@ export const orderLayers: DockerfileRule = { for (const inst of instructions) { if (inst.instruction === "COPY" || inst.instruction === "ADD") { const parts = inst.args.split(/\s+/u); - // If copying the current directory (e.g., COPY . .) - const [src] = parts; + const src = parts.find((p) => !p.startsWith("--")); + + if (!src) { + continue; + } if ( (src === "." || src === "./" || src === "*" || src.includes("src")) && diff --git a/packages/core/src/rules/security.ts b/packages/core/src/rules/security.ts index 7ba1ef3..4e93163 100644 --- a/packages/core/src/rules/security.ts +++ b/packages/core/src/rules/security.ts @@ -113,9 +113,9 @@ export const pinImageVersion: DockerfileRule = { // FROM image or FROM image:tag or FROM image@sha256:hash // Also respect multi-stage builds (AS stageName) const parts = inst.args.split(/\s+/u); - const [imagePart] = parts; + const imagePart = parts.find((p) => !p.startsWith("--")); - if (imagePart === "scratch") { + if (!imagePart || imagePart === "scratch") { continue; }