Skip to content

PTAAA-881: remove extension-based self-healing and the ai-sdk-node dependency (v8) - #322

Merged
hamza-browserstack merged 5 commits into
v8from
PTAAA-881-remove-ai-extension-healing-v8
Nov 3, 2026
Merged

hamza-browserstack merged 5 commits into
v8from
PTAAA-881-remove-ai-extension-healing-v8

Conversation

@Hitesh-IDK

@Hitesh-IDK Hitesh-IDK commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

What is this about?

v8 port of #315, which landed the same removal on main (wdio v9). This is a security fix, so it has to ship in every supported major — v8 carries the identical vulnerable path, pinned to @browserstack/ai-sdk-node@1.5.17.

BrowserstackHealing.init() downloaded the AI browser extension and loaded it into the local browser — via goog:chromeOptions.extensions (Chrome/Edge) or browser.installAddOn() (Firefox). That extension ships a window.postMessage handler that accepts a page-controlled endpoint and bearer token and forwards them to a privileged background fetch, giving any page a test visits an SSRF / CORS-bypass primitive against the machine running the test (localhost, private network). Reported via HackerOne; the path is deprecated, so it is removed rather than hardened.

This path only ever ran for sessions not on BrowserStack infra (gated on !shouldAddServiceVersion(...)).

Self-healing on BrowserStack infra is unaffected. That is driven by the browserstack.selfHeal capability, resolved hub-side, and never went through this code. BrowserstackConfig.selfHeal is deliberately kept so existing capability configs keep type-checking.

Removed:

  • AiHandler (src/ai-handler.ts) and its two entry points in launcher.ts / service.ts
  • the healing branch of the funnel instrumentation (handleHealingInstrumentation + its file-local helpers)
  • isValidCapsForHealing / hasBrowserName / getBrowserStackUserAndKey in util.ts — no callers left after the above
  • TCG_URL, TCG_INFO, SUPPORTED_BROWSERS_FOR_AI, BSTACK_TCG_AUTH_RESULT in constants.ts
  • SDK_AI_SELF_HEAL_STEP / SDK_AI_SELF_HEAL_GET_RESULT and the AI_EVENTS map
  • the @browserstack/ai-sdk-node dependency (and axios, which it was the only source of)

~1,607 deletions. The only addition is a one-time warning when selfHeal: true is set on an off-infra session, so the behaviour change is visible rather than silent.

This matches the final state of #315 after its review rounds — the orphan cleanups that took three follow-up commits there are folded in here.

Related Jira task/s

https://browserstack.atlassian.net/browse/PTAAA-881

Release (mandatory for every PR — required for the ready-for-review label)

Version bump: (required — tick exactly one)

  • minor (backwards-compatible feature)
  • patch (bug fix or other small change)

Release notes type: (optional)

  • New Feature
  • Bug Fix
  • Other Improvement

Release notes (customer-facing): (optional but encouraged)

  • Removed the deprecated client-side self-healing extension. Self-healing on BrowserStack continues to work unchanged via the browserstack.selfHeal capability.

Release notes (internal): (required — engineer-facing; what actually changed / why)

  • v8 port of PTAAA-881: remove extension-based self-healing and the ai-sdk-node dependency #315. Removed AiHandler and the extension-based healing path (PTAAA-881). The bundled extension exposed an unvalidated cross-origin postMessage handler that forwarded a page-controlled endpoint and bearer to a privileged fetch — a client-side SSRF reachable from any page a test visits. The path ran only off BrowserStack infra and is deprecated.
  • Dropped the @browserstack/ai-sdk-node dependency (and transitively axios). The pin was 1.5.17 while the SDK is at 1.8.x; logData/healFailure had already been removed upstream, so this code only resolved because of the stale pin.
  • Infra-side healing is untouched — it is capability-driven and resolved hub-side.

Checklist

  • Ready to review
  • Has it been tested locally?

