Is Purrfect Pomodoro Timer: Productivity, Time Management & Daily Journal safe?

High risk

Purrfect Pomodoro Timer sends daily journal entries and blocked-site URLs to PostHog analytics.

When you add a daily journal item, the extension stores the trimmed text locally and sends the journal text to PostHog analytics with a persistent anonymous user ID. When you save blocked sites in settings, it also sends each entered site URL, its host, and the block-list count to the same analytics service.

kartikth40v1.5.2Chrome Web Store
72Risk
Who publishes it

kartikth40 - 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
kartikth40
Registered address
New Palam Vihar, Gurgaon, Haryana 122017, IN
Registered contact
Kartik Thakur

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

Publishers can request a review.

Findings

Daily journal text is sent to PostHog

Adding a daily journal item stores the trimmed entry locally and sends the same text in a PostHog event.

The client targets us.i.posthog.com and IDs the browser with a persistent ID in storage, linking journal events over time.

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

You add a daily journal item in the extension.

The same flow is present on both the over page and the history journal page.

The extension did this

The extension sends the trimmed journal text as a PostHog analytics event.

The background service worker receives the journal message and includes the submitted text in the analytics event.

Fields sent or used for the analytics event
  • Your journal text
    Finished planning tomorrow's launch checklist

    This is the free-text note you typed into the daily journal. It can include personal plans, work notes, or other sensitive content.

  • Event name
    daily_journal_added

    This labels the note as a daily journal entry when it reaches the analytics service.

  • Browser analytics ID
    6f6ac450-7b8e-4c2f-8d1a-960c2d5f0a19

    This lets analytics associate journal events from the same browser over time.

Captured request
POSThttps://us.i.posthog.com/e/

Observed during dynamic analysis: a PostHog POST for the journal-added event. No response body was recorded with this observation.

The code that does this

Journal text path from UI submission to PostHog capture

Readable version

Over page: journal submission handler

public/over.js
dt.addEventListener("click", async () => {  oe("Add a daily journal item!", "What would you like to add to your daily journal?", "", async e => {    if (e !== null && e.trim() !== "") {      const t = new Date,        {          year: a,          monthDay: s,          history: n,          yearObj: o,          dayObj: l,          journalList: u        } = await te(t);      u.push({        id: Date.now() + Math.random().toString(36),        item: e.trim(),        completed: !1      }), l[0][q] = u, o[s] = l, n[a] = o, await N({        [a]: n[a]      }), await pe(), await de({        type: "DAILY_JOURNAL_ADDED",        response: e.trim()      })    }  })})

History page: journal submission handler

public/history.js
wt.addEventListener("click", async () => {  b && Yt("Add a daily journal item!", "What would you like to add to your daily journal?", "", async C => {    if (C !== null && C.trim() !== "") {      const U = k.getFullYear().toString(),        $ = `${k.getDate()}-${k.getMonth()+1}`,        j = await B(U);      let R = j[U] || {},        K = R[$] || [{}],        q = K[0][_] || [];      q.push({        id: Date.now() + Math.random().toString(36),        item: C.trim(),        completed: !1      }), K[0][_] = q, R[$] = K, j[U] = R, await dt({        [U]: j[U]      }), St(q), O = !0, await lt({        type: "DAILY_JOURNAL_ADDED",        response: C.trim()      })    }  })})

Background service worker: PostHog client and capture helper

public/background.js
const Cs = Ia().then(i => (Zi.init(cn.POSTHOG_API_KEY, {  api_host: "https://us.i.posthog.com"}), Zi.identify(i), Zi));let St = ln(0),  zt = ln(!1);const Nt = async i => {  try {    await chrome.runtime.sendMessage(i)  } catch (e) {    console.warn(e)  }}, fe = (i, e = null) => {  Cs.then(t => {    e ? t.capture(i, e) : t.capture(i)  })}, Wt = async () => {  zt.getState() && (await nn(), zt.setState(!1))};

Background service worker: journal message mapped to PostHog event

public/background.js
rn = {  START_SESSION: () => {    Sa()  },  DAILY_JOURNAL_ADDED: i => {    fe("daily_journal_added", {      item: i.response.trim()    })  },  MUSIC_PLAYING: i => {    ni && clearTimeout(ni), ni = setTimeout(() => {      fe("playing_music", {        music_track: i.track      }), ni = null    }, 30 * 1e3)  }}

Utilities: persistent anonymous ID

public/utils.js
function Ze() {  return new Promise(async e => {    const t = await E(["anonymousId"]);    if (t.anonymousId) e(t.anonymousId);    else {      const o = crypto.randomUUID();      await b({        anonymousId: o      }), e(o)    }  })}
External analytics destination
    • us.i.posthog.com

    PostHog ingestion endpoint that receives the `daily_journal_added` analytics event containing the journal text.

Where it sends data

Destinations our analysis observed Purrfect Pomodoro Timer: Productivity, Time Management & Daily Journal contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • us.i.posthog.com

    Purrfect Pomodoro Timer: Productivity, Time Management & Daily Journal sends data to us.i.posthog.com. 24 other extensions we have analysed send data here.

Updated 30 September 2026aobapnhgpjlldncjopmbbfeoomombhel