Is ESUIT | Photos Downloader for Facebook™ safe?

Medium risk

ESUIT is medium risk. Starting the photo-download workflow makes the content script fetch a GraphQL config from graphql-info.esuit.dev. The returned docId is used in a Facebook GraphQL POST with the page's session context: actor ID and CSRF headers.

ESUITv4.8.3Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

Remote GraphQL config drives Facebook API calls

Starting the photo-download workflow makes the content script fetch a GraphQL config from graphql-info.esuit.dev.

The returned docId is used in a Facebook GraphQL POST with the page's session context: actor ID and CSRF headers.

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

You click the extension control to start downloading Facebook photos.

The extension did this

The extension asks an ESUIT server for GraphQL configuration before it sends Facebook API requests.

Captured request
GEThttps://graphql-info.esuit.dev/CometPhotoRootContentQuery

The code expects a JSON response containing a docId field, then caches the parsed config on window and localStorage.

Headers
Content-Type
text/plain
Concrete fields used across the config fetch and follow-on Facebook call
  • Config endpoint
    https://graphql-info.esuit.dev/CometPhotoRootContentQuery

    Shows the ESUIT-controlled host contacted before the Facebook API call.

  • GraphQL query name
    CometPhotoRootContentQuery

    Identifies which Facebook query configuration the extension asks the remote host to supply.

  • Returned document ID
    7391543647605027

    The value from the remote response selects the Facebook GraphQL operation the extension sends next.

  • Facebook actor ID
    100064789123456

    This ties the Facebook API request to the currently signed-in Facebook account.

  • Facebook CSRF header
    X-CSRFToken

    This session-bound header lets the request run in the context of the signed-in Facebook page.

The code that does this

Remote config fetch and Facebook GraphQL request construction

Readable version

Readable remote config fetch function

deobfuscated/injects/index.js
        const oi = 15e3,          qn = 5e3,          be = "https://graphql-info.esuit.dev",          ai = "graphql_config_cache_",          Un = {            maxRetries: 3,            retryDelay: 1e3          };        function De(t, e = []) {          const n = {            UWgMB: "error",            BDIAF: "graphql_load"          };          return {            level: n.UWgMB,            errorMessage: t,            tags: {              scope: n.BDIAF            },            extras: {              pageLink: window.location.href            },            context: e          }        }        const si = t => new Promise(e => setTimeout(e, t));        async function ui(t, e, n) {          const r = function(C, L, Z) {              return C(L, Z)            },            i = function(C, L) {              return C(L)            },            o = function(C, L, Z, Q) {              return C(L, Z, Q)            },            a = function(C, L) {              return C !== L            },            s = function(C, L) {              return C(L)            },            u = function(C, L) {              return C instanceof L            },            c = function(C, L) {              return C === L            },            g = function(C, L) {              return C / L            },            d = function(C, L) {              return C + L            },            f = function(C, L) {              return C + L            },            l = function(C, L) {              return C + L            },            h = "HTTP error! status: ",            m = function(C, L, Z, Q) {              return C(L, Z, Q)            },            v = function(C, L, Z, Q, R) {              return C(L, Z, Q, R)            },            w = "ssss_",            S = function(C, L) {              return C + L            },            D = function(C, L, Z) {              return C(L, Z)            },            T = function(C, L, Z) {              return C(L, Z)            },            k = function(C, L, Z) {              return C(L, Z)            },            E = function(C, L, Z) {              return C(L, Z)            },            y = function(C, L) {              return C + L            },            b = function(C, L) {              return C + L            },            x = "Failed to connect to ",            $ = ": Request timeout (exceeded ",            V = function(C, L) {              return C + L            },            P = function(C, L) {              return C + L            },            O = function(C, L) {              return C + L            },            Y = function(C, L) {              return C + L            },            A = ": Unknown error",            I = function(C, L, Z) {              return r(C, L, Z)            },            F = function(C, L, Z) {              return r(C, L, Z)            },            _ = "GET",            et = "text/plain",            nt = function(C, L) {              return i(C, L)            },            at = "string",            X = function(C, L, Z, Q) {              return o(C, L, Z, Q)            },            W = function(C, L) {              return a(C, L)            },            H = function(C, L) {              return i(C, L)            },            M = "warning",            j = "docId 发生变化",            q = "graphql_doc_id_change",            J = function(C, L) {              return i(C, L)            },            rt = function(C, L) {              return s(C, L)            },            ut = function(C, L, Z) {              return r(C, L, Z)            },            Ft = "获取远程 GraphQL 配置信息失败",            st = "errors",            bt = function(C, L) {              return u(C, L)            },            G = function(C, L) {              return c(C, L)            },            tt = "AbortError",            ft = function(C, L) {              return g(C, L)            },            ct = d(f("", ai), t);          if (window[ct]) return window[ct];          const mt = new AbortController,            K = o(I, setTimeout, () => {              mt.abort()            }, qn);          try {            const C = await o(F, fetch, f(l(be, "/"), t), {              signal: mt.signal,              method: _,              headers: {                "Content-Type": et              }            });            if (r(nt, clearTimeout, K), !C.ok) throw new Error(l(h, C.status));            const L = m(I, ii, await C.text(), at);            let Z = JSON.parse(L);            const Q = {              ...Z            };            return Z = await v(X, li, Z, e, n), r(W, Q.docId, Z.docId) && (window.localStorage.getItem(f(w, Q.docId)) || (r(H, n, {              level: M,              errorMessage: j,              tags: {                scope: q              },              extras: {                pageLink: window.location.href,                graphqlName: t,                oldDocId: Q.docId,                newDocId: Z.docId              }            }), window.localStorage.setItem(S(w, Q.docId), "1"))), window[ct] = Z, Z          } catch (C) {            throw D(J, clearTimeout, K), D(rt, n, o(ut, De, Ft, [              [st, {                errorString: T(bt, C, Error) ? C.message : T(J, String, C),                graphqlName: t              }]            ])), k(bt, C, Error) ? E(G, tt, C.name) ? new Error(y(d(S(b(x, be), $), T(ft, qn, 1e3)), "s)")) : new Error(V(P(O(x, be), ": "), C.message)) : new Error(Y(S(x, be), A))          }        }