Verification (measured on two clean worktrees — PR head 89892a3 vs its merge-base 722e27d, each with its own npm ci. The merge-base is the right baseline here: the branch sits behind v8 by release commit #327, so current v8 would fold unrelated drift into the comparison.)

  • Build / typecheck — npm run build (buf generate && tsc -p tsconfig.prod.json) exits 0 on both. tsc --noEmit under both tsconfig.json and tsconfig.prod.json: 0 errors → 0 errors. No typecheck change either way. (Note: both tsconfigs scope to src/**/*; tests are excluded from typechecking.)

  • Tests — npm test (scripts/test-isolated.mjs, which runs each file in its own vitest run): 1177 passing / 0 failing → 1137 passing / 0 failing, 47 → 46 files. Delta −40, reconciling exactly:

    • tests/ai-handler.test.ts deleted — −30
    • tests/instrumentation/funnelInstrumentation.test.ts trimmed 19 → 9 — −10

    Verified per-file across all 47: those two are the only files whose test count changed. No file fails to load on either revision.

PR Validations

Run Tests: Comment RUN_TESTS to trigger sanity tests.

🤖 Generated with Claude Code

…pendency

v8 port of #315, which landed the same removal on main (wdio v9). The
security fix has to ship in every supported major, and v8 carries the
identical vulnerable path pinned to @browserstack/ai-sdk-node 1.5.17.

The client-side healing path downloaded the AI browser extension via
BrowserstackHealing.init() and loaded it into the local browser, either
through goog:chromeOptions.extensions or browser.installAddOn(). That
extension ships a window.postMessage handler that forwards a
page-controlled endpoint and bearer to a privileged background fetch,
giving any visited page an SSRF primitive against the machine running
the test. The path is deprecated and only ever ran off BrowserStack
infra, so it is removed rather than hardened.

Removes AiHandler and its two entry points, the healing branch of the
funnel instrumentation, the capability helpers and constants left
without callers, the self-heal performance events, and the
@browserstack/ai-sdk-node dependency.

Self-healing on BrowserStack infra is unaffected: it is driven by the
browserstack.selfHeal capability, resolved hub-side, and never went
through this code. BrowserstackConfig.selfHeal is deliberately kept,
and an off-infra run that sets it now gets a one-time warning instead
of silently losing healing.

Typecheck 12 -> 9 errors (3 removed, 0 added; the rest pre-existing).
Tests 738 -> 728 passing with 0 failures either side; the 10-test drop
is the deleted healing suites.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Hitesh-IDK
Hitesh-IDK requested a review from a team as a code owner October 30, 2026 12:50
@Hitesh-IDK
Hitesh-IDK requested review from AakashHotchandani and rounak610 and removed request for a team October 30, 2026 12:50
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Central YAML (base), Organization UI (inherited), Workspace UI (inherited); Enforced overrides: Organization
  • Review profile: ASSERTIVE
  • Plan: Enterprise
  • Run ID: b642b461-8606-4920-a119-410e69dd1ca0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@shrish-browserstack shrish-browserstack left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lfg

@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@Hitesh-IDK

Copy link
Copy Markdown
Collaborator Author

🔴 Blocking findings — fix required

4 blocking issue(s) — all objectively grounded:

  1. src/instrumentation/funnelInstrumentation.ts — sendEvent map left as dead code after its only caller was removed (same pattern that already failed CI once in this file's history, per commit d4400f1).
  2. src/launcher.ts — new off-infra selfHeal warning misdiagnoses a reachable chromedriver-service case as "not on BrowserStack infrastructure."
  3. src/launcher.ts / src/service.ts — the new warning added in launcher.ts has no counterpart in service.ts's mirror branch for the same condition.
  4. tests/instrumentation/funnelInstrumentation.test.ts — expectedEventData fixture left dangling after its only consuming test block was removed (same file, same previously-hit pattern).

Full review: see the linked review.md.

Change map (generated deterministically from the diff)

graph LR
  subgraph nwdio_service["wdio-service"]
    npackages_browserstack_service_tests_ai_handler_test_ts["ai-handler.test.ts<br/>~750 lines"]
    npackages_browserstack_service_src_ai_handler_ts["ai-handler.ts<br/>~234 lines"]
    npackages_browserstack_service_src_instrumentation_funnelInstrumentation_ts["funnelInstrumentation.ts<br/>~181 lines"]
    npackages_browserstack_service_tests_instrumentation_funnelInstrumentation_test_ts["funnelInstrumentation.test.ts<br/>~181 lines"]
    npackages_browserstack_service_src_util_ts["util.ts<br/>~41 lines"]
    npackages_browserstack_service_src_launcher_ts["launcher.ts<br/>~27 lines"]
    npackages_browserstack_service_src_constants_ts["constants.ts<br/>~12 lines"]
    npackages_browserstack_service_src_service_ts["service.ts<br/>~12 lines"]
    npackages_browserstack_service_src_instrumentation_performance_constants_ts["constants.ts<br/>~10 lines"]
    n_changeset_pr_322_md["pr-322.md<br/>~5 lines"]
    npackages_browserstack_service_package_json["package.json<br/>~1 lines"]
  end
Loading

↻ This verdict comment is the review anchor — it's updated in place on each run (the gate posts its status separately).

— SDK PR Review Agent

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: failure).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

sendEvent was only read by the healing instrumentation helpers removed
with AiHandler, so it is dead once they go — the same no-unused-vars
failure this file hit on main.

The new selfHeal warning gated on !shouldAddServiceVersion(...), which
also returns false for a chromedriver service with observability left
on. A genuine BrowserStack session could therefore be told it was not
running on BrowserStack infrastructure. Gate on isBrowserstackInfra()
instead, which is the condition the message actually describes.
shouldAddServiceVersion stays for its four other callers.

Typecheck unchanged at 9 pre-existing errors; tests unchanged at 728
passing / 0 failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

…e.ts

Its only call site was the healing block removed in this PR; the call
went and the import stayed. Same no-unused-vars shape as the sendEvent
map. Swept the named imports of every file this PR touches — this was
the only one left dangling.

Typecheck unchanged at 9 pre-existing errors; tests unchanged at 728
passing / 0 failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@Hitesh-IDK

Copy link
Copy Markdown
Collaborator Author

✅ SDK PR Review — approve. No code changes required. Re-review of ca92a0c, which resolved three of the four findings from the 3d8ba8c round.

Verified clean

  • Dead/orphan sweep — all 13 removed symbols (AiHandler, isValidCapsForHealing, hasBrowserName, getBrowserStackUserAndKey, TCG_URL, TCG_INFO, SUPPORTED_BROWSERS_FOR_AI, BSTACK_TCG_AUTH_RESULT, AI_EVENTS, handleHealingInstrumentation, SDK_AI_SELF_HEAL_*, sendEvent) have zero remaining references. No dangling imports — ca92a0c swept the last one (shouldAddServiceVersion in service.ts).
  • No over-removal in funnelInstrumentation.ts — the riskiest edit. sendStart / sendFinish / buildEventData / getProductList intact; the healing branch was genuinely self-contained. Non-healing funnel events unaffected.
  • Import hygiene — shouldAddServiceVersion correctly dropped from service.ts (healing was its only consumer) and correctly retained in launcher.ts (still used elsewhere).
  • Dependency + lockfile — @browserstack/ai-sdk-node removed from the manifest; lockfile drops it, its nested uuid, and axios, with nothing re-introduced. (axios was never a direct dep — transitive only, so this is a lockfile-level effect.)
  • Changeset — .changeset/pr-322.md: package name matches, patch matches the ticked bump.
  • Warning path — one-time (onPrepare, once per launcher process), correctly gated, log-only so it cannot break user tests.

Port fidelity vs #315

Verified file-by-file against #315's final merged state (f708db1). The "three follow-up commits folded in" claim holds. handleProxyError / isProxyError appear in #315's removals but not here because those symbols don't exist on v8 — a branch difference, not a missed cleanup.

#322 is strictly better than #315 in one place. The warning gate here is isBrowserstackInfra(...); main still uses !shouldAddServiceVersion(...), which also returns false for a local-chromedriver-with-observability session. That means the merged #315 on main can emit "not running on BrowserStack infrastructure" for a session that is on infra. Worth a follow-up porting this fix back to main.

One correction to the PR description (non-blocking)

The verification section claims vitest went 738 → 728, a 10-test drop. The actual drop is 40: tests/ai-handler.test.ts contributes 30 deleted test cases (whole file) and the Healing instrumentation block contributes 10. Counted directly from the diff and independently reconciled against a clean-baseline run of 768. The body appears to have missed the whole-file deletion. Code is unaffected — only the description's number is wrong.

Considered and dismissed

An earlier pass flagged service.ts's before() as having lost its half of the off-infra warning. Not a defect: both deleted warnings were catch-block messages reporting extension setup failure, and that code path no longer exists. The new onPrepare warning already fires for every affected user, and before() is per-worker — a warning there would emit N duplicates for one session-level flag. One warning in the launcher is the correct design.

Security reasoning

Gating is sound — the removed path only ran off-infra, and infra healing is capability-driven (browserstack.selfHeal, hub-resolved) and never touched this code. Retaining BrowserstackConfig.selfHeal for type-compat is right, and the new warning makes the behaviour change visible rather than silent.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

Picks up the root-level mocha hook fix (#309). One conflict in
service.ts: its new _setCliSuiteFile(specs?.[0]) call sits directly
above the healing block this branch removes, so the delete read as
covering both. Kept the mocha call, dropped only the healing block.

Tests 731 passing / 0 failures, including all 12 of the new mocha-hook
tests; typecheck unchanged at 9 pre-existing errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

1 similar comment
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@Hitesh-IDK

Copy link
Copy Markdown
Collaborator Author

SDK PR Review Agent — verdict: ✅ success

Reviewed against #315 (the main original) and #325 (its follow-up), with a fresh clone and independent tsc / vitest runs on both the PR branch and its merge-base. No blocking findings.

Scope reviewed

Area Result
Removal completeness ✅ Repo-wide grep for AiHandler, ai-handler, ai-sdk-node, TCG_URL, TCG_INFO, SUPPORTED_BROWSERS_FOR_AI, BSTACK_TCG_AUTH_RESULT, AI_EVENTS, SDK_AI_SELF_HEAL_*, isValidCapsForHealing, hasBrowserName, getBrowserStackUserAndKey — zero hits outside the diff. No orphaned imports or dead exports.
axios removal ✅ No remaining direct importer; zero axios / ai-sdk-node entries in package-lock.json; no sibling workspace package depends on either; clean install from a fresh clone.
On-infra healing unaffected ✅ No on-infra path went through AiHandler or any removed symbol. BrowserstackConfig.selfHeal kept for capability type-compat, matching #315.
Funnel instrumentation ✅ Straight deletion of the healing branch only. No change to any non-healing function signature or event payload shape (fireFunnelTestEvent, sendStart/sendFinish, getReferrer untouched).
Tests ✅ Nothing surviving references a removed symbol; nothing .skip/.todo'd in place of deletion.
PR template hygiene ✅ Complete; exactly one version bump ticked. patch is appropriate — a dead-path and dependency removal, not a new capability.

Warning gate — reviewed, correct as written

launcher.ts gates the new off-infra selfHeal warning on !isBrowserstackInfra(...) rather than the !shouldAddServiceVersion(...) used by the code it replaced. This was examined closely and is the correct gate, not a porting slip:

shouldAddServiceVersion() returns false for two independent reasons — off BrowserStack infra, or the chromedriver service with testObservability left enabled. The second is a genuine BrowserStack session, so gating the message on it would tell that user their session "is not running on BrowserStack infrastructure" — wrong, and pointed at the wrong root cause. isBrowserstackInfra() is precisely the condition the message describes.

#325 ports this same correction back to main, so this branch is the more-correct one on that line.

Non-blocking notes

  1. No test covers the new warning. It is the only added logic in an otherwise pure-deletion PR. The gap is inherited from PTAAA-881: remove extension-based self-healing and the ai-sdk-node dependency #315 rather than introduced here, so it is not a merge blocker — but it is the one piece of behaviour with no coverage.
  2. Verification numbers in the description have been corrected. The original figures were measured against a baseline that has since moved; the branch sits behind v8 by release commit Version Packages #327, so the honest baseline is the merge-base (722e27d), not current v8. Corrected figures are in the PR body.

Verdict is advisory per sdk-pr-review-gate; native reviewer approval is separately required by branch protection.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

1 similar comment
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

@Hitesh-IDK

Copy link
Copy Markdown
Collaborator Author

RUN_TESTS

@minionhelperappqa

Copy link
Copy Markdown

[SDK Wdio Test] TRA build state: failed | Stability 96% — verdict: success. Passed: 51, Failed: 2, Aggregate: 53. TRA: https://observability.browserstack.com/builds/y5rii2cnlwligbxhksiedcl2zfk8qeftfqk0matn

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

1 similar comment
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

@hamza-browserstack
hamza-browserstack merged commit 08f9ce6 into v8 Nov 3, 2026
20 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants