Is Scribe: AI Documentation, SOPs & Process Intelligence safe?

Medium risk

Scribe is medium risk. When the extension starts, it creates an offscreen document to run the LaunchDarkly SDK. DA observed startup requests, including a GET whose decoded context held an anonymous device key, then analytics and feature-flag traffic.…

chrome-store-adminsv104.30.0Chrome Web Store
45Risk
Who publishes it

Colony Labs, Inc. - 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
chrome-store-admins
Declared legal entity
Colony Labs, Inc.
Registered address
427 Brannan St, San Francisco, CA 94107-1715, US
Registered contact
dba Scribe

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

LaunchDarkly Receives Extension Device Context

When the extension starts, it creates an offscreen document to run the LaunchDarkly SDK.

DA observed startup requests, including a GET whose decoded context held an anonymous device key, then analytics and feature-flag traffic.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension starts after installation or browser startup.

The extension did this

It loads LaunchDarkly in an offscreen document and sends an anonymous device context to LaunchDarkly.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://clientsdk.launchdarkly.com/sdk/evalx/61831e1e3e135e62b5cbb6bd/contexts/eyJrZXkiOiI0NDg2ZDAxMi01ZGYzLTQyMzktYWFlNC1mZjhhYjk4YTJhNmQiLCJhbm9ueW1vdXMiOnRydWUsImtpbmQiOiJkZXZpY2UifQ
Feature-flag evaluation request; no request body because the context is encoded in the URL.
03EvidenceFIELD TABLE
Context observed in LaunchDarkly traffic
FieldValueWhy it matters
Device key
4486d012-5df3-4239-aae4-ff8ab98a2a6dThis lets the feature-flag service associate requests with this browser's extension install.
Context kind
deviceThis marks the request as an anonymous device context rather than a named account.
Client-side ID
61831e1e3e135e62b5cbb6bdThis identifies the LaunchDarkly project used by the extension.
04EvidenceCODE COMPARE
The code that does this

Offscreen LaunchDarkly setup and context construction

What it actually does
Readable offscreen document creationassets/launchdarkly-DljPGdGt.js
async function ne(e = "src/offscreen/offscreen.html") {
  if (l) {
    await l;
    return
  }
  const o = chrome.runtime.getURL(e);
  l = (async () => {
    if (chrome.runtime.getContexts && (await chrome.runtime.getContexts({
        contextTypes: ["OFFSCREEN_DOCUMENT"],
        documentUrls: [o]
      })).length) return;
    const a = ce();
    try {
      await chrome.offscreen.createDocument({
        url: e,
        reasons: ["LOCAL_STORAGE"],
        justification: "Run LaunchDarkly browser SDK in a window context; it caches flags in localStorage and requires browser-only APIs not available in the MV3 service worker."
      })
    } catch (m) {
      const i = m instanceof Error ? m.message : String(m);
      if (!/single offscreen document/i.test(i)) throw a.cancel(), m
    }
    await a.promise
  })().catch(a => {
    throw A(), a
  }), await l
}
Readable device context and LD_INIT callassets/launchdarkly-DljPGdGt.js
M = async () => {
  let e = await T(O);
  return e || (e = await T(Q) || V(), X(O, e), e)
}, P = async e => {
  const o = f(),
    a = {
      kind: "multi",
      device: {
        key: await M(),
        ...o ? {
          extension_version: o
        } : {}
      }
    },
    m = e?.active_organization?.super_organization;
  if (e) {
    const i = e,
      t = {
        key: e.id,
        email: e.email,
        signupMethod: e.signup_method,
        signupSource: i.signup_source,
        dateJoinedTimestamp: e.date_joined ? new Date(e.date_joined).valueOf() : void 0,
        businessEmail: e.email ? ie(e.email) : void 0,
        roleCode: m?.role?.code
      };
    a.user = t
  }
  if (m?.id) {
    const i = {
      key: m.id,
      plan: m.plan?.name,
      proPlanType: m.pro_plan_type,
      enterprisePlanType: m.enterprise_plan_type,
      subscriptionStatus: m.stripe_subscription_status,
      spsEnabled: m.smart_privacy_screen_enabled,
      organization_id: e?.active_organization?.id,
      userCount: e?.active_organization?.user_count,
      createdTimestamp: m.created ? new Date(m.created).valueOf() : void 0
    };
    a.super_organization = i
  }
  if (e?.active_organization?.id) {
    const i = e.active_organization,
      t = i.created,
      c = {
        key: i.id,
        ...i.name && {
          name: i.name
        },
        created_timestamp: t ? new Date(t).valueOf() : void 0
      };
    a.organization = c
  }
  return a
}, I = async () => {
  try {
    return await p("LD_INIT", {
      clientSideId: H,
      context: await P(null)
    }) === !0
  } catch {
    return !1
  }
}, $ = async () => u ? !0 : s || (s = (async () => {
  try {
    if (await I()) return u = !0, !0;
    try {
      w("launchdarkly_init_failed_retrying")
    } catch {}
    if (await new Promise(e => {
        setTimeout(e, le)
      }), await I()) return u = !0, !0;
    try {
      w("launchdarkly_init_failed")
    } catch {}
    return !1
  } finally {
    s = null
  }
})(), s);
05EvidenceTHIRD PARTY LIST
LaunchDarkly endpoints observed or configured
  • clientsdk.launchdarkly.com

    LaunchDarkly feature-flag evaluation endpoint receiving the encoded device context.

  • clientstream.launchdarkly.com

    LaunchDarkly streaming endpoint for live feature-flag updates.

  • events.launchdarkly.com

    LaunchDarkly event endpoint for diagnostic and bulk analytics events.

