Is Simplify Copilot - Autofill job applications, job tracker & AI resumes safe?
Simplify Copilot is medium risk. Dynamic analysis captured 38 POSTs to api.axiom.co in one Simplify Copilot session. Each tracked_input event records the field touched: label, ATS, employer, input type, posting ID, not typed value. On by default via flag `analyticsEvents`.…
Who publishes itSimplify Jobs - no other listings under this identity, 15 shared hostnames
Simplify Jobs - no other listings under this identity, 15 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 15 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Autofill field metadata sent to Axiom analytics on every job form interaction
Dynamic analysis captured 38 POSTs to api.axiom.co in one Simplify Copilot session.
Each tracked_input event records the field touched: label, ATS, employer, input type, posting ID, not typed value.
On by default via flag `analyticsEvents`.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You interact with a field in a job application form.
Any click or keystroke in a tracked input triggers the event.
The extension sends the field label, ATS system, company name, and input metadata to api.axiom.co.
The field value is removed before transmission; the remaining metadata is posted as a tracked_input event to Axiom's ingest API.
HTTP 200. Our dynamic analysis captured 38 requests of this shape in a single session.
- Content-Type
- application/json
- Authorization
- Bearer xaat-e0a585d9-2911-489d-8c83-babd0dc44f28
- X-Axiom-Org-Id
- simplify-qiqd
[ { "labelText": "Why are you a good fit for Simplify", "ATSKey": "Greenhouse", "trackedObj": "simplify:tutorial", "inputTagName": "TEXTAREA", "status": "tracking", "name": "tracked_input" }]- Field labelWhy are you a good fit for Simplify
The text label of the job application form field you interacted with, such as 'Why are you a good fit for this role?'.
- ATS systemGreenhouse
The name of the applicant tracking system used by the employer, identifying which job platform you are applying through.
- Job posting identifiersimplify:tutorial
An internal reference to the specific job posting you are applying for.
- Input element typeTEXTAREA
The HTML element type of the form field (e.g. TEXTAREA, INPUT).
Service worker strips inputValue then forwards the remaining fields to Axiom
// background.bundle.js:50514-50521 const handleTrackInput = async ({ trackedInput: input }) => { const payload = Object.assign({}, input); delete payload.inputValue; // field value removed before sending sendToAxiom({ name: 'tracked_input', event: payload }); return true; };- api.axiom.co
Axiom analytics. Receives tracked_input events for the 'sabre' dataset under org simplify-qiqd (Simplify Jobs Inc.), posted with a hardcoded bearer token in the bundle.
Cover letter HTML is uploaded when saved or used
Saving a cover letter template or using the editor in Simplify Copilot packages the name and HTML content, sent to Simplify's account API.
In testing, the endpoint returned HTTP 401 and Use cover letter stayed disabled with no account.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You use Simplify Copilot's cover letter editor.
The same path is used when you create a template, update a saved cover letter, or choose Use Cover Letter.
The extension sends the cover letter name and HTML content to Simplify's API.
For a newly used cover letter, the request object can also include job tracking context and whether the letter was generated.
- Cover letter nameCover Letter for Product Manager at Acme Labs (illustrative)
This names the letter or template you save, which can identify the job or company you are applying to.
- Cover letter HTML<p>Dear Hiring Manager,</p><p>I am writing to express my interest in the {{JOB_TITLE}} position at {{COMPANY_NAME}}.</p><p>{{COPILOT_GENERATE_BODY}}</p><p>Sincerely,<br/>{{USER_FULL_NAME}}</p>
This is the formatted text of the cover letter you typed, generated, or saved as a template.
- Job tracking contexttrackedObj for an Acme Labs application (illustrative)
This can connect a saved cover letter to the job record active in the extension.
- Generated markertrue
This marks whether the cover letter came from the generator rather than being typed entirely by you.
HTTP 401 Unauthorized; no request body because this was a GET request.
The editor puts cover letter HTML into extension messages
Create template sends html_content
deobfuscated/js/contentScriptMain.bundle.js:68653-68691ee = (0, Ho.useCallback)(async () => { if (Z && !window.confirm("You have unsaved changes to this template. Discard them?")) return; const e = window.prompt("Name for the new template:", "My Template"); if (e && e.trim()) { z(!0); try { vo({ name: "misc", event: { action: "create_cover_letter_template", source: "CoverLetterEditor" } }); const t = (null == m ? void 0 : m.html) && m.html.trim() ? m.html : "<p>Dear Hiring Manager,</p><p>I am writing to express my interest in the {{JOB_TITLE}} position at {{COMPANY_NAME}}.</p><p>{{COPILOT_GENERATE_BODY}}</p><p>Sincerely,<br/>{{USER_FULL_NAME}}</p>", n = { name: e.trim(), html_content: t }, r = await o.runtime.sendMessage({ method: "createCoverLetterTemplate", template: n }); if (!r.ok) return void window.alert(r.error); A(r.template.id), L(r.template), D(r.template.name), B(!1), K([]); const i = r.template.html_content || ""; null == J || J.commands.setContent(i, { emitUpdate: !1 }), g(e => { var t; return hZ(pZ({}, null != e ? e : {}), { html: i, text: null !== (t = null == J ? void 0 : J.getText()) && void 0 !== t ? t : "" }) }), await Y() } finally { z(!1) } }}, [J, null == m ? void 0 : m.html, Y, Z])Use cover letter sends html_content
deobfuscated/js/contentScriptMain.bundle.js:69016-69067"aria-label": "Use cover letter",disabled: !d || !(null == m ? void 0 : m.html),onClick: () => { vo({ name: "misc", event: { action: "fill_cover_letter", source: "CoverLetterEditor" } }); const e = null == m ? void 0 : m.html; if (e) if (U) { const t = (null == l ? void 0 : l.title) ? `Cover Letter for ${l.title}${l.companyName?` at ${l.companyName}`:""}` : "Cover Letter"; o.runtime.sendMessage({ method: "updateCandidateCoverLetter", coverLetterId: U, update: { name: (null != H ? H : t).slice(0, 200), html_content: e } }) } else { const t = (null == l ? void 0 : l.title) ? `Cover Letter for ${l.title}${l.companyName?` at ${l.companyName}`:""}` : "Cover Letter"; o.runtime.sendMessage({ method: "createCandidateCoverLetter", coverLetter: { name: t.slice(0, 200), html_content: e, tracked_obj: (null == l ? void 0 : l.trackedObj) || void 0, generated: $ } }).then(e => { (null == e ? void 0 : e.ok) && p(t => t ? hZ(pZ({}, t), { savedId: e.coverLetter.id, savedName: e.coverLetter.name }) : t) }) } p(m ? hZ(pZ({}, m), { savedId: null != U ? U : m.savedId, savedName: null != H ? H : m.savedName }) : m), C ? null == d || d({ keyPaths: ["coverLetter"], showProgress: !0 }) : null == u || u("coverLetter", { inputFillStatus: "", inputFillMessage: "", inputFillTime: void 0, actionIndex: void 0 }), s("modal/cover-letter-editor")},children: C ? "Fill cover letter" : "Use Cover Letter"The background worker forwards the messages to account API routes
Base API host
deobfuscated/js/background.bundle.js:47345-47352const Y = { BASE: "https://api.simplify.jobs", WITH_CREDENTIALS: !1, TOKEN: void 0, USERNAME: void 0, PASSWORD: void 0, HEADERS: void 0};Cover letter API methods
deobfuscated/js/background.bundle.js:50936-50974static async createCandidateCoverLetter(e) { return await So({ method: "POST", path: "/v2/candidate/me/cover-letter", body: e })}static async updateCandidateCoverLetter(e, t) { return await So({ method: "PUT", path: `/v2/candidate/me/cover-letter/${e}`, body: t })}static async copilotWriteAndSaveCoverLetter(e) { return await So({ method: "POST", path: "/v2/candidate/me/copilot/cover-letter-doc", body: e })}static async getCoverLetterTemplates() { return await So({ method: "GET", path: "/v2/candidate/me/template/cover-letter" })}static async getCoverLetterTemplate(e) { return await So({ method: "GET", path: `/v2/candidate/me/template/cover-letter/${e}` })}static async createCoverLetterTemplate(e) { return await So({ method: "POST", path: "/v2/candidate/me/template/cover-letter", body: e })}Message handlers call API methods
deobfuscated/js/background.bundle.js:100233-100306case "createCoverLetterTemplate": return (async ({ template: e }) => { try { return { ok: !0, template: (await Qo.createCoverLetterTemplate(e)).body } } catch (e) { var t; const n = null == e || null === (t = e.body) || void 0 === t ? void 0 : t.detail; return { ok: !1, error: "string" == typeof n ? n : "Failed to create template" } } })(e);case "updateCandidateCoverLetter": return (async ({ coverLetterId: e, update: t }) => { try { return { ok: !0, coverLetter: (await Qo.updateCandidateCoverLetter(e, t)).body } } catch (e) { var n; const t = null == e || null === (n = e.body) || void 0 === n ? void 0 : n.detail; return { ok: !1, error: "string" == typeof t ? t : "Failed to update cover letter" } } })(e);case "createCandidateCoverLetter": return (async ({ coverLetter: e }) => { try { return { ok: !0, coverLetter: (await Qo.createCandidateCoverLetter(e)).body } } catch (e) { var t; const n = null == e || null === (t = e.body) || void 0 === t ? void 0 : t.detail; return { ok: !1, error: "string" == typeof n ? n : "Failed to create cover letter" } } })(e);- api.simplify.jobs
Simplify Jobs account API that receives candidate cover letter and cover letter template requests.