Skip to content

Sync Windows hotfix to release/bi-1.8.x#1561

Closed
kanushka wants to merge 14 commits intorelease/bi-1.8.xfrom
ballerina-5.8.1
Closed

Sync Windows hotfix to release/bi-1.8.x#1561
kanushka wants to merge 14 commits intorelease/bi-1.8.xfrom
ballerina-5.8.1

Conversation

@kanushka
Copy link
Contributor

@kanushka kanushka commented Feb 25, 2026

Purpose

Update the release/bi-1.8.x branch with the Windows activation hotfix.

Changes

  • Fixes BI extension activation issues specific to Windows environments.
  • Maintains stability for the 1.8.x release cycle.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed Ballerina distribution detection on Windows systems.
    • Improved Windows environment PATH visibility for shell operations.
  • Chores

    • Released Ballerina Extension version 5.8.1.
    • Updated fast-xml-parser dependency to 5.3.7 across packages.
    • Added security vulnerability entries to ignore list.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 4 committers have signed the CLA.

✅ kanushka
✅ gigara
✅ axewilledge
❌ choreo-cicd
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

This pull request addresses dependency version updates, CVE vulnerability tracking, and enhances Windows environment detection in the Ballerina extension. Fast-xml-parser is bumped to 5.3.7 across multiple package manifests, three CVEs are added to the ignore list, and the Ballerina extension is updated to v5.8.1 with improved Windows installation discovery and PATH environment handling.

Changes

Cohort / File(s) Summary
CVE Vulnerability Management
.trivyignore
Added three CVE entries (CVE-2025-14505, CVE-2025-69873, CVE-2026-26996) with explanatory comments for vulnerability exceptions.
Dependency Version Upgrades
common/autoinstallers/rush-plugins/package.json, common/config/rush/.pnpmfile.cjs, package.json, workspaces/mi/mi-extension/package.json, workspaces/mi/mi-visualizer/package.json
Unified fast-xml-parser dependency upgrades from 5.3.4 to 5.3.7 across multiple manifests; .pnpmfile.cjs also locks bn.js to 5.2.3 when present.
Ballerina Extension Release v5.8.1
workspaces/ballerina/ballerina-extension/package.json, workspaces/ballerina/ballerina-extension/CHANGELOG.md
Version bump and changelog entry documenting improved Windows environment detection in Ballerina distribution discovery.
Windows Ballerina Path Detection
workspaces/ballerina/ballerina-extension/src/core/extension.ts
Introduces findWindowsBallerinaPath() function to locate Ballerina installations on Windows by scanning registry PATH entries and common installation directories; enhances getShellEnvironment() to merge machine and user PATHs from registry; updates version detection flow to leverage Windows fallback mechanism when ballerinaHome is unavailable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A swift Windows hop through registry and paths so deep,
Faster XML parsers help dependencies to keep,
Ballerina's v5.8.1 springs forth with grace,
As CVEs are noted and versions find their place! 🌿✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers Purpose and Changes sections, but omits most template sections including Goals, Approach, Testing, Security checks, and Documentation, which are relevant for a release branch fix. Expand the description to include Goals explaining how the Windows hotfix resolves activation issues, Approach detailing the implementation, Test environment, Security checks, and Documentation impact.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically identifies the main purpose: syncing a Windows hotfix to a release branch, matching the PR's primary objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ballerina-5.8.1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
common/config/rush/.pnpmfile.cjs (1)

79-89: Consider consolidating duplicated override assignments into a shared helper map.

This update is correct, but the same override edits are repeated in both branches, which increases drift risk over time.

