Is Vmaker - Free Screen Recorder safe?

Medium risk

Vmaker - Free Screen Recorder is medium risk. Starting a Vmaker recording opens a Socket.IO link to ping.vmaker.com and emits video chunks with your user/video ID. The code reads the stored access token and attaches it as the auth header on related POSTs, including the S3 fallback.

Vmakerv6.1.0Chrome Web Store
45Risk
Who publishes it

Vmaker - no other listings under this identity

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

Publisher
Vmaker

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Vmaker uploads recordings to ping.vmaker.com

Starting a Vmaker recording opens a Socket.IO link to ping.vmaker.com and emits video chunks with your user/video ID.

The code reads the stored access token and attaches it as the auth header on related POSTs, including the S3 fallback.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You start a screen or camera recording in Vmaker.

The extension did this

The extension opens its upload service and sends recording chunks tied to your Vmaker account.

02EvidenceFIELD TABLE
Fields sent or used by the upload flow
FieldValueWhy it matters
Recorded video chunk
Blob object for vmk_20260714_153045-0.webm (illustrative)A chunk can contain part of what your screen or camera captured during the recording.
Video identifier
vmk_20260714_153045This ties each uploaded chunk back to one recording session.
Vmaker user identifier
742391 (illustrative)This links the upload activity to a Vmaker account.
Chunk name
vmk_20260714_153045-0This records the order of each uploaded piece so the service can rebuild the video.
Upload timestamp
1720961445This records when the chunk was sent.
Stored access token
authorization: <redacted>A token can authorize related upload-service requests for your Vmaker account.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://ping.vmaker.com
Socket.IO upload connection selected by the extension source; no request body was recorded for this flow.
04EvidenceCODE COMPARE
The code that does this

The upload socket, blob emission, and token-bearing POST helper

