Is AeroLeads.com - Free B2B Phone Number & Email Finder safe?
Aeroleads.com - v6.3.9 is high risk. When a logged-in user saves a LinkedIn prospect in the AeroLeads panel, the extension reads profile fields and prepares a POST to AeroLeads: name, company, position, location, image URL, page URL. Dynamic capture failed at LinkedIn login.…
Who publishes itAeroLeads - no other listings under this identity
AeroLeads - 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
LinkedIn profiles saved through AeroLeads are posted to its API
When a logged-in user saves a LinkedIn prospect in the AeroLeads panel, the extension reads profile fields and prepares a POST to AeroLeads: name, company, position, location, image URL, page URL.
Dynamic capture failed at LinkedIn login.
You save a LinkedIn prospect while signed in to LinkedIn and AeroLeads.
The behavior did not run in an unauthenticated test session because LinkedIn redirected to login and the extension showed an AeroLeads login form.
The extension reads the LinkedIn profile details and prepares them for the AeroLeads saved-prospect API.
The side panel collects the profile object into a save request after the content script sends it from the LinkedIn tab.
| Field | Value | Why it matters | |
|---|---|---|---|
LinkedIn profile name | Riley Chen (illustrative) | Identifies the person you saved as a prospect. | |
Current company | Acme Robotics (illustrative) | Links that person to an employer shown on the LinkedIn page. | |
Current position | Director of Partnerships (illustrative) | Adds the role or headline shown on the profile. | |
Location | San Francisco Bay Area (illustrative) | Adds the geographic location visible on the profile. | |
LinkedIn profile URL | https://www.linkedin.com/in/riley-chen/ (illustrative) | Ties the saved record back to a specific LinkedIn page. | |
Profile image URL | https://media.licdn.com/dms/image/profile-displayphoto-shrink_200_200/0/1700000000000 (illustrative) | Adds the profile photo URL when the page exposes one. | |
Tab context | LinkedIn profile tab title and URL (illustrative) | Shows which browser tab produced the saved prospect record. |
| Content-Type | application/json |
| Authorization | Bearer token from the signed-in AeroLeads account |
LinkedIn profile extraction and AeroLeads prospect save path
async extractProfileData() {
var r, e, t, o, n;
try {
let i = {
url: this.settings.tab.url,
title: "",
query: "",
location: "",
current_company: "",
current_position: "",
details_str: "",
full_name: "",
img_url: ""
};
const l = this.getRegularProfileContainer(),
a = (l == null ? void 0 : l.querySelector(".mt2.relative")) || l || document;
if (l || document.querySelector("main h1")) {
const c = this.getExpectedProfileName(),
d = c || this.getProfileNameFromContainer(a, c) || this.getText(a, ["h1", "h2", "main h1", "main h2", "h1.text-heading-xlarge"]);
if (d && !this.isGenericLinkedInName(d)) i.title = d, i.query = d, i.full_name = d;
else return !1;
const m = this.getProfileSummaryLines(l || document, i.full_name || i.title || ""),
u = this.getText(l || document, [".text-body-medium.break-words", ".pv-text-details__left-panel .text-body-medium", "div.text-body-medium"]) || m.find(p => !p.includes("·")) || "";
if (u) {
const {
position: p,
company: _
} = this.companyPositionParser(u);
i.current_position = p || u, i.current_company = _
}
const g = document.querySelector('button[aria-label^="Current company:"]') || document.querySelector('[aria-label*="Current company"]'),
y = this.cleanCompanyText(((r = g == null ? void 0 : g.textContent) == null ? void 0 : r.trim()) || "");
if (y && (i.current_company = y), i.current_company == "" || i.current_company == "N/A") {
const p = m.find(_ => _.includes("·"));
i.current_company = (p == null ? void 0 : p.split("·")[0].trim()) || i.current_company
}
if (s.log("BEFORE", i), i.current_company == "" || i.current_company == "N/A") {
const p = document.querySelector('button[aria-label^="Current company:"]');
if (p) {
s.log("GET COMPANY", i);
const _ = ((e = p.textContent) == null ? void 0 : e.trim()) || "";
i.current_company = this.cleanCompanyText(_), s.log("Other currentCompanyElement", _)
} else s.log("GET COMPANY NOT FOUND", i)
}
if (i.current_company == "" || i.current_company == "N/A") {
const p = (t = document.querySelector("#experience")) == null ? void 0 : t.closest("section");
if (p) {
const _ = p.querySelector(".pv-entity__summary-info > h3") || (p == null ? void 0 : p.querySelector("ul > li:nth-of-type(1) > div > div:nth-of-type(2) > div > div > span:nth-of-type(1) > span")) || (p == null ? void 0 : p.querySelector("ul > li:nth-of-type(1) > div > div:nth-of-type(2) > div > a > span span"));
if (_) {
s.log("GET COMPANY 1", i);
const S = ((o = _.textContent) == null ? void 0 : o.trim()) || "";
i.current_company = this.cleanCompanyText(S)
} else s.log("GET COMPANY 1 NOT FOUND", i)
} else s.log("GET COMPANY 1 NOT FOUND", i)
}
if (i.current_company == "" || i.current_company == "N/A") {
const p = document.querySelector('[aria-label*="Current company"]') || document.querySelector(".inline-show-more-text--is-collapsed");
if (p) {
s.log("GET COMPANY 2", i);
const _ = ((n = p.textContent) == null ? void 0 : n.trim()) || "";
i.current_company = this.cleanCompanyText(_), s.log("Other currentCompanyElement", _)
} else s.log("GET COMPANY 2 NOT FOUND", i)
}
i.img_url = this.getImageSrc(l || document, i.full_name || i.title || "") || this.getImageSrc(document, i.full_name || i.title || ""), i.location = this.getText(l || document, [".text-body-small.inline.t-black--light", ".pv-text-details__left-panel .text-body-small", "span.text-body-small"]);
let P = 0;
for (; P < 3 && (i.current_company === "" || i.current_company === "N/A");) i = this.retryGetCompany(i), P++;
return i.current_company !== "NA" && i.title !== "LinkedIn Member" ? this.pageProspect(i) : this.ncPageProspect(i), this.sendProfileData(i, "profile"), !0
}
return !1
} catch (i) {
return s.log("Error in extractProfileData:", i), !1
}
}sendProfileData(r, e) {
try {
chrome.runtime.sendMessage(chrome.runtime.id, {
type: "SP::LINKEDIN_PROFILE_DATA",
payload: {
profile: r,
pageType: e,
tab: this.settings.tab
}
})
} catch (t) {
s.log("Error sending profile data:", t)
}
}const qy = "production",
Ox = {
development: "http://localhost:3000",
staging: "https://aeroleadsmail.com",
production: "https://aeroleads.com"
},
Qt = Ox[qy],
ar = `${Qt}/api`,
const iB = (...e) => Z1(void 0, [...e], function*(t = {}) {
const r = yield we.get(), n = Gp({}, t);
return r && (n.headers = sB(Gp({}, n.headers), {
Authorization: `Bearer ${r}`
})), n
}),
wr = (e, t, r) => Z1(void 0, null, function*() {
const n = (t == null ? void 0 : t.method) || "GET",
a = (t == null ? void 0 : t.headers) || {
"Content-Type": "application/json"
},
s = yield iB({
method: n,
url: e,
headers: a
});
return t != null && t.data && (s.data = t == null ? void 0 : t.data), t != null && t.params && (s.params = t == null ? void 0 : t.params), yield(yield Ue(s)).data
});class UB extends K1 {
constructor(t) {
t || (t = {}), t.url = "prospects", super(t), this.search = r => a0(this, null, function*() {
const n = {
method: "POST",
data: n0({}, r)
};
return yield wr(`${this.getURL(r)}/search`, n)
}), this.autoCreate = r => a0(this, null, function*() {
const n = {
method: "POST",
data: XB(n0({}, r), {
auto: !0
})
};
return yield wr(this.getURL(r), n)
})
}
}
const tn = new UB({});B = g.useCallback(async () => {
try {
if (b || I) {
ce.log("Already navigating or saving, skipping save");
return
}
const z = s.filter(D => !y.get(Ke(D.url)));
if (z.length > 0) {
Z(z);
const D = z.map(T => ({
...T,
status: "adding"
}));
p(D);
const L = new Set(z.map(T => Ke(T.url)));
P(L), x(!0), h("Saving prospects..."), await U(oa({
list_id: e,
data: z
})), ce.log("Save dispatch completed, waiting for status update...", {
count: z.length
})
} else l && !v && !b && (E(!0), h("Loading new page..."), await R("next_page"))
} catch (z) {
ce.log("Error in saveCurrentPage:", z), E(!1), x(!1)
}
}, [l, v, s, y, e, b, I, U, Z, p, R])- aeroleads.com
Receives saved LinkedIn prospect records through the extension API endpoint at /api/prospects.
LinkedIn profile URLs are sent to AeroLeads profile lookup API
Viewing a LinkedIn profile through the AeroLeads side panel sends that profile URL to AeroLeads' profile details API.
The URL can identify the person or company profile viewed and is used for a server-side enrichment lookup.
The user views a LinkedIn profile while using the AeroLeads side panel.
The extension sends the LinkedIn profile URL to AeroLeads' profile details API for server-side lookup.
| Field | Value | Why it matters | |
|---|---|---|---|
LinkedIn profile URL | https://www.linkedin.com/in/example-profile (illustrative) | Identifies the LinkedIn profile being viewed and lets AeroLeads perform a profile lookup. |
Observed during dynamic analysis: the tested session was not logged into AeroLeads, so the profile lookup request was not triggered; the stored evidence shows the lookup runs when an authenticated user requests profile details from the side panel.
Bulk LinkedIn profile enrichment opens minimized windows to scrape profiles.
Bulk LinkedIn profile enrichment opens a minimized, unfocused window and loads each supplied profile URL, injecting a script to read page content: names, jobs, locations, images, company logos, URLs, and tab details.
A logged-in user triggers bulk LinkedIn profile enrichment.
The extension opens a minimized, unfocused window, loads supplied LinkedIn profile URLs, and injects a script to read profile page fields.
| Field | Value | Why it matters | |
|---|---|---|---|
LinkedIn page content | Jane Smith, Example Corp, Sales Director, San Francisco | Profile page content can include a person's name, current company, role, location, profile image, and company logo. | |
LinkedIn profile URL | https://www.linkedin.com/in/jane-smith-123456/ (illustrative) | The URL identifies which LinkedIn profile was loaded for enrichment. | |
Browser tab details | LinkedIn profile tab in minimized enrichment window | Tab context shows which extension-created tab was used to load and process the profile page. |
Dynamic analysis confirmed the static code path from database evidence, while an earlier run could not trigger the behavior because the extension required AeroLeads authentication.
What it can do
Permissions this extension asks for, as declared in version 6.3.9. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to. The current listed version is 6.4.18, which we have not unpacked yet.
Read and change your data on aeroleads.com
https://aeroleads.com/* and 1 more
Read and change your data on linkedin.com
https://linkedin.com/* and 1 more
Read and change your data on google.com
https://*.google.com/*
Store data in your browser
storage
Run its own code inside the pages you visit
scripting
See the address and title of every tab you have open
tabs
Show a panel beside the page
sidePanel
Show you desktop notifications
notifications
Add items to the right-click menu
contextMenus