♻️ Suggested refactor
+const FORCE_VERSIONS = {
+  'fast-xml-parser': '5.3.7',
+  'bn.js': '5.2.3'
+};
+
+function applyOverrides(depSet) {
+  if (!depSet) return;
+  for (const [name, version] of Object.entries(FORCE_VERSIONS)) {
+    if (depSet[name]) depSet[name] = version;
+  }
+}
+
 module.exports = {
   hooks: {
     readPackage(pkg, context) {
-      if (pkg.dependencies) {
-        ...
-        if (pkg.dependencies['fast-xml-parser']) {
-          pkg.dependencies['fast-xml-parser'] = '5.3.7';
-        }
-        if (pkg.dependencies['bn.js']) {
-          pkg.dependencies['bn.js'] = '5.2.3';
-        }
-      }
+      applyOverrides(pkg.dependencies);

-      if (pkg.devDependencies) {
-        ...
-        if (pkg.devDependencies['fast-xml-parser']) {
-          pkg.devDependencies['fast-xml-parser'] = '5.3.7';
-        }
-        if (pkg.devDependencies['bn.js']) {
-          pkg.devDependencies['bn.js'] = '5.2.3';
-        }
-      }
+      applyOverrides(pkg.devDependencies);

Also applies to: 146-156

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common/config/rush/.pnpmfile.cjs` around lines 79 - 89, The duplicate
dependency override assignments for pkg.dependencies keys ('fast-xml-parser',
'hono', 'lodash', 'bn.js') are repeated in multiple branches; extract a single
helper map (e.g., const dependencyOverrides = { 'fast-xml-parser': '5.3.7',
'hono': '^4.11.7', 'lodash': '4.17.23', 'bn.js': '5.2.3' }) and replace the
repeated blocks in the .pnpmfile.cjs logic (the sections that currently check
pkg.dependencies[...] and assign values, including the other duplicate at lines
~146-156) with a small loop or function that iterates dependencyOverrides and
applies pkg.dependencies[key] = value when present. Ensure you reference and
reuse this helper in both branches instead of duplicating assignments.
workspaces/ballerina/ballerina-extension/src/core/extension.ts (1)

2694-2769: findWindowsBallerinaPath — Strategy 2 iterates files unnecessarily

Minor observation: fs.readdirSync(root) (Line 2753) returns both files and directories. For each child (including .exe, .txt, licence files, etc. that may live at the Ballerina install root), the code constructs path.join(root, child, 'bin') and calls fs.existsSync. Adding an isDirectory guard avoids needless probes:

♻️ Suggested refinement
             const children = fs.readdirSync(root);
             for (const child of children) {
+                const childPath = path.join(root, child);
+                try {
+                    if (!fs.statSync(childPath).isDirectory()) { continue; }
+                } catch { continue; }
                 const versionedBin = path.join(root, child, 'bin');
                 if (fs.existsSync(path.join(versionedBin, 'bal.bat'))) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts` around lines
2694 - 2769, The loop in findWindowsBallerinaPath currently calls
fs.readdirSync(root) and treats every child as if it were a directory, causing
unnecessary fs.existsSync probes for files; change the inner loop to skip
non-directories by checking each child with fs.statSync or
fs.lstatSync(rootChild).isDirectory() (wrap the stat call in try/catch to skip
unreadable entries) before constructing versionedBin and testing for bal.bat, so
only real subdirectories are probed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.trivyignore:
- Around line 8-15: Update the three new CVE entries in .trivyignore
(CVE-2025-14505, CVE-2025-69873, CVE-2026-26996) to include a GitHub issue
tracking link like the existing CVE-2020-36851 entry; create or reference an
appropriate repo issue for each CVE and append the issue URL to each CVE comment
so every ignored CVE has a traceable GitHub issue for governance and periodic
re-evaluation.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts`:
- Around line 2721-2727: findWindowsBallerinaPath currently uses synchronous
fs.existsSync(path.join(entry, 'bal.bat')) for every PATH entry (called
synchronously from getBallerinaVersion), which can block the extension host on
slow or network-mounted PATH entries; update the function to avoid synchronous
blocking by either (a) pre-filtering entries to skip UNC/network paths (entries
starting with '\\\\') and first guard-checking that the entry is a local
directory via a cheap sync test like fs.statSync(entry).isDirectory() before
probing for bal.bat, or (b) convert the search to an asynchronous implementation
using fs.promises.stat/access and make getBallerinaVersion await the async probe
(or run it on a worker), and add a brief comment documenting the performance
expectation; reference function names findWindowsBallerinaPath,
getBallerinaVersion, and the use of fs.existsSync/path.join when making changes.
- Around line 2785-2792: The PowerShell snippet assigned to the variable
"command" currently replaces the process-level Path with only Machine+User
registry values, dropping VS Code-injected entries; update that snippet to
preserve the current process PATH by capturing it (e.g.,
$p=[Environment]::GetEnvironmentVariable('Path','Process') or using $e['Path'])
and append it when building $e['Path'] (set $e['Path']=$mp+';'+$up+';'+$p while
handling empty mp/up/p cases) so when updateProcessEnv writes process.env.Path
the VS Code entries remain and registry paths are prepended.

---

Nitpick comments:
In `@common/config/rush/.pnpmfile.cjs`:
- Around line 79-89: The duplicate dependency override assignments for
pkg.dependencies keys ('fast-xml-parser', 'hono', 'lodash', 'bn.js') are
repeated in multiple branches; extract a single helper map (e.g., const
dependencyOverrides = { 'fast-xml-parser': '5.3.7', 'hono': '^4.11.7', 'lodash':
'4.17.23', 'bn.js': '5.2.3' }) and replace the repeated blocks in the
.pnpmfile.cjs logic (the sections that currently check pkg.dependencies[...] and
assign values, including the other duplicate at lines ~146-156) with a small
loop or function that iterates dependencyOverrides and applies
pkg.dependencies[key] = value when present. Ensure you reference and reuse this
helper in both branches instead of duplicating assignments.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts`:
- Around line 2694-2769: The loop in findWindowsBallerinaPath currently calls
fs.readdirSync(root) and treats every child as if it were a directory, causing
unnecessary fs.existsSync probes for files; change the inner loop to skip
non-directories by checking each child with fs.statSync or
fs.lstatSync(rootChild).isDirectory() (wrap the stat call in try/catch to skip
unreadable entries) before constructing versionedBin and testing for bal.bat, so
only real subdirectories are probed.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8453f6 and c623472.

⛔ Files ignored due to path filters (2)
  • common/autoinstallers/rush-plugins/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • common/config/rush/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .trivyignore
  • common/autoinstallers/rush-plugins/package.json
  • common/config/rush/.pnpmfile.cjs
  • package.json
  • workspaces/ballerina/ballerina-extension/CHANGELOG.md
  • workspaces/ballerina/ballerina-extension/package.json
  • workspaces/ballerina/ballerina-extension/src/core/extension.ts
  • workspaces/mi/mi-extension/package.json
  • workspaces/mi/mi-visualizer/package.json

Comment on lines +8 to +15
# No fix released by the author
CVE-2025-14505

# Library is used in nested dependencies and not directly used by our codebase. No fix released by the author.
CVE-2025-69873

# used in nested dependencies and not directly used by our codebase. No fix released by the author.
CVE-2026-26996
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .trivyignore

Repository: wso2/vscode-extensions

Length of output: 656


🏁 Script executed:

rg -i 'github\.com.*issue|tracking|reviewer|date|expires' .trivyignore

Repository: wso2/vscode-extensions

Length of output: 120


🏁 Script executed:

# Search the entire codebase for these CVE IDs to see if there are tracking references elsewhere
rg 'CVE-2025-14505|CVE-2025-69873|CVE-2026-26996' --type markdown --type yaml --type json

Repository: wso2/vscode-extensions

Length of output: 48


Add GitHub issue links to each newly ignored CVE.

The existing suppression (CVE-2020-36851, line 5–6) includes a tracking link (https://github.com/wso2/vscode-extensions/issues/550). The three new CVE entries (CVE-2025-14505, CVE-2025-69873, CVE-2026-26996) lack issue references, making them permanent suppressions without traceability or expiry. Follow the established pattern and include a GitHub issue link for each new entry to maintain governance and enable periodic re-evaluation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.trivyignore around lines 8 - 15, Update the three new CVE entries in
.trivyignore (CVE-2025-14505, CVE-2025-69873, CVE-2026-26996) to include a
GitHub issue tracking link like the existing CVE-2020-36851 entry; create or
reference an appropriate repo issue for each CVE and append the issue URL to
each CVE comment so every ignored CVE has a traceable GitHub issue for
governance and periodic re-evaluation.

Comment on lines +2721 to +2727
for (const entry of pathEntries) {
const candidate = path.join(entry, 'bal.bat');
if (fs.existsSync(candidate)) {
debug(`[WIN_BAL_FIND] Found bal.bat in registry PATH entry: ${entry}`);
return entry + path.sep;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Synchronous fs.existsSync across all PATH entries may stall the extension host

Strategy 1 calls fs.existsSync(path.join(entry, 'bal.bat')) synchronously for every entry in the combined Machine+User PATH. On typical Windows developer machines this can be 80–200+ entries; many corporate environments add UNC (\\server\share\...) or mapped-drive entries that incur network round-trips for each stat call. Since findWindowsBallerinaPath runs on the extension host thread (called synchronously from the else if branch in getBallerinaVersion), a single slow network PATH entry can block activation for several seconds per probe.

Consider failing fast by only probing entries that are local (e.g., skip entries starting with \\ or that don't fs.existsSync as a directory first with a short guard), or move the search to an async worker. At minimum, document the performance expectation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts` around lines
2721 - 2727, findWindowsBallerinaPath currently uses synchronous
fs.existsSync(path.join(entry, 'bal.bat')) for every PATH entry (called
synchronously from getBallerinaVersion), which can block the extension host on
slow or network-mounted PATH entries; update the function to avoid synchronous
blocking by either (a) pre-filtering entries to skip UNC/network paths (entries
starting with '\\\\') and first guard-checking that the entry is a local
directory via a cheap sync test like fs.statSync(entry).isDirectory() before
probing for bal.bat, or (b) convert the search to an asynchronous implementation
using fs.promises.stat/access and make getBallerinaVersion await the async probe
(or run it on a worker), and add a brief comment documenting the performance
expectation; reference function names findWindowsBallerinaPath,
getBallerinaVersion, and the use of fs.existsSync/path.join when making changes.

Comment on lines +2785 to +2792
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
'elseif($mp){$e[\'Path\']=$mp}' +
'elseif($up){$e[\'Path\']=$up};' +
'$e | ConvertTo-Json"';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Windows PATH merge drops VS Code's process-level PATH entries

$e=[Environment]::GetEnvironmentVariables('Process') captures the full live process PATH (including entries VS Code injects at startup — its bundled Node.js, extension host paths, etc.), but the very next assignment $e['Path'] = $mp+';'+$up replaces it entirely with only the registry Machine+User values. After updateProcessEnv writes this back via process.env.Path = newEnv.Path (Line 2656), all subsequent exec calls that rely on those process-level injected entries can fail — not just Ballerina's. The comment says "VS Code-internal variables are preserved" but that applies only to non-Path keys.

To preserve the process-level entries, append the current process PATH instead of discarding it:

🔧 Proposed fix — include process PATH in the merge
-            command = 'powershell.exe -NoProfile -Command "' +
-                '$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
-                '$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
-                '$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
-                'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
-                'elseif($mp){$e[\'Path\']=$mp}' +
-                'elseif($up){$e[\'Path\']=$up};' +
-                '$e | ConvertTo-Json"';
+            command = 'powershell.exe -NoProfile -Command "' +
+                '$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
+                '$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
+                '$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
+                '$pp=$e[\'Path\'];' +
+                '$merged=@($mp,$up,$pp | Where-Object{$_}) -join \';\';' +
+                '$e[\'Path\']=$merged;' +
+                '$e | ConvertTo-Json"';

This ensures the registry paths (where a fresh Ballerina install writes) are prepended so that bal.bat is found first, while VS Code's own process entries are still present for everything else.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
'elseif($mp){$e[\'Path\']=$mp}' +
'elseif($up){$e[\'Path\']=$up};' +
'$e | ConvertTo-Json"';
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'$pp=$e[\'Path\'];' +
'$merged=@($mp,$up,$pp | Where-Object{$_}) -join \';\';' +
'$e[\'Path\']=$merged;' +
'$e | ConvertTo-Json"';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts` around lines
2785 - 2792, The PowerShell snippet assigned to the variable "command" currently
replaces the process-level Path with only Machine+User registry values, dropping
VS Code-injected entries; update that snippet to preserve the current process
PATH by capturing it (e.g.,
$p=[Environment]::GetEnvironmentVariable('Path','Process') or using $e['Path'])
and append it when building $e['Path'] (set $e['Path']=$mp+';'+$up+';'+$p while
handling empty mp/up/p cases) so when updateProcessEnv writes process.env.Path
the VS Code entries remain and registry paths are prepended.

@kanushka
Copy link
Contributor Author

Duplicate of #1568

@kanushka kanushka marked this as a duplicate of #1568 Feb 25, 2026
@kanushka kanushka closed this Feb 25, 2026
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.

5 participants