Is Parcel Journey Updater safe?
Parcel Journey Updater executes JavaScript sent back by its own server inside live Amazon account pages on every automatic update.
On a recurring update cycle the extension posts to its vendor's server and, if the response tells it to fetch a URL, runs eval() on two server-supplied fields (a transform function and a response handler) with full access to the page's DOM, cookies, and jQuery on Amazon tracking and order-detail pages. This gives the vendor's backend the ability to run arbitrary code in an authenticated Amazon session with no code-signing or sandboxing. Separately, the extension stores the user's Amazon account password in plain text in local storage and reads it back to auto-fill the sign-in form.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Its update server can eval() code inside your Amazon session
On every automated update, the content script sends your Amazon page data to the vendor's server and, if told to, runs two server-supplied JavaScript strings with eval() in that page.
No check or signature guards those strings.
You open an Amazon tracking or order-details page that the extension's content script matches.
The next chrome.alarms update cycle then runs automatically, with no click from you.
The content script posts your page data to its own server, then runs two fields from the JSON reply with eval() in your page.
Nothing checks what those fields contain before they run.
The FetchURL branch of responseHandlerAsync(), shipped and readable
case "FetchURL": {
let text = await window.fetch(responseData.NextAddress, {redirect: "manual"})
.then(response => response.text(), () => null);
if (text && responseData.Transform) {
let trans: Function;
eval(`trans = ${responseData.Transform}`);
if (trans)
text = trans(text);
}
if (responseData.FetchResponseHandler) {
let shallReturn: boolean;
eval(responseData.FetchResponseHandler);
if (shallReturn)
return;
}
await sendRequestAsync(undefined, [{TrackingURL: responseData.NextAddress, TrackingPageHtml: text}]);
}
break;| Field | Value | Why it matters | |
|---|---|---|---|
NextStep | "FetchURL" | Tells your browser what to do next. "FetchURL" starts the fetch-then-eval sequence below. | |
NextAddress | "https://tracking.example.com/status" | The URL your browser fetches before the response text is transformed and executed. | |
Transform | "(text) => text.toUpperCase()" | A function body from the server. Your browser compiles it with eval() and calls it on the fetched text. | |
FetchResponseHandler | "shallReturn = true;" | A raw JavaScript string from the server. Your browser runs it with eval(), with cookies and the DOM in scope. |
Copies the shipped FetchURL branch verbatim and feeds it a crafted response, to show the FetchResponseHandler string executing via eval().
// Copied verbatim from the shipped content script's responseHandlerAsync()
// FetchURL branch. Only the network fetch is mocked; the eval() calls below
// are byte-identical to the shipped code.
async function responseHandlerAsync(responseData) {
switch (responseData.NextStep) {
case "FetchURL": {
let text = "mock fetched text";
if (text && responseData.Transform) {
let trans;
eval(`trans = ${responseData.Transform}`);
if (trans) text = trans(text);
}
if (responseData.FetchResponseHandler) {
let shallReturn;
eval(responseData.FetchResponseHandler);
if (shallReturn) return text;
}
return text;
}
}
}
// A stand-in for a compromised or malicious AddInfo2 response.
const craftedResponse = {
NextStep: "FetchURL",
NextAddress: "https://example.com/",
Transform: "(t) => t.toUpperCase()",
FetchResponseHandler: "globalThis.POC_RCE_CONFIRMED = true; shallReturn = true;",
};
responseHandlerAsync(craftedResponse).then(() => {
console.log(
globalThis.POC_RCE_CONFIRMED
? "POC_RCE_CONFIRMED: the FetchResponseHandler string executed via eval()."
: "eval() did not run the injected handler.",
);
});
- 1Save as eval_rce_repro.js.
- 2Run: node eval_rce_repro.js.
- 3Confirm it prints POC_RCE_CONFIRMED, proving the server-supplied string ran.
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
What it can do
Permissions this extension asks for, as declared in version 0.0.1.9. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on infinityds.app
https://*.infinityds.app/*
Schedule its own background tasks
alarms
Store data in your browser
storage
Store an unlimited amount of data in your browser
unlimitedStorage
Where it sends data
Destinations our analysis observed Parcel Journey Updater 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.
- www.infinityds.app
Parcel Journey Updater sends data to www.infinityds.app. No other extension we have analysed sends data here.