Readable GraphQL request helper

deobfuscated/injects/index.js
        async function gi(t, e, n, r) {          const i = function(U, z, it, Ot) {              return U(z, it, Ot)            },            o = function(U, z) {              return U(z)            },            a = function(U, z) {              return U(z)            },            s = function(U, z) {              return U === z            },            u = function(U, z) {              return U === z            },            c = function(U, z, it) {              return U(z, it)            },            g = function(U, z) {              return U instanceof z            },            d = function(U, z) {              return U && z            },            f = function(U, z) {              return U(z)            },            l = function(U, z) {              return U instanceof z            },            h = function(U, z, it, Ot, _t) {              return U(z, it, Ot, _t)            },            m = function(U, z) {              return U + z            },            v = function(U, z) {              return U + z            },            w = "graphql request error [",            S = "]: ",            D = function(U, z, it) {              return U(z, it)            },            T = function(U, z) {              return U != z            },            k = function(U, z, it) {              return U(z, it)            },            E = function(U, z, it, Ot, _t) {              return U(z, it, Ot, _t)            },            y = function(U, z, it) {              return U(z, it)            },            b = function(U, z) {              return U + z            },            x = function(U, z) {              return U + z            },            $ = function(U, z) {              return U + z            },            V = "graphql request warning [",            P = function(U, z, it) {              return U(z, it)            },            O = function(U, z, it) {              return U(z, it)            },            Y = function(U, z, it) {              return U(z, it)            },            A = function(U, z) {              return U + z            },            I = function(U, z) {              return U + z            },            F = function(U, z) {              return U + z            },            _ = "graphql request parser error [",            et = function(U, z) {              return U + z            },            nt = "graphql request timeout [",            at = function(U, z, it) {              return U(z, it)            },            X = function(U, z) {              return U == z            },            W = function(U, z, it) {              return U(z, it)            },            H = function(U, z, it) {              return U(z, it)            },            M = function(U, z, it) {              return U(z, it)            },            j = function(U, z, it, Ot, _t) {              return U(z, it, Ot, _t)            },            q = function(U, z, it) {              return U(z, it)            },            J = function(U, z) {              return U + z            },            rt = function(U, z) {              return U + z            },            ut = "graphql request unknown error [",            Ft = function(U, z, it, Ot, _t) {              return U(z, it, Ot, _t)            },            st = function(U, z, it) {              return U(z, it)            },            bt = function(U, z, it) {              return U(z, it)            },            G = function(U, z) {              return U + z            },            tt = "graphql config error [",            ft = function(U, z, it, Ot) {              return i(U, z, it, Ot)            },            ct = "graphqlRequest 1",            mt = function(U, z) {              return o(U, z)            },            K = "complete/next stuck",            C = function(U, z) {              return a(U, z)            },            L = function(U, z) {              return s(U, z)            },            Z = function(U, z) {              return u(U, z)            },            Q = "CRITICAL",            R = "graphqlRequest 2",            Dt = function(U, z) {              return a(U, z)            },            Yt = function(U, z, it) {              return c(U, z, it)            },            Wt = function(U, z) {              return g(U, z)            },            re = function(U, z) {              return o(U, z)            },            fn = "graphqlRequest 3",            ie = function(U, z) {              return a(U, z)            },            ke = "utfvrfSSIY",            hn = "tnbsbQdoztBufh",            Oe = "POST",            gn = "hjgopDJQBzbmfS",            pn = "sftsbQftopqtfSefloviDzbmfSfubfsd",            St = "tmjuVutfvrfSMRiqbsHzbmfS",            Me = function(U, z) {              return d(U, z)            },            It = "Required dependencies are not available",            oe = "/graphql/query/",            mn = "/api/graphql/",            Ie = "RelayModern",            ot = "application/x-www-form-urlencoded",            gt = "X-BLOKS-VERSION-ID",            Ct = "EJhojopjtsfWtlpmCcfX",            lo = "X-CSRFToken",            Zn = "hjgopDtjsbmpQ",            fo = "X-IG-App-ID",            ho = "graphqlRequest 4",            go = function(U, z) {              return f(U, z)            },            po = "pjubSmfyjQcfX",            mo = function(U, z) {              return l(U, z)            },            wo = function(U, z) {              return a(U, z)            },            vo = function(U, z) {              return o(U, z)            },            {              graphqlName: Lt,              afterArgs: yo,              skipLabelData: bo = !1            } = t;          try {            const U = await Ft(ft, ui, Lt, e, r),              z = D(mt, yo, U.variables);            z.scale || (z.scale = window.zKjQYvgSmF(po).get());            const {              docId: it            } = U;            let Ot = 0,              _t = !1;            return new Promise((Rn, ae) => {              const Do = function(qt, Qt, $t) {                  return Y(qt, Qt, $t)                },                Co = function(qt, Qt, $t) {                  return at(qt, Qt, $t)                };              var $n;              const se = {                fb_api_req_friendly_name: Lt,                variables: JSON.stringify(z),                doc_id: it              };              try {                const qt = window.zKjQYvgSmF(ke),                  Qt = window.zKjQYvgSmF(hn)(Oe),                  $t = window.zKjQYvgSmF(gn),                  tr = window.zKjQYvgSmF(pn),                  er = X(null, $n = window.zKjQYvgSmF(St)) ? void 0 : $n.parsePayload;                if (!(y(Me, qt, Qt) && $t && tr && er)) throw new Error(It);                const wn = [];                let nr = 0;                const vn = new qt(n ? oe : mn),                  To = $t.actorID;                vn.setMethod(Oe).setData({                  av: To,                  ...Qt,                  fb_api_caller_class: Ie,                  server_timestamps: !0,                  ...se                }).setErrorHandler(Ut => {                  const zt = [Ut.errorCode, Ut.errorType, Ut.errorMsg].filter(Boolean).join(" ");                  h(ft, ve, ct, zt, se), c(mt, ae, new Error(m(v(m(w, Lt), S), zt)))                }).setResponseHandler(W(ie, tr, Ut => {                  const zt = {                    HwqHW: K,                    uRxsq: function(Jt, Vt) {                      return Do(mt, Jt, Vt)                    }                  };                  try {                    for (const Jt of Ut) {                      const Vt = D(C, er, Jt.responseText);                      if (T(null, Vt) && Vt.errors && c(L, 0, nr)) {                        const ue = Vt.errors.find(ce => ce.severity === "CRITICAL") || Vt.errors[0];                        if (ue) {                          const ce = [ue.code, ue.message, ue.description].filter(Boolean).join("  ");                          if (k(Z, Q, ue.severity)) return E(ft, ve, R, ce, se), y(Dt, ae, new Error(b(v(x(w, Lt), S), ce)));                          console.warn(x(b($(V, Lt), S), ce))                        }                      }                      if (wn.push(Vt), bo || Jt.isComplete) return _t = !0, void P(C, Rn, wn);                      nr++, window.clearTimeout(Ot), Ot = i(Yt, setTimeout, () => {                        _t || (console.log(zt.HwqHW), _t = !0, zt.uRxsq(Rn, wn))                      }, oi)                    }                  } catch (Jt) {                    const Vt = D(Wt, Jt, Error) ? O(re, we, Jt) : D(Dt, String, Jt);                    E(ft, ve, fn, Vt, se), Y(mt, ae, new Error(A(I(F(_, Lt), S), Vt)))                  }                })).setTimeout(3e4).setTimeoutHandler(() => {                  var Ut, zt;                  Ut = ae, zt = new Error(b(et(nt, Lt), "]")), Co(ie, Ut, zt)                });                const Ne = {                  "Content-Type": ot,                  "X-FB-Friendly-Name": Lt                };                n && (Ne[gt] = window.zKjQYvgSmF(Ct).versioningID, Ne[lo] = window.zKjQYvgSmF(Zn).getCSRFToken(), Ne[fo] = window.zKjQYvgSmF(Zn).getIGAppID()), Object.entries(Ne).forEach(([Ut, zt]) => {                  vn.setRequestHeader(Ut, zt)                }), vn.send()              } catch (qt) {                const Qt = H(Wt, qt, Error) ? y(re, we, qt) : M(mt, String, qt);                j(ft, ve, ho, Qt, se), q(go, ae, new Error(J(v(rt(ut, Lt), S), Qt)))              }            })          } catch (U) {            const z = st(mo, U, Error) ? c(wo, we, U) : bt(vo, String, U);            throw new Error(v(F(G(tt, Lt), S), z))          }        }
