Is Vidyard - Screen Recorder & Screen Capture safe?

Medium risk

Vidyard is medium risk. Code shows Vidyard's recording panel posts metrics to extension-backend.vidyard.com/gv_metrics: a metric name, value, connection type, version, and caller tags. Sign-in requirement blocked live capture; no body included.…

Vidyardv5.1.5Chrome Web Store
54Risk
Who publishes it

Buildscale, Inc - no other listings under this identity, 2 shared hostnames

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Vidyard
Declared legal entity
Buildscale, Inc
Registered address
301-1 Queen St N, Kitchener, ON N2H 2G7, CA
Registered contact
Buildscale, Inc

Shared hosts - 2 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

embed.vidyard.com
Also called by 2 other listings: SuperSDR Chrome Extension, Outplay Connect
vidyard.com
Also called by 3 other listings, including Cast Kodi, Cast Kodi

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Vidyard posts recording metrics to its telemetry backend

Code shows Vidyard's recording panel posts metrics to extension-backend.vidyard.com/gv_metrics: a metric name, value, connection type, version, and caller tags.

Sign-in requirement blocked live capture; no body included.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You use Vidyard's recording panel or a recording-related workflow.

The extension did this

The extension measures performance and sends the metric name, value, and tags to Vidyard's metrics backend.

Fields built for the metrics request
  • Metric name
    recording_panel_time_to_load

    Shows which part of the recording workflow was measured.

  • Measured value
    842.5

    Records the timing or count for that recording workflow measurement.

  • Network type
    4g

    Adds your browser-reported connection type to the telemetry tags.

  • Extension version
    4.3.9

    Tells the metrics backend which extension build produced the measurement.

Captured request
POSThttps://extension-backend.vidyard.com/gv_metrics

No response was captured because sign-in prevented the dynamic session from entering the recording workflow.

The code that does this

Recording metrics are measured and posted

Readable version

Recording panel starts the load metric

overlayPopup.min.js
function jp() {  (0, t.useEffect)((() => {    (async () => {      await Np.A.worker("startPerformanceMetrics", {        measureName: Wi.A.Analytics.Metrics.RECORDING_PANEL_TIME_TO_LOAD      }), await Zf.A.dispatch("resetUIVisibility")    })()  }), []);  const {    cameraDeviceName: e,    micDeviceName: n,    microphoneEnabled: r,    source: i,    isProcessing: a,    isRecording: o  } = qi(Zi.A, (e => ({    cameraDeviceName: e.cameraDeviceName,    micDeviceName: e.micDeviceName,    microphoneEnabled: e.microphoneEnabled,    source: e.source,    isProcessing: e.isProcessing,    isRecording: e.isRecording  })));}

Metrics helper posts metric, value, and tags

overlayPopup.min.js
async function s(e, t = 1, n = {}) {  var i;  n.connectionType = (null === (i = navigator) || void 0 === i || null === (i = i.connection) || void 0 === i ? void 0 : i.effectiveType) || "unknown", n.version = "4.3.9";  try {    await r.A.sendRequest({      baseUrl: "https://extension-backend.vidyard.com/gv_metrics",      method: "POST",      params: {        metric: e,        value: t,        tags: n      }    })  } catch (r) {    if (o(e, r)) return;    a.A.error("Could not log metric to Datadog", r, {      ...null == r ? void 0 : r.data,      metric: e,      value: t,      tags: n    })  }}
Telemetry destination
    • extension-backend.vidyard.com

    Vidyard endpoint receiving recording performance metrics; the error log string names Datadog as the metrics destination.

Vidyard sends identified usage events to Heap Analytics

Code shows Vidyard posts usage events to Heap Analytics with a Heap app ID, user ID, event name, timestamp, user agent, and version.

Sign-in blocked live capture; the body below reflects source code, not a capture.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You open Vidyard or use one of its recording-related controls.

The extension did this

The extension prepares a usage event that is tied to the current Vidyard user ID and sends it to Heap Analytics.

Fields built for the Heap request
  • Analytics app
    4242522408

    Identifies the Heap project that receives the event.

  • Your Vidyard user ID
    12345678

    Ties the usage event back to a signed-in Vidyard account in the extension state.

  • Event name
    Opened Extension

    Shows what extension action was recorded.

  • Event time
    2026-07-12T20:31:48.376Z

    Records when the extension action happened.

  • Browser and extension
    Chrome/126.0.0.0, Vidyard 4.3.9

    Adds your browser user agent and the Vidyard extension version to the event.

Captured request
POSThttps://heapanalytics.com/api/track

No response was captured because the login gate prevented the dynamic session from triggering this request.

The code that does this

The source path that builds and sends Heap events

Readable version

Popup open event calls the worker handler

