Security Alert: Malware Risk Confirmed
Motion DevTools
ID: mnbliiaiiflhmnndmoidhddombbmgcdk
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- motion.devView Profile
- Privacy
- Privacy Policy
- Website
- Visit
Inspect, edit and export animations made with CSS and Motion One.
Motion DevTools is a browser extension to inspect, edit and export animations made with CSS and Motion One. 🔍 Inspect: Press record and interact. Detected CSS and Motion One animations will be plotted on a classic timeline interface. Use the playback controls to scrub through and replay your animation from any point. ✍️ Edit: Add, move and remove keyframes. Edit values and easing with custom controls, and your edits will be reflected on the page in real-time. 🚢 Export: Perfected your animation? Hit the export button to instantly generate code. Export any animation into CSS transitions, CSS animations or Motion One.
The extension registers an `onMessageExternal` listener that accepts login payloads (username, email, isPro) from any page whose URL contains the string "motion.dev" — this substring check is insufficient and could be spoofed with a domain like `evil-motion.dev` or a path such as `attacker.com/motion.dev/`. A successful spoof would allow an attacker to overwrite the stored user credentials in `chrome.storage.sync`.
const handleLogin = (message, sender, sendResponse) => { // Only accept messages from motion.dev if (!sender.url || !sender.url.includes("motion.dev")) return; switch (message.type) { case "login": { const { username, email, isPro } = message; chrome.storage.sync.set({ user: { username, isPro, email, verifiedAt: new Date() .getTime(), numRetryAttempts: 0, }, }, () => sendResponse({ success: true })); break; } }};chrome.runtime.onMessageExternal.addListener(handleLogin);The content script runs at `document_start` across all URLs and all frames (`<all_urls>`, `all_frames: true`) and immediately injects `client.js` into the page's main world JavaScript context by appending a `<script>` element. This gives extension-controlled code full access to the page's DOM, JavaScript heap, and any secrets (tokens, form data) present on every website the user visits before the page has loaded any of its own content.
(function() { 'use strict'; var _a; window.__MOTION_BRIDGE_HAS_LOADED = true; /** * Inject client script into the actual webpage */ const script = document.createElement("script"); script.src = chrome.runtime.getURL("js/client.js"); document.documentElement.appendChild(script); (_a = script.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(script);User email and username are transmitted to `https://motion.dev/api/pro/check-subscription` as plaintext URL query parameters on every periodic auth check. Embedding PII in query strings exposes the data in server access logs, browser history, and any intermediate proxies or CDN logs, making it a persistent privacy leak beyond the immediate HTTPS channel.
function checkAuth() { return __awaiter(this, void 0, void 0, function*() { const { user } = yield chrome.storage.sync.get("user"); if (!user || new Date() .getTime() - user.verifiedAt < weekMs) return; try { const response = yield fetch( `https://motion.dev/api/pro/check-subscription?username=${user.username}&email=${user.email}`); const { result } = yield response.json(); if (result) { chrome.storage.sync.set({ user: Object.assign(Object.assign({}, user), { verifiedAt: new Date() .getTime(), numRetryAttempts: 0 }), }); } else { chrome.storage.sync.remove("user"); }The bridge listens for all `window.postMessage` events from the current page and forwards any message with type `login` to the background service worker without validating the page origin. Any script running on the visited page (including third-party scripts and XSS payloads) can craft a `{type: 'login', username: ..., email: ...}` message and have it relayed to the background, potentially overwriting the stored user object in `chrome.storage.sync`.
const handleMessagesFromWebPage = (event) => { if (event.source != window) return; if (!backgroundPort) { connect(); } switch (event.data.type) { /** * Events from client to backend */ case "animationstart": case "clientready": case "login": { backgroundPort.postMessage(event.data); return; } }};window.addEventListener("message", handleMessagesFromWebPage, false);The `externally_connectable` manifest entry permits any page served from localhost on any port and any protocol (http or https) to send messages directly to the extension via `chrome.runtime.sendMessage`. Because the background's `handleLogin` guard only checks whether `sender.url` contains the string `motion.dev`, a localhost dev server (or local malware) can also send a `login` message if it includes `motion.dev` anywhere in its URL structure, allowing arbitrary credential injection into the extension's storage.
{ "externally_connectable": { "matches": [ "https://*.motion.dev/*", "*://localhost/*" ] }}By severity
Versions scanned
Showing 1 of 6 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 1.1.0 | 5 |
Files with findings
3 distinct paths — top paths by unique finding count:
- js/background.js2
- js/bridge.js2
- manifest.json1
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Code Diff
Compare extension code between any two versions.
No comparable text files found between these versions.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.