What it actually does
Socket.IO connection and upload response handlersapp/background.js
initSocket = (e => {
  if (!SOCKET || SOCKET.disconnected)
    if (SOCKET && SOCKET.disconnected) updateLogs("log", "Reopened the socket connection"), SOCKET.open();
    else {
      const {
        socketURL: a = "https://ping.vmaker.com"
      } = backgroundState || {};
      updateLogs("log", "Initialize new socket connection"), SOCKET = io(e || a, {
        transports: ["websocket", "polling"],
        reconnection: !0,
        reconnectionAttempts: 3,
        pingTimeout: 3e4,
        pingInterval: 25e3
      }), connect(e), SOCKET.on("LoginAccessResponse", e => {
        sendMessageToMainTab({
          message: "SEND_SOCIAL_AUTH_RESPONSE",
          payload: e
        })
      }), SOCKET.on("BlobReceivedResponse", ({
        status: e,
        name: a,
        videoId: t,
        userId: o,
        code: n,
        message: r
      }) => {
        if (doUploadTimer(o, t, !0), "Success" === e) {
          a === `${t}-0` && generateThumbnail(o, t);
          try {
            updateLogs("log", `Upload Completed - ${a}`, t), db.deleteBlob(a);
            try {
              backgroundState.userData[o][t].pendingSize -= backgroundState.userData[o][t].blobs[a].size / 1e6
            } catch (e) {}
            delete backgroundState.userData[o][t].blobs[a], triggerUpload(o, t)
          } catch (e) {
            updateLogs("error", `UserData deletion error ${e}`, t), backgroundState.userData[o][t] && triggerUpload(o, t)
          }
        } else if (301 === n) try {
          updateLogs("error", `${r} Proceed for S3 Storage ${a}`, t), db.deleteBlob(a), backgroundState.userData[o][t].isS3 = !0, delete backgroundState.userData[o][t].blobs[a], triggerUpload(o, t)
        } catch (e) {
          updateLogs("error", `Captured catch block ${e}`, t)
        } else updateLogs("error", `Uploaded Failed ${a}`, t), backgroundState.userData[o][t].isS3 = !0, triggerUpload(o, t)
      }), SOCKET.on("ProjectCancelledResponse", ({
        status: e,
        videoId: a
      }) => {
        updateLogs("log", `Project ${a} Cancelled ${e}`, a)
      }), SOCKET.on("MergeBlobsFromS3Response", ({
        videoId: e,
        userId: a
      }) => {
        setCommonData(`history-${e}`, {
          isCompleted: !0
        }), setCommonData(`progress${e}`, {
          isCancelled: !0
        }), updateLogs("log", `${e} - S3 Merge Completed`, e);
        const {
          userData: t
        } = backgroundState;
        db.deleteBlob(e), delete t[a][e], IS_UPLOADING || SOCKET.close(), IS_UPLOADING = !1, checkPendingUpload && checkPendingUpload()
      }), SOCKET.on("BlobMergedResponse", ({
        videoId: e,
        userId: a,
        message: t,
        code: o,
        missingBlob: n
      }) => {
        const {
          userData: r
        } = backgroundState;
        if (200 === o) {
          try {
            setCommonData(`progress${e}`, {
              isMerged: !0
            }), updateLogs("log", `${e} - Merge Completed`, e), db.deleteBlob(e), delete r[a][e]
          } catch (a) {
            updateLogs("log", `${e} - Merge Completed - ${a}`, e)
          }
          setCommonData(`history-${e}`, {
            isCompleted: !0
          }), IS_UPLOADING || SOCKET.close(), IS_UPLOADING = !1, checkPendingUpload && checkPendingUpload()
        } else try {
          const {
            mergingTriedCount: s = 1
          } = r[a][e];
          (500 === o || 403 === o || 402 === o && 1 === (n || []).length) && (s || 1) <= 2 ? (updateLogs("warn", `Tried Merge Count : ${s} - ${o}`, e), r[a][e].mergingTriedCount = s ? s + 1 : 1, triggerUpload(a, e)) : (backgroundState.userData[a][e].isS3 = !0, updateLogs("warn", `Failed to Merge Request Status: ${o}, Missing Blogs: ${n}, Try Count: ${s} `, e), doS3MergeRequest(a, e))
        } catch (o) {
          backgroundState.userData[a][e].isS3 = !0, updateLogs("error", `Blob Merge Failed : ${t} ${o}`, e), doS3MergeRequest(a, e)
        }
      })
    }
});
BlobRequest emissionapp/pin_dependencies.js
triggerUpload = (e, t) => {
  IS_WAITING_FOR_BLOB = !1, IS_UPLOADING = !0;
  try {
    const {
      userData: o,
      isRecording: a
    } = backgroundState, {
      blobs: r,
      isRecordingStoped: n,
      isS3: d
    } = o[e][t];
    if (showLoader(e, t), window.akbar) return !0;
    if (d) return pushToS3(e, t), !0;
    const s = getKeys(r);
    if (a && n) return IS_WAITING_FOR_BLOB = !0, updateLogs("log", "Queue has been ended proceeding for current recording", t), !0;
    if (a || s.length) {
      const o = s[0],
        a = r[o] instanceof Blob || "[object Blob]" === toString.call(r[o]);
      r[o] && a ? (doUploadTimer(e, t), SOCKET.disconnected ? (updateLogs("log", `Upload Processing Failed Because of disconnected - ${o}`, t, null, !1), IS_UPLOADING = !1) : (updateLogs("log", `Upload Processing - ${o}`, t, null, !1), SOCKET.emit("BlobRequest", {
        videoId: t,
        userId: e,
        blob: r[o],
        name: o,
        unixtime: Math.floor(Date.now() / 1e3)
      }))) : !a && o ? (db.deleteBlob(o), delete backgroundState.userData[e][t].blobs[name], triggerUpload(e, t)) : IS_WAITING_FOR_BLOB = !0
    } else doBlobMerge(e, t)
  } catch (e) {
    updateLogs("error", `Trigger Upload Function ${e}`)
  }
}
Stored-token POST helperapp/pin_dependencies.js
doApiCall = (e, t, o, a = !1, r = !1) => {
  try {
    const {
      reduxData: n
    } = backgroundState, {
      userDetails: d
    } = n || {
      userDetails: backgroundState.userDetails || {}
    }, {
      access_token: s
    } = d, i = doSerialize(t || {});
    let c;
    const u = {
      ...t || {},
      product: "vmaker",
      source: "vmakerPlugin",
      version: chrome.runtime.getManifest().version,
      unixtime: Math.floor(Date.now() / 1e3),
      plugin: 1
    };
    let l;
    r ? (l = new FormData, Object.keys(u).forEach(e => {
      l.append(e, u[e])
    })) : l = JSON.stringify(u);
    let g = {};
    if (r || (g = {
        "Content-Type": "application/json"
      }), g = {
        ...g,
        authorization: s
      }, fetch(e, {
        method: "POST",
        headers: g,
        body: l
      }).then(e => e.json()).then(e => {
        c = {
          error: "Failed",
          msg: "Default One"
        }, c = e
      }).catch(e => {
        c = {
          error: "Failed",
          msg: "From Catch Block"
        }
      }).finally(() => {
        o && o(c), updateLogs("warn", `${e} ${c.error?"Failed":"Success"} ${i}`, t.videoId, c)
      }), t.userId !== d.userid && !a) return updateLogs("error", `user id not matched userId: ${t.userId} - userid: ${d.userid}`, t.videoId), !0
  } catch (o) {
    updateLogs("warn", `${e} Catch block ${o}`, t.videoId)
  }
  return !0
}
05EvidenceTHIRD PARTY LIST
Upload destinations named in the source
  • ping.vmaker.com

    Vmaker Socket.IO service that receives BlobRequest chunks and returns BlobReceivedResponse and BlobMergedResponse events.

  • s3-accelerate.amazonaws.com

    AWS S3 accelerated endpoint used by the fallback upload path after temporary S3 credentials are fetched.

Updated 30 September 2026bjibimlhliikdlklncdgkpdmgkpieplj