popup.min.js
(0, t.useEffect)((() => {  let e = null;  const t = async t => {    const {      action: n    } = t;    n === Sm.A.Popup.CLOSE_POPUP && await (0, rk.dE)(e) && window.close()  };  return (0, Em.d$)(t, Sm.A.Popup), (async () => {    try {      e = await (0, rk.Oo)(), await (0, Sy.A)(), await (0, Cy.vs)(), await Wr.A.commit("clearVideoPreviewer"), await lk.A.worker("handleOnExtensionOpened"), p(await (0, Oy.$I)({        namespace: "auth",        storageArea: "local"      })), await em.A.dispatch("checkVideoRecovery"), await s.A.dispatch("validateAccessTokenNotExpired"), Mu.A.state.isTestVideo || await hr.A.dispatch("updatePanelForAIAvatarsPromo")    } catch (e) {      Hh.A.error("PopupContainer init failed", e)    } finally {      d(!1)    }  })(), () => {    (0, Em.E2)(t)  }}), []);

Heap helper adds identity and event properties

service-worker.min.js
const u = {    ADD_USER_PROPERTIES: "addUserProperties",    TRACK: "track"  },  l = async (e, ...t) => {    if (!(0, a.SR)() && !(0, a.hp)()) return void await i.A.worker("sendHeap", {      method: e,      args: t    });    if (await r.A.waitForLoaded(), !r.A.state.userId) return;    let n, l;    if (e === u.TRACK) {      n = "track";      const e = t?.[1] || {};      e.manifestVersion = 3, e.extensionVersion = "4.3.9", e.browser = navigator.userAgent, l = {        timestamp: (new Date).toISOString(),        event: t[0],        properties: e      }    } else e === u.ADD_USER_PROPERTIES && (n = "add_user_properties", l = {      properties: t[0]    });    o.A.debug({      src: "Heap",      message: e,      data: t    });    try {      await s.A.sendRequest({        baseUrl: `https://heapanalytics.com/api/${n}`,        method: "POST",        params: {          app_id: "4242522408",          identity: r.A.state.userId,          ...l        }      })    } catch (e) {      if (((e, t) => {          if ("Failed to fetch" === e?.message) return o.A.error({            src: "Heap",            message: e.message,            data: t          }), !0        })(e, t[0])) return;      c.rollbar.error("Failed to send Heap request", e, {        ...e?.data,        requestParams: l      })    }  };
Destination receiving the usage event
    • heapanalytics.com

    Heap Analytics endpoint receiving Vidyard extension usage events with app ID and user identity.

Hover recorder injects into all HTTPS pages when enabled

When the hover recorder flag is present and state says it should show, Vidyard registers hoverRecorder.min.js/css for https://*/*, and queries tabs to inject the same script/CSS into matches, giving the overlay page-level access.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You enable or use Vidyard's hover recorder feature.

The extension did this

The extension registers and injects its hover recorder script across HTTPS pages while the feature is active.

What the injected recorder can observe on a page
  • Matched page
    https://app.example.com/dashboard

    The recorder is not limited to a single named website; any HTTPS page can match while the feature is active.

  • Page structure
    Dashboard heading, Save button, Search input label

    The injected script can read headings, buttons, labels, and other visible page elements needed by the overlay.

  • Recorder assets
    hoverRecorder.min.js and hoverRecorder.min.css

    Shows which script and stylesheet are inserted into matching tabs.

The code that does this

Hover recorder content script registration and injection

Readable version

Feature-gated registration and tab injection

service-worker.min.js
async function l() {  if (o.Ay.syncDispatch("hasFeature", {      name: o.Gv.HOVER_RECORDER_FEATURE    }) && s.A.state.showHoverRecorder) {    await chrome.scripting.registerContentScripts([{      id: "hover-script",      js: ["hoverRecorder.min.js"],      css: ["hoverRecorder.min.css"],      matches: ["https://*/*"]    }]);    try {      (await chrome.tabs.query({})).forEach((async e => {        await (0, i.dE)(e.id) && (await chrome.scripting.insertCSS({          target: {            tabId: e.id          },          files: ["hoverRecorder.min.css"]        }), await chrome.scripting.executeScript({          target: {            tabId: e.id          },          files: ["hoverRecorder.min.js"]        }))      })), (0, r.OB)("Viewed - Hover Recorder")    } catch (e) {      a.A.error("Mounting hover recorder failed", e)    }  }}

Manifest grants scripting and broad host permissions

manifest.json
"permissions": ["storage", "tabs", "webNavigation", "scripting", "notifications", "activeTab", "offscreen", "system.display", "alarms","tabGroups"],"host_permissions": ["<all_urls>"]

What it can do

Permissions this extension asks for, as declared in version 5.1.5. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    <all_urls>

  • Store data in your browser

    storage

  • See the address and title of every tab you have open

    tabs

  • See every page you navigate to, as you navigate to it

    webNavigation

  • Run its own code inside the pages you visit

    scripting

  • Show you desktop notifications

    notifications

  • Act on the current tab, but only after you click the extension

    activeTab

  • Run hidden pages in the background

    offscreen

  • Read information about your displays

    system.display

  • Schedule its own background tasks

    alarms

  • Read and change your tab groups

    tabGroups

Updated 30 September 2026jiihcciniecimeajcniapbngjjbonjan