The code that does this

Download workflow and concrete GraphQL query names

Readable version

Readable click component that calls the download workflow

deobfuscated/injects/index.js
function Ji() {          const t = {              VZReU: function(l, h) {                return l(h)              },              EvFck: function(l, h, m) {                return l(h, m)              },              gnkvL: function(l) {                return l()              },              MJitb: function(l) {                return l()              },              ZxNnM: "consumeFeaturesTreeTryByMemoUIConfigs",              uxdZm: function(l, h) {                return l(h)              },              PkLQz: function(l, h) {                return l(h)              },              OpljH: function(l, h) {                return l(h)              },              GxJkR: function(l) {                return l()              },              NkTAZ: "100%",              twPcN: "space-between",              ospUd: "middle",              hVJqe: function(l, h, m) {                return l(h, m)              },              NVrSo: function(l, h) {                return l === h              },              IFPVu: function(l, h, m) {                return l(h, m)              },              SgccG: "text",              TYSVA: "Close",              FSpjC: function(l, h, m) {                return l(h, m)              },              ttjza: function(l, h, m) {                return l(h, m)              },              owZTi: "primary",              mSnxv: "Stop",              mZeIZ: function(l, h, m) {                return l(h, m)              },              GgWko: function(l, h, m) {                return l(h, m)              },              ZTIjf: "ReDownload"            },            {              resetStatus: e,              setOpen: n,              step: r,              isStopManually: i,              setStep: o,              isOnLimit: a,              updateUI: s            } = t.PkLQz(B.useContext, yt),            {              isSkipDownloadedFile: u,              saveMemoSettings: c            } = t.uxdZm(B.useContext, xt),            {              modalApi: g            } = t.uxdZm(B.useContext, Gt),            {              startFetchAndDownload: d            } = t.GxJkR(Yi);          function f(l) {            const h = function(v, w) {                return t.VZReU(v, w)              },              m = function(v, w, S) {                return t.EvFck(v, w, S)              };            t.gnkvL(c), t.gnkvL(Te), t.MJitb(Tt).send(t.ZxNnM, {              isSkipDownloadedFile: u            }), i.current = !1, t.uxdZm(o, lt.DOWNLOADING), t.PkLQz(d, l).then(() => {              if (a.current) return h(s, !0);              h(o, lt.DONE)            }).catch(v => {              console.error(v), i.current = !0, m(je, g, v)            })          }          return t.EvFck(p.jsxs, N.Row, {            style: {              width: t.NkTAZ            },            justify: t.twPcN,            align: t.ospUd,            children: [t.hVJqe(p.jsxs, N.Space, {              size: 8,              children: [t.hVJqe(p.jsx, nn, {}), t.EvFck(p.jsx, rn, {})]            }), t.EvFck(p.jsxs, N.Space, {              size: 24,              children: [t.NVrSo(r, lt.START) && t.IFPVu(p.jsxs, p.Fragment, {                children: [t.IFPVu(p.jsx, N.Button, {                  type: t.SgccG,                  onClick: () => n(!1),                  children: t.TYSVA                }), t.IFPVu(p.jsx, un, {                  onClick: () => f()                }), t.FSpjC(p.jsx, qi, {                  onClick: f                })]              }), t.NVrSo(r, lt.DOWNLOADING) && t.hVJqe(p.jsx, p.Fragment, {                children: t.ttjza(p.jsx, N.Button, {                  type: t.owZTi,                  danger: !0,                  onClick: () => {                    i.current = !0, t.OpljH(o, lt.DONE)                  },                  children: t.mSnxv                })              }), t.NVrSo(r, lt.DONE) && t.mZeIZ(p.jsxs, p.Fragment, {                children: [t.GgWko(p.jsx, N.Button, {                  type: t.SgccG,                  onClick: () => n(!1),                  children: t.TYSVA                }), t.ttjza(p.jsx, N.Button, {                  onClick: () => e(),                  children: t.ZTIjf                })]              })]            })]          })        }

Readable photo-download workflow with CometPhotoRootContentQuery

deobfuscated/injects/index.js
function Yi() {          const t = {              COqxZ: function(V, P) {                return V(P)              },              PPLqj: function(V, P) {                return V(P)              },              qfWxF: "CometPhotoRootContentQuery",              ALZrp: "photo",              brIHE: "API request error 141 photo:",              iByOg: function(V, P, O) {                return V(P, O)              },              oRpcd: "data.currMedia.owner.id",              ALYUJ: function(V, P) {                return V > P              },              wKImL: function(V, P) {                return V(P)              },              FMlnO: "Failed to fetch HD photos",              bXSia: function(V, P) {                return V + P              },              teKxB: function(V, P, O) {                return V(P, O)              },              XKewa: "data.owner.name",              btBWU: "name",              YXDKs: "unknown",              xjluB: "data.currMedia.image.uri",              rSzrO: function(V, P, O) {                return V(P, O)              },              qjvFY: "data.message.text",              tpPTY: function(V, P, O, Y) {                return V(P, O, Y)              },              hKGeh: "data.currMedia.id",              CtZyP: function(V, P) {                return V(P)              },              XEyfI: function(V, P) {                return V ?? P              },              LrjjG: "data.currMedia.created_time",              YnZAX: "set",              lhMeh: "found collectionToken as undefined!",              zxWUV: function(V, P) {                return V >= P              },              hqEkw: function(V) {                return V()              },              dKxno: function(V, P, O) {                return V(P, O)              },              Lhihx: "downloading",              nXtKY: function(V, P) {                return V === P              },              ymrFH: function(V, P) {                return V - P              },              qwXMB: "day",              MgKOC: function(V, P) {                return V < P              },              jJTmv: "error",              HbJGo: "download HD image error: ",              bCXeZ: "fetch HD image error: ",              klrkI: function(V, P) {                return V > P              },              rUHDo: "There have been 5 consecutive request errors, and the program has been terminated. ",              MghvA: function(V, P, O, Y) {                return V(P, O, Y)              },              LJYmG: function(V, P) {                return V == P              },              TrjgZ: "string",              vociu: function(V, P, O, Y) {                return V(P, O, Y)              },              flabI: "Photo",              xAkxg: function(V, P, O, Y) {                return V(P, O, Y)              },              BAhsO: "waiting",              DkqKg: function(V, P) {                return V + P              },              pcZBR: function(V, P) {                return V || P              },              mIsil: function(V, P) {                return V(P)              },              ZXxat: function(V, P) {                return V(P)              },              UtBxi: function(V, P) {                return V(P)              },              XjMur: "uyfuopDfspuTfuvpSufnpD",              YZJNn: function(V, P) {                return V(P)              },              TMBxa: function(V, P) {                return V(P)              },              hsLbh: function(V) {                return V()              },              piHAR: function(V, P) {                return V(P)              }            },            e = t.UtBxi(B.useContext, window.zKjQYvgSmF(t.XjMur)),            {              graphQLName: n,              collectionToken: r,              paths: i,              requestExtraPayload: o = {},              folderName: a            } = t.YZJNn(B.useContext, on),            {              fetchLimit: s,              fetchingCountType: u,              fetchingCountByPhotosCountValue: c,              fetchingCountByPhotosDaysValue: g            } = t.wKImL(B.useContext, xt),            {              isOnLimit: d,              isStopManually: f,              downloadCountRef: l,              photosArrRef: h,              setIsFetchingNextPageRef: m,              appendPhotos: v,              setPhotoStatus: w            } = t.wKImL(B.useContext, yt),            {              removeResumeCursor: S,              updateResumeCursor: D            } = t.UtBxi(B.useContext, an),            {              AvoidAccountRestrict: T            } = t.hqEkw(Qn),            {              findValueFromLoadQueryData: k,              graphqlRequest: E            } = t.TMBxa(Ke, {              projectId: Pt            }),            {              download: y            } = t.hsLbh(cn),            {              requestDelay: b            } = t.hsLbh(Wn),            x = t.piHAR(B.useRef, 0);          async function $(V, P = 0) {            var I;            const O = {              VuWEI: t.ALZrp,              WXAnF: t.brIHE,              oIqDI: function(F, _, et) {                return t.iByOg(F, _, et)              },              PJFTK: t.oRpcd,              jBZlb: function(F, _) {                return t.ALYUJ(F, _)              },              rhWuR: function(F, _) {                return t.wKImL(F, _)              },              lGszk: t.FMlnO,              bqGYJ: function(F, _) {                return t.wKImL(F, _)              },              RXNug: function(F, _) {                return t.bXSia(F, _)              },              pwBUS: function(F, _, et) {                return t.teKxB(F, _, et)              },              vsbTP: t.XKewa,              gggwv: t.btBWU,              iQbnw: t.YXDKs,              ilbzF: t.xjluB,              sHNcZ: function(F, _, et) {                return t.rSzrO(F, _, et)              },              UyQdW: t.qjvFY,              UYXMA: function(F, _, et, nt) {                return t.tpPTY(F, _, et, nt)              },              hFNnv: t.hKGeh,              XBcdB: function(F, _) {                return t.CtZyP(F, _)              },              oXDqf: function(F, _) {                return t.XEyfI(F, _)              },              khutD: function(F, _, et, nt) {                return t.tpPTY(F, _, et, nt)              },              XMOtx: t.LrjjG            };            let Y = new URLSearchParams(V.uri.split("?")[1]),              A = Y.get(t.YnZAX);            if (Y = null, !A) {              const F = await e.fetchRoute(V.uri);              (I = F == null ? void 0 : F.params) != null && I.set && (A = F.params.set)            }            return new Promise((F, _) => {              const et = function(nt, at) {                return t.COqxZ(nt, at)              };              t.PPLqj(E, {                graphqlName: t.qfWxF,                afterArgs: nt => ({                  ...nt,                  ...Yn(A, V.id)                }),                skipLabelData: !1              }).then(async nt => {                if (!nt[0]) throw console.log(O.VuWEI, V), new Error(O.WXAnF);                const at = O.oIqDI(ht.get, nt[0], O.PJFTK);                if (!at) return O.jBZlb(P, 2) ? O.rhWuR(_, O.lGszk) : (await O.bqGYJ(Qe, 2), O.rhWuR(F, await O.oIqDI($, V, O.RXNug(P, 1))));                const X = O.pwBUS(k, nt, O.vsbTP);                let W = a || (window.zKjqYvcSmF(at, O.gggwv) ?? X ?? O.iQbnw);                const H = O.pwBUS(ht.get, nt[0], O.ilbzF),                  M = O.sHNcZ(k, nt, O.UyQdW),                  j = {                    id: O.UYXMA(ht.get, nt[0], O.hFNnv, ""),                    userId: at,                    thumbnail: V.thumbnail,                    uri: H,                    folderName: O.XBcdB(Nt, O.oXDqf(a, W)),                    userName: O.XBcdB(Nt, X ?? window.zKjqYvcSmF(at, O.gggwv) ?? W),                    createdAt: O.khutD(ht.get, nt[0], O.XMOtx, 0),                    status: V.status,                    caption: M                  };                O.bqGYJ(F, j)              }).catch(nt => {                et(_, nt)              })            })          }          return t.teKxB(B.useEffect, () => {            if (!r) throw new Error(t.lhMeh)          }, []), {            startFetchAndDownload: function V(P) {              const O = {                weEZX: function(Y, A) {                  return t.wKImL(Y, A)                },                iCWus: function(Y, A) {                  return t.zxWUV(Y, A)                },                dGWtS: function(Y) {                  return t.hqEkw(Y)                },                vJRLV: function(Y, A, I) {                  return t.dKxno(Y, A, I)                },                zsuxr: t.Lhihx,                HmKvI: function(Y, A) {                  return t.nXtKY(Y, A)                },                UkndB: function(Y) {                  return t.hqEkw(Y)                },                ivSia: function(Y, A) {                  return t.ymrFH(Y, A)                },                lLxCI: t.qwXMB,                nJSLI: function(Y, A) {                  return t.MgKOC(Y, A)                },                VDPOG: t.FMlnO,                Salhi: t.jJTmv,                mPGpn: t.HbJGo,                tEtkZ: t.bCXeZ,                yjzra: function(Y, A) {                  return t.klrkI(Y, A)                },                hLxgW: t.rUHDo,                FZOxD: function(Y, A, I, F) {                  return t.MghvA(Y, A, I, F)                },                cwDaS: function(Y, A, I, F) {                  return t.tpPTY(Y, A, I, F)                },                ePbyN: function(Y, A) {                  return t.LJYmG(Y, A)                },                IwKqx: t.TrjgZ,                Ytrvm: function(Y, A, I, F) {                  return t.vociu(Y, A, I, F)                },                QdSjh: t.flabI,                bXEzq: function(Y, A, I, F) {                  return t.xAkxg(Y, A, I, F)                },                pplfw: t.BAhsO,                MANOB: function(Y, A) {                  return t.nXtKY(Y, A)                },                JTuxT: function(Y, A) {                  return t.DkqKg(Y, A)                },                biUdS: function(Y, A) {                  return t.ymrFH(Y, A)                },                jCXKM: function(Y, A) {                  return t.pcZBR(Y, A)                },                WfarU: function(Y) {                  return t.hqEkw(Y)                },                KxOvB: function(Y, A) {                  return t.mIsil(Y, A)                }              };              return f.current ? Promise.resolve() : t.zxWUV(l.current, s) ? (d.current = !0, Promise.resolve()) : (P && t.ZXxat(D, P), new Promise(async (Y, A) => {                const I = function(F, _) {                  return O.weEZX(F, _)                };                await O.WfarU(T), await O.dGWtS(b), O.KxOvB(m, !0), O.weEZX(E, {                  graphqlName: n,                  afterArgs: F => ({                    ...F,                    cursor: P || null,                    id: r,                    ...o                  }),                  skipLabelData: !0                }).then(async F => {                  const _ = {                    ykJWJ: function(j, q) {                      return O.weEZX(j, q)                    },                    ceXcv: function(j, q) {                      return O.iCWus(j, q)                    },                    axhLj: function(j) {                      return O.dGWtS(j)                    },                    DChoq: function(j, q, J) {                      return O.vJRLV(j, q, J)                    },                    iZTLi: O.zsuxr,                    MqBFg: function(j, q) {                      return O.HmKvI(j, q)                    },                    xJhnY: function(j) {                      return O.UkndB(j)                    },                    jYLpJ: function(j, q) {                      return O.ivSia(j, q)                    },                    wxmZs: O.lLxCI,                    KpbCP: function(j, q) {                      return O.nJSLI(j, q)                    },                    ZubQA: O.VDPOG,                    hEFJV: O.Salhi,                    tmouC: O.mPGpn,                    bwzEJ: O.tEtkZ,                    VcmlB: function(j, q) {                      return O.yjzra(j, q)                    },                    UblOJ: O.hLxgW                  };                  if (O.weEZX(m, !1), !F[0]) throw new Error("API request error 142 collectionToken:" + r);                  const et = O.FZOxD(ht.get, F[0], i.edgesPath, []),                    nt = O.cwDaS(ht.get, F[0], i.pageInfoPath, {}),                    at = nt.has_next_page ?? !1,                    X = nt.end_cursor ?? null;                  let W = [];                  for (let j of et) {                    const q = O.ePbyN(O.IwKqx, typeof i.viewerLinkPath) ? O.Ytrvm(ht.get, j, i.viewerLinkPath, "") : i.viewerLinkPath(j);                    O.HmKvI(O.QdSjh, O.Ytrvm(ht.get, j, i.nodeTypePath, "")) && W.push({                      id: O.bXEzq(ht.get, j, i.idPath, ""),                      thumbnail: O.Ytrvm(ht.get, j, i.thumbnailUriPath, ""),                      uri: q,                      userId: "",                      userName: "",                      folderName: "",                      createdAt: 0,                      status: O.pplfw,                      caption: ""                    })                  }                  let H = !1;                  if (O.MANOB(u, kt.BY_PHOTOS_COUNT) && O.iCWus(O.JTuxT(h.current.length, W.length), c)) {                    const j = O.biUdS(W.length, O.biUdS(O.JTuxT(h.current.length, W.length), c));                    W = W.slice(0, j), H = !0                  }                  let M = !await async function(j) {                    j = j.filter(q => !h.current.find(J => J.id === q.id)), _.ykJWJ(v, j);                    for (let q of j) {                      if (_.ceXcv(l.current, s)) return d.current = !0, !1;                      if (await _.axhLj(T), await _.axhLj(b), f.current) return !1;                      _.DChoq(w, q.id, _.iZTLi);                      let J = q;                      try {                        if (J = await _.ykJWJ($, q), _.MqBFg(u, kt.BY_DAYS_COUNT)) {                          const rt = _.xJhnY(Mt).subtract(_.jYLpJ(g, 1), _.wxmZs).startOf(_.wxmZs).unix();                          if (_.KpbCP(J.createdAt, rt)) return !1                        }                        x.current = 0;                        try {                          if (!J.id) throw new Error(_.ZubQA);                          await _.ykJWJ(y, J)                        } catch (rt) {                          _.DChoq(w, q.id, _.hEFJV), console.error(_.tmouC, rt, q)                        }                      } catch (rt) {                        if (_.ykJWJ(Tr, rt)) throw new Error(rt);                        if (console.error(_.bwzEJ, rt, q), _.DChoq(w, q.id, _.hEFJV), x.current++, _.VcmlB(x.current, 5)) throw new Error(_.UblOJ)                      }                    }                    return !0                  }(W);                  return O.jCXKM(H, M) || (at ? await O.weEZX(V, X) : O.dGWtS(S)), O.UkndB(Y)                }).catch(F => {                  I(A, F)                })              }))            }          }        }