SeverityLOW
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Scribe Uploads Extension Trace Spans

When the extension starts, it inits OpenTelemetry tracing for the service worker and posts trace data to otel.scribehow.com.

DA captured a POST to /v1/traces with resource attributes, platform details, and spans of its own fetches.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension starts and enables its telemetry configuration.

The extension did this

It collects OpenTelemetry spans for extension activity and posts them to Scribe's tracing endpoint.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://otel.scribehow.com/v1/traces
24,341-byte OTLP JSON payload with resourceSpans for service.name='scribe-extension' and service.version='2.95.1'.
Headers
Content-Typeapplication/json
03EvidenceFIELD TABLE
Fields observed in the trace payload
FieldValueWhy it matters
Service name
scribe-extensionThis identifies the trace data as coming from the Scribe extension.
Extension version
2.95.1This ties the trace data to the installed extension build.
Browser platform
LinuxThis describes the browser environment where the extension ran.
Outbound request span
POST https://scribe-api.scribehow.com/api/track/log_new_relic/This records that the extension made a specific network request while tracing was active.
04EvidenceCODE COMPARE
The code that does this

OpenTelemetry exporter setup

What it actually does
Readable trace exporter POST implementationassets/index.js-CuJ0YNIJ.js
class ng {
  _url;
  constructor(t) {
    this._url = cc(t)
  }
  export (t, n) {
    const r = nI.serializeRequest(t);
    ic(this._url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: r
    }).then(a => {
      n({
        code: a.ok ? Qt.SUCCESS : Qt.FAILED
      })
    }).catch(a => {
      console.warn("[OTel] Failed to export traces:", a), n({
        code: Qt.FAILED
      })
    })
  }
  shutdown() {
    return Promise.resolve()
  }
  forceFlush() {
    return Promise.resolve()
  }
}
Readable telemetry initializationassets/index.js-CuJ0YNIJ.js
const pc = e => Do ? new URL(e, Do).toString() : null,
  $a = () => {
    if (ot || ar) return;
    const e = u.getState(),
      {
        extensionOtel: t
      } = pe(e);
    if (!t) return;
    const n = pc("/v1/traces"),
      r = pc("/v1/logs");
    if (!n || !r) {
      dc || (console.warn("[OTel] Skipping telemetry because OTEL_COLLECTOR_ORIGIN is empty"), dc = !0), e?._persist?.rehydrated && pa();
      return
    }
    const a = typeof t == "number" ? t : 10;
    globalThis.__otelFlushTelemetry = rI, globalThis.__otelGetDirectTracer = aI;
    try {
      sI({
        serviceName: "scribe-extension",
        serviceVersion: chrome?.runtime?.getManifest?.()?.version ?? "unknown",
        collectorOrigin: Do,
        scheduledDelayMillis: a * 1e3,
        logsToConsole: !oI,
        traceExporter: new ng(n),
        logExporter: new rg(r),
        jwtGetter: () => lc,
        attributeGetter: () => {
          const s = Ve(u.getState()).userData?.active_organization?.id,
            i = {};
          return s && (i["team.id"] = String(s)), i
        }
      }), ot = !0, xd()
    } catch (s) {
      ot = !1, console.error("[OTel] Failed to initialize telemetry", s), pa()
    }
  };
05EvidenceTHIRD PARTY LIST
Tracing destination
  • otel.scribehow.com

    Scribe OpenTelemetry collector receiving extension trace payloads.

Updated 30 September 2026okfkdaglfjjjfefdcppliegebpoegaii