Is Careerflow AI Job Application Tracker, ATS Resume Checker, Autofill & more safe?
Careerflow is high risk. The extension requests Careerflow config endpoints for selectors, profile selectors, form selectors, data paths, and settings after visiting LinkedIn jobs. Shipped code stores these rules to pick which elements are read on matching pages.…
Who publishes itcareerflow.ai - no other listings under this identity
careerflow.ai - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Remote selector rules control page data extraction
The extension requests Careerflow config endpoints for selectors, profile selectors, form selectors, data paths, and settings after visiting LinkedIn jobs.
Shipped code stores these rules to pick which elements are read on matching pages.
You open a job or profile page with the extension enabled.
The extension loads server-provided selector rules and uses matching rules to read page content.
| Field | Value | Why it matters | |
|---|---|---|---|
Selector endpoint | https://us-central1-faang-path.cloudfunctions.net/faangpathV2/misc/selectors | Tells the extension where to load rules that decide which page text can be read. | |
Site matcher | linkedin_com_jobs_search_collections | Matches the current page to a rule set, so only selected sites and layouts are processed. | |
DOM selector set | websiteSelectors.selectors.description | Lists the page elements the extension can read once a site rule matches. | |
Version controls | versionControl.selectors | Lets the backend change which selector version the extension should use. |
The selector and configuration responses are kept in local browser storage so later page processing can use them without another prompt.
chrome.storage.local keys 'selectors', 'profileSelectors', 'formSelectors', 'extensionConfig'{
"selectors": "res.data.content from /misc/selectors or selectors CDN",
"formSelectors": "res.data.content from /misc/formSelectors when form-data features are enabled",
"extensionConfig": "res.data.content from /misc/extensionConfig",
"profileSelectors": "res.data.content from /misc/profileSelectors or bundled fallback"
}Shipped code fetches remote selectors and applies them to the DOM
var fetchSelectorsViaCdnOrApi = function (filename, apiPath, expectedVersion) { return MiscService_awaiter(void 0, void 0, void 0, function () {
var body, _a;
return MiscService_generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, isSelectorsCdnEnabled()];
case 1:
if (!_b.sent()) return [3 /*break*/, 5];
_b.label = 2;
case 2:
_b.trys.push([2, 4, , 5]);
return [4 /*yield*/, fetchSelectorsJson(filename, expectedVersion)];
case 3:
body = _b.sent();
return [2 /*return*/, wrapAsAxiosResponse(body)];
case 4:
_a = _b.sent();
return [3 /*break*/, 5];
case 5: return [2 /*return*/, utils_axios.get(apiPath)];
}
});
}); };
var getExtensionConfig = function () {
return utils_axios.get("".concat(miscApiPath, "/extensionConfig"));
};
var getSelectors = function (expectedVersion) {
return fetchSelectorsViaCdnOrApi(SELECTOR_FILES.selectors, "".concat(miscApiPath, "/selectors"), expectedVersion);
};
var getProfileSelectors = function (expectedVersion) {
return fetchSelectorsViaCdnOrApi(SELECTOR_FILES.profileSelectors, "".concat(miscApiPath, "/profileSelectors"), expectedVersion);
};
var getFormSelectors = function (expectedVersion) {
return fetchSelectorsViaCdnOrApi(SELECTOR_FILES.formSelectors, "".concat(miscApiPath, "/formSelectors"), expectedVersion);
};
var getUserDataPath = function () {
return utils_axios.get("".concat(miscApiPath, "/userDataPath"));
};
var MiscService = {
getExtensionConfig: getExtensionConfig,
getSelectors: getSelectors,
getProfileSelectors: getProfileSelectors,
getFormSelectors: getFormSelectors,
getUserDataPath: getUserDataPath,
};var extractAndTransformJobDetails = function extractAndTransformJobDetails(tabUrl, selectors) {
var document = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : document;
try {
var baseDocument = document;
// Find website selectors
var websiteSelectors = selectors === null || selectors === void 0 ? void 0 : selectors.find(function (data) {
return (data === null || data === void 0 ? void 0 : data.id) && safeUrlMatch(tabUrl, data.id) && (data !== null && data !== void 0 && data.is_ai_generated ? data === null || data === void 0 ? void 0 : data.is_active : true);
});
if (!websiteSelectors) {
return 'Site Not Supported';
}
var documentToExtract = baseDocument;
if (websiteSelectors !== null && websiteSelectors !== void 0 && websiteSelectors.iframeSelector) {
var iframeDoc = getIframeDocument(websiteSelectors.iframeSelector);
if (iframeDoc) {
documentToExtract = iframeDoc;
}
}
// EXTRACT
var extractor = getExtractor(websiteSelectors.name);
var extractedDataFromWebsite = extractor.extract(websiteSelectors.selectors, documentToExtract);
// Treat empty or literal "undefined" as missing for fallback
var descriptionMissingStandalone = !(extractedDataFromWebsite !== null && extractedDataFromWebsite !== void 0 && extractedDataFromWebsite.description) || String(extractedDataFromWebsite.description).trim().toLowerCase() === 'undefined';
// Fallback for LinkedIn search/collections pages:
// sometimes the job details are rendered outside the interop iframe.
if (websiteSelectors !== null && websiteSelectors !== void 0 && websiteSelectors.iframeSelector && websiteSelectors.name === 'linkedin_com_jobs_search_collections' && (descriptionMissingStandalone || !(extractedDataFromWebsite !== null && extractedDataFromWebsite !== void 0 && extractedDataFromWebsite.company) || !(extractedDataFromWebsite !== null && extractedDataFromWebsite !== void 0 && extractedDataFromWebsite.role) || !(extractedDataFromWebsite !== null && extractedDataFromWebsite !== void 0 && extractedDataFromWebsite.location))) {
try {
var fallbackExtracted = extractor.extract(websiteSelectors.selectors, baseDocument);
var fallbackDesc = fallbackExtracted !== null && fallbackExtracted !== void 0 && fallbackExtracted.description && String(fallbackExtracted.description).trim().toLowerCase() !== 'undefined' ? fallbackExtracted.description : null;
if (descriptionMissingStandalone && fallbackDesc) {
extractedDataFromWebsite.description = fallbackDesc;
}
if (!extractedDataFromWebsite.company && fallbackExtracted !== null && fallbackExtracted !== void 0 && fallbackExtracted.company) {
extractedDataFromWebsite.company = fallbackExtracted.company;
}
if (!extractedDataFromWebsite.role && fallbackExtracted !== null && fallbackExtracted !== void 0 && fallbackExtracted.role) {
extractedDataFromWebsite.role = fallbackExtracted.role;
}
if (!extractedDataFromWebsite.location && fallbackExtracted !== null && fallbackExtracted !== void 0 && fallbackExtracted.location) {
extractedDataFromWebsite.location = fallbackExtracted.location;
}
} catch (err) {
// LinkedIn search/collections fallback is best-effort.
}
}
// TRANSFORM
var transformer = getTransformer(websiteSelectors.name);
if (!transformer) {
return {};
}
var transformedData = transformer.transform(extractedDataFromWebsite);
if (!transformedData) {
return {};
}
var finalData = new JobDetailToModelTransformer().transform(transformedData);
// Add company name if available
var companyName = websiteSelectors === null || websiteSelectors === void 0 ? void 0 : websiteSelectors.company_name;
if (companyName) {
try {
finalData.company = companyName;
finalData.companyPayload = extractAndTransformJobDetails_objectSpread(extractAndTransformJobDetails_objectSpread({}, finalData.companyPayload), {}, {
id: companyName,
name: companyName
});
} catch (err) {
// Setting company name is best-effort.
}
}
return finalData;
} catch (err) {
return {};
}
};- us-central1-faang-path.cloudfunctions.net
Careerflow Cloud Functions host serving misc selector and configuration endpoints.
- app.careerflow.ai
Careerflow web app host used as the CDN base for static selector JSON files.
Referral cookie read during upgrade checkout
The Careerflow upgrade flow asks the extension for the `rewardful.referral` cookie from careerflow.ai.
The background reads it via the cookies API so checkout includes it as `client_reference_id`.
Prior analysis missed it; never triggered.
When you start an upgrade checkout flow, the page asks the extension for a Careerflow referral identifier.
The background process reads the `rewardful.referral` cookie for Careerflow and returns its value to the requesting page code.
| Field | Value | Why it matters | |
|---|---|---|---|
Careerflow referral cookie | rewardful.referral=%7B%22id%22%3A%22ref_7J8K2M%22%7D (illustrative) | This can connect the checkout flow to the referral source stored for your Careerflow browser session. | |
Referral ID | ref_7J8K2M (illustrative) | This is the decoded identifier that the checkout flow uses as a customer reference. | |
Checkout reference field | client_reference_id=ref_7J8K2M (illustrative) | This places the referral identifier into the payment checkout request. | |
Success page | https://careerflow.ai/thank-you-premium | This is where the checkout flow sends you after the payment provider flow completes. |
| When | You did | Extension did |
|---|---|---|
| same action | user You click an upgrade plan. | content_script The page code sends `getRewardfulClientId` to the extension. |
| message response | content_script The content script asks for the referral identifier. | service_worker The background process reads the Careerflow referral cookie. |
| after response | service_worker The background process returns the cookie value. | content_script The page code decodes the ID and adds it to the checkout request. |
Cookie read and checkout reference code
if (msg.getRewardfulClientId) {
chrome.cookies.get({
url: 'https://www.careerflow.ai',
name: 'rewardful.referral'
}).then((res) => {
sendResponse(res?.value);
}).catch(() => {
sendResponse(undefined);
});
return true;
}async function handleSubscribe(priceId) {
chrome.runtime.sendMessage({
analytics: {
eventAction: 'Go to stripe payments page for upgrade'
}
});
setPaymentLoading(true);
chrome.runtime.sendMessage({ getRewardfulClientId: true }, (res) => {
const referenceId = res ? JSON.parse(decodeURIComponent(res)).id : undefined;
utils_axios.post(stripeCheckoutApiPath, {
price: priceId,
success_url: 'https://careerflow.ai/thank-you-premium',
client_reference_id: referenceId
}).then((res) => {
window.open(res.data.checkout_session.url);
}).finally(() => {
setPaymentLoading(false);
closeModal();
});
});
}