Readable marketplace workflow with concrete GraphQL query names

deobfuscated/injects/index.js
function oo() {          const t = {              giEUK: "found collectionToken as undefined!",              XlOMA: function(u, c) {                return u(c)              },              rvjDS: "MarketplacePDPContainerQuery",              fDDBQ: function(u, c) {                return u(c)              },              ykXtG: "MarketplacePDPC2CMediaViewerWithImagesQuery",              CbYTx: function(u, c) {                return u(c)              },              ehDpv: function(u, c, g, d) {                return u(c, g, d)              },              TcxGA: "[0].data.viewer.marketplace_product_details_page.target.listing_photos",              LHalb: "[0].data.viewer.marketplace_product_details_page.target.creation_time",              NmAXi: "[0].data.viewer.marketplace_product_details_page.target.marketplace_listing_seller.name",              pDpjJ: "unknown",              IUexD: function(u, c, g, d) {                return u(c, g, d)              },              OVlvm: "[0].data.viewer.marketplace_product_details_page.target.marketplace_listing_seller.id",              yKOZB: "[0].data.viewer.marketplace_product_details_page.target.redacted_description.text",              gJuEU: "waiting",              yxWal: function(u) {                return u()              },              qvdGo: function(u, c) {                return u(c)              },              nYxyg: function(u, c) {                return u(c)              },              xYmtM: function(u, c, g) {                return u(c, g)              }            },            {              targetId: e            } = t.CbYTx(B.useContext, Xn),            {              isStopManually: n,              setIsFetchingNextPageRef: r,              appendPhotos: i            } = t.qvdGo(B.useContext, yt),            {              graphqlRequest: o,              findValueFromLoadQueryData: a            } = t.CbYTx(Ke, {              projectId: Pt            }),            {              download: s            } = t.nYxyg(cn, !0);          return t.xYmtM(B.useEffect, () => {            if (!e) throw new Error(t.giEUK)          }, []), {            startFetchAndDownload: function() {              return n.current ? Promise.resolve() : new Promise(async (u, c) => {                t.XlOMA(r, !0);                const g = await t.XlOMA(o, {                    graphqlName: t.rvjDS,                    afterArgs: w => ({                      ...w,                      targetId: e                    }),                    skipLabelData: !1                  }),                  d = await t.fDDBQ(o, {                    graphqlName: t.ykXtG,                    afterArgs: w => ({                      ...w,                      targetId: e                    }),                    skipLabelData: !1                  });                t.CbYTx(r, !1);                const f = t.ehDpv(ht.get, d, t.TcxGA, []),                  l = t.ehDpv(ht.get, g, t.LHalb, 0),                  h = t.ehDpv(ht.get, g, t.NmAXi, t.pDpjJ),                  m = t.IUexD(ht.get, g, t.OVlvm, ""),                  v = t.IUexD(ht.get, g, t.yKOZB, "");                t.XlOMA(i, f.map(w => ({                  id: w.id,                  userId: m,                  thumbnail: w.image.uri,                  uri: w.image.uri,                  folderName: Nt(h),                  userName: Nt(h),                  createdAt: l,                  status: "waiting",                  caption: v                })));                for (const w of f)                  if (await t.CbYTx(s, {                      id: w.id,                      userId: m,                      thumbnail: w.image.uri,                      uri: w.image.uri,                      folderName: t.CbYTx(Nt, h),                      userName: t.CbYTx(Nt, h),                      createdAt: l,                      status: t.gJuEU,                      caption: v                    }), n.current) return;                return t.yxWal(u)              })            }          }        }
Remote hosts involved in the workflow
    • graphql-info.esuit.dev

    ESUIT-controlled host that supplies GraphQL docId configuration.

    • www.facebook.com

    Facebook host receiving the follow-on /api/graphql/ request in the signed-in page context.

    • web.facebook.com

    Facebook web variant covered by the extension matches and host permissions.

Updated 21 September 2026djlgfdiljlmbcfimhkeenolnndblfmoo