Skip to content

devcontainer-lock.json includes features from user-level "Default Features" setting, leaking personal config into projects #11616

@gakugaku

Description

@gakugaku
  • VSCode Version: 1.118.1 (user setup), commit 034f571df509819cc10b0c8129f66ef77a542f0e
  • Local OS Version: Windows 11
  • Remote OS Version: Ubuntu 24.04.3 LTS
  • Remote Extension/Connection Type: Dev Containers
  • Logs:

Steps to Reproduce:

  1. In VS Code user settings, configure dev.containers.defaultFeatures with one or more features that you intentionally do NOT want declared in the project's devcontainer.json (the entire purpose of this user-level setting):
    "dev.containers.defaultFeatures": {
      "ghcr.io/example/feature-a:latest": {},
      "ghcr.io/example/feature-b:latest": {}
    }
  2. Open a project whose .devcontainer/devcontainer.json does NOT declare those features.
  3. Build/rebuild the dev container (lockfile generation is on by default since 1.118: https://code.visualstudio.com/updates/v1_118#_dev-container-lockfile-for-features-enabled-by-default ).
  4. Inspect .devcontainer/devcontainer-lock.json.

Expected:

per the devcontainer-lockfile spec, the lockfile records "each feature listed in the devcontainer.json". User-level Default Features are not part of the project manifest and should not appear in the project's lockfile.

Actual:

devcontainer-lock.json contains entries for the user-level Default Features alongside the features declared in devcontainer.json. Example excerpt (only node:2.0.0 is declared in devcontainer.json; the rest come from the user setting):

{
  "features": {
    "ghcr.io/devcontainers/features/node:2.0.0": { "version": "2.0.0", "resolved": "...", "integrity": "..." },
    "ghcr.io/example/feature-a:latest":          { "version": "1.0.0", "resolved": "...", "integrity": "..." },
    "ghcr.io/example/feature-b:latest":          { "version": "1.0.1", "resolved": "...", "integrity": "..." }
  }
}

Impact:

the whole reason to put a feature in dev.containers.defaultFeatures (instead of devcontainer.json) is that it is personal: the user wants it in their own dev containers without committing it to the repo. With lockfile generation default-enabled in 1.118+, those personal features now appear in devcontainer-lock.json, which is a project-level file expected to be committed (it lives next to devcontainer.json and exists for build reproducibility). This silently leaks personal tooling choices into PRs and breaks the user-vs-project separation that the Default Features setting was designed to provide.

Suggested fix:

scope the lockfile strictly to features declared in devcontainer.json (matching the spec). Features merged from dev.containers.defaultFeatures or other user-level sources should still be installed but excluded from devcontainer-lock.json.

Workarounds considered:

  • Disable lockfile generation per-project: no documented project-level opt-out as of writing.
  • Add .devcontainer/devcontainer-lock.json to .gitignore: loses the supply-chain pinning benefit for legitimately-declared features too.
  • Move Default Features out of user settings into devcontainer.json: defeats the purpose of the setting.

None are satisfactory.

References:

Does this issue occur when you try this locally?: N/A (Dev Containers-only behavior)
Does this issue occur when you try this locally and all extensions are disabled?: N/A

Metadata

Metadata

Assignees

Labels

bugIssue identified by VS Code Team member as probable bugcontainersIssue in vscode-remote containers

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions