Incorrect Dynamic Property Access in Package Data Resolver

Open Beginner friendly
#10,724 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript

Research direction

The issue is in scopes/dependencies/dependencies/resolve-pkg-data.ts lines 66-74. Look at the enrichDataFromDependent function. The fix is to change .packageName to [packageName] in three places. Run the existing tests in resolve-pkg-data.spec.ts to verify the change works. The test case described can be added to ensure the versionUsedByDependent is correctly populated from dependencies, devDependencies, or peerDependencies.

Written by the indexing model from the issue text.

Description

type/bug

Issue : Incorrect Dynamic Property Access in Package Data Resolver

Metadata
  • Subsystem: scopes/dependencies/dependencies
  • Source File: scopes/dependencies/dependencies/resolve-pkg-data.ts
  • Line Numbers: 66–74
  • Severity: High
  • Keywords: dependency-resolution, package.json, version-ranges, property-access
Problem Description

In scopes/dependencies/dependencies/resolve-pkg-data.ts, the function enrichDataFromDependent() resolves package information from a dependent component's package.json. It attempts to look up the package version or semver range defined in dependencies, devDependencies, or peerDependencies.

Instead of utilizing computed property bracket notation ([packageName]), the code uses dot notation with the literal identifier (.packageName).

Vulnerable Code
// scopes/dependencies/dependencies/resolve-pkg-data.ts: Lines 65-75

  const packageName = resolvePackageNameByPath(packageRelativePath);
  const packageVersion =
    dependentPackageJson.dependencies?.packageName ||
    dependentPackageJson.devDependencies?.packageName ||
    dependentPackageJson.peerDependencies?.packageName;
  if (packageVersion) {
    packageData.dependentPackageJsonPath = packageJsonInfo.path;
    packageData.name = packageName;
    packageData.versionUsedByDependent = packageVersion;
  }
Root Cause Analysis
  1. packageName is a variable holding the resolved package string (e.g. 'lodash', 'chalk', or '@teambit/base-ui').
  2. dependentPackageJson.dependencies?.packageName checks for the literal key "packageName" inside the dependencies map:
    {
      "dependencies": {
        "packageName": "1.0.0"
      }
    }
    
  3. Unless a project literally depends on a package titled "packageName", packageVersion strictly evaluates to undefined.
  4. As a result, the condition if (packageVersion) at line 70 is never entered for any standard package.
Real-World Impact

According to the file's architectural documentation (lines 20–29):

"for a package that is not bit-component, we're interested in the range because that's how it was set in the first place and changing it to an exact version result in the component modified."

Because versionUsedByDependent is never populated from dependentPackageJson, Bit loses the author's specified semver range (e.g., ^1.2.0 or ~2.0.0). Bit falls back to reading concreteVersion from the package's internal package.json in node_modules (e.g., 1.2.4). This can lead to:

  • Bit marking components as modified unexpectedly due to forced exact version pinning.
  • Inability to retain and propagate semver ranges when snapping or tagging components.
Proposed Fix

Replace static dot notation .packageName with dynamic bracket notation [packageName]:

--- a/scopes/dependencies/dependencies/resolve-pkg-data.ts
+++ b/scopes/dependencies/dependencies/resolve-pkg-data.ts
@@ -64,9 +64,9 @@ function enrichDataFromDependent(packageData: ResolvedPackageData, dependentDir:
 
   const packageName = resolvePackageNameByPath(packageRelativePath);
   const packageVersion =
-    dependentPackageJson.dependencies?.packageName ||
-    dependentPackageJson.devDependencies?.packageName ||
-    dependentPackageJson.peerDependencies?.packageName;
+    dependentPackageJson.dependencies?.[packageName] ||
+    dependentPackageJson.devDependencies?.[packageName] ||
+    dependentPackageJson.peerDependencies?.[packageName];
   if (packageVersion) {
     packageData.dependentPackageJsonPath = packageJsonInfo.path;
     packageData.name = packageName;
Verification & Unit Test

Add a test in resolve-pkg-data.spec.ts:

it('should populate versionUsedByDependent from dependent package.json dependencies', () => {
  const result = resolvePackageData(dependentFixtureDir, packageFullPath);
  expect(result).to.not.be.undefined;
  expect(result?.name).to.equal('lodash');
  expect(result?.versionUsedByDependent).to.equal('^4.17.21');
});

Dominant language
TypeScript
Stars
18.5k
Forks
962
Avg merge
1d 12h
Merged PRs (30d)
119

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from teambit/bit

All issues in teambit/bit

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.