Skip to content

fix(docker): skip FROM references to earlier build stages - #602

Open
vibgrate-team wants to merge 1 commit into
mainfrom
cursor/dockerfile-stage-from-4501
Open

vibgrate-team wants to merge 1 commit into
mainfrom
cursor/dockerfile-stage-from-4501

Conversation

@vibgrate-team

@vibgrate-team vibgrate-team commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

parseDockerfile treated every FROM target as a registry image. In a multi-stage Dockerfile the later stages usually start from an earlier stage name:

FROM node:20 AS build
RUN npm ci && npm run build

FROM build AS test
RUN npm test

build was recorded as library/build. vg scan then looked that name up on Docker Hub and reported unknown drift, or drift against an unrelated public image of the same name.

While walking the file, the parser now records stage names declared with AS (the keyword is case-insensitive) and skips a FROM whose target is a stage already declared. Comparison of the target to those names is case-insensitive, matching Docker. A name is recorded only after that FROM is classified, so an image that merely shares a name with a stage declared later is still a row. Row naming is unchanged: a Docker Hub image with no namespace stays library/<image>, and the tag stays the version (latest when the reference has none).

FROM node:20 AS build / FROM build AS test now yields one row, library/node at 20. FROM build followed by FROM node:20 AS build still yields library/build and library/node.

Related issues

Closes #588

Checklist

  • pnpm test passes
  • pnpm lint is clean
  • pnpm typecheck is clean
  • Docs updated (README / DOCS / ARCHITECTURE) where behavior changed
  • Determinism preserved — identical input still produces identical
    graph.json / report output (content-hashed IDs, stable sorts; no time,
    randomness, or filesystem-order dependence)
  • No proprietary or internal references — public, Apache-2.0 content only
  • Commits use Conventional Commits and are signed off (git commit -s, DCO)

Notes for reviewers

Table-driven tests cover uppercase AS, lowercase as, and an untagged image whose name is reused by a later stage. scratch is still skipped. The FROM instruction match itself is unchanged (still uppercase, still anchored at the start of the line), so this does not overlap the lowercase/indented from work in #576 beyond the same regex.

No doc edit: the existing DOCS examples are single-stage FROM lines, and they already describe real images rather than stage names. pnpm lint exits 0; the five warnings it prints are existing and outside this change.

Open in Web Open in Cursor 

A multi-stage Dockerfile's `FROM <stage>` was recorded as a Docker Hub
image (for example `library/build`). parseDockerfile now remembers stage
names declared with AS, case-insensitively, and skips a FROM whose target
is a stage already declared. An image that only matches a stage declared
later is still recorded, and row names stay `library/<image>`.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: vibgrate-team <vibgrate-team@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: FROM <earlier-stage> in a multi-stage Dockerfile is reported as a Docker Hub image

2 participants