From e301549d7506c8c380bef6af9b9feac2e51ed066 Mon Sep 17 00:00:00 2001 From: zhangxin11112342 Date: Wed, 28 Aug 2024 10:12:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DCVE-2024-3172?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangxin11112342 --- front_end/core/common/ParsedURL.ts | 8 ++++++++ front_end/core/sdk/DebuggerModel.ts | 2 +- front_end/core/sdk/NetworkRequest.ts | 2 +- front_end/core/sdk/Script.ts | 2 +- front_end/core/sdk/SourceMap.ts | 2 +- .../models/bindings/DebuggerLanguagePlugins.ts | 3 ++- front_end/models/bindings/ResourceMapping.ts | 2 +- front_end/models/issues_manager/CookieIssue.ts | 14 ++++++++------ front_end/models/logs/NetworkLog.ts | 2 +- front_end/models/persistence/Automapping.ts | 4 ++-- .../persistence/NetworkPersistenceManager.ts | 2 +- front_end/models/persistence/PersistenceActions.ts | 2 +- front_end/models/persistence/PersistenceUtils.ts | 4 ++-- .../application/components/BackForwardCacheView.ts | 3 ++- front_end/panels/console/ConsoleContextSelector.ts | 2 +- front_end/panels/console/ConsoleFormat.ts | 5 ++++- front_end/panels/coverage/CoverageModel.ts | 2 +- .../panels/snippets/ScriptSnippetFileSystem.ts | 4 ++-- front_end/panels/timeline/TimelineUIUtils.ts | 4 ++-- front_end/ui/components/chrome_link/ChromeLink.ts | 5 +++-- front_end/ui/legacy/components/utils/Linkifier.ts | 4 ++-- .../front_end/ui/components/ChromeLink_test.ts | 3 ++- 22 files changed, 49 insertions(+), 32 deletions(-) diff --git a/front_end/core/common/ParsedURL.ts b/front_end/core/common/ParsedURL.ts index 37c79c85..addb1883 100644 --- a/front_end/core/common/ParsedURL.ts +++ b/front_end/core/common/ParsedURL.ts @@ -64,6 +64,14 @@ export function normalizePath(path: string): string { return normalizedPath; } +export function schemeIs(url: Platform.DevToolsPath.UrlString, scheme: string): boolean { + try { + return (new URL(url)).protocol === scheme; + } catch (e) { + return false; + } +} + /** * File paths in DevTools that are represented either as unencoded absolute or relative paths, or encoded paths, or URLs. * @example diff --git a/front_end/core/sdk/DebuggerModel.ts b/front_end/core/sdk/DebuggerModel.ts index 6251204b..393c7082 100644 --- a/front_end/core/sdk/DebuggerModel.ts +++ b/front_end/core/sdk/DebuggerModel.ts @@ -456,7 +456,7 @@ export class DebuggerModel extends SDKModel { condition?: BackendCondition): Promise { // Convert file url to node-js path. let urlRegex; - if (this.target().type() === Type.Node && url.startsWith('file://')) { + if (this.target().type() === Type.Node && Common.ParsedURL.schemeIs(url, 'file:')) { const platformPath = Common.ParsedURL.ParsedURL.urlToRawPathString(url, Host.Platform.isWin()); urlRegex = `${Platform.StringUtilities.escapeForRegExp(platformPath)}|${Platform.StringUtilities.escapeForRegExp(url)}`; diff --git a/front_end/core/sdk/NetworkRequest.ts b/front_end/core/sdk/NetworkRequest.ts index 49c7c2c1..0c4c8786 100644 --- a/front_end/core/sdk/NetworkRequest.ts +++ b/front_end/core/sdk/NetworkRequest.ts @@ -435,7 +435,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper i // If a page resulted in an error, the browser will navigate to an internal error page // hosted at 'chrome-error://...'. In this case, skip the frame navigated event to preserve // the network log. - if (mainFrame.url !== mainFrame.unreachableUrl() && mainFrame.url.startsWith('chrome-error://')) { + if (mainFrame.url !== mainFrame.unreachableUrl() && Common.ParsedURL.schemeIs(mainFrame.url, 'chrome-error:')) { return; } diff --git a/front_end/models/persistence/Automapping.ts b/front_end/models/persistence/Automapping.ts index 5babaeeb..2e084f25 100644 --- a/front_end/models/persistence/Automapping.ts +++ b/front_end/models/persistence/Automapping.ts @@ -185,7 +185,7 @@ export class Automapping { if (this.interceptors.some(interceptor => interceptor(networkSourceCode))) { return Promise.resolve(); } - if (networkSourceCode.url().startsWith('wasm://')) { + if (Common.ParsedURL.schemeIs(networkSourceCode.url(), 'wasm:')) { return Promise.resolve(); } const createBindingPromise = @@ -318,7 +318,7 @@ export class Automapping { private createBinding(networkSourceCode: Workspace.UISourceCode.UISourceCode): Promise { const url = networkSourceCode.url(); - if (url.startsWith('file://') || url.startsWith('snippet://')) { + if (Common.ParsedURL.schemeIs(url, 'file:') || Common.ParsedURL.schemeIs(url, 'snippet:')) { const fileSourceCode = this.fileSystemUISourceCodes.get(url); const status = fileSourceCode ? new AutomappingStatus(networkSourceCode, fileSourceCode, false) : null; return Promise.resolve(status); diff --git a/front_end/models/persistence/NetworkPersistenceManager.ts b/front_end/models/persistence/NetworkPersistenceManager.ts index afe49122..a88db584 100644 --- a/front_end/models/persistence/NetworkPersistenceManager.ts +++ b/front_end/models/persistence/NetworkPersistenceManager.ts @@ -430,7 +430,7 @@ export class NetworkPersistenceManager extends Common.ObjectWrapper.ObjectWrappe } private canHandleNetworkUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean { - return this.activeInternal && !uiSourceCode.url().startsWith('snippet://'); + return this.activeInternal && !Common.ParsedURL.schemeIs(uiSourceCode.url(), 'snippet:'); } private async networkUISourceCodeAdded(uiSourceCode: Workspace.UISourceCode.UISourceCode): Promise { diff --git a/front_end/models/persistence/PersistenceActions.ts b/front_end/models/persistence/PersistenceActions.ts index 072b0c3a..4ef255d2 100644 --- a/front_end/models/persistence/PersistenceActions.ts +++ b/front_end/models/persistence/PersistenceActions.ts @@ -92,7 +92,7 @@ export class ContextMenuProvider implements UI.ContextMenu.Provider { const binding = uiSourceCode && PersistenceImpl.instance().binding(uiSourceCode); const fileURL = binding ? binding.fileSystem.contentURL() : contentProvider.contentURL(); - if (fileURL.startsWith('file://')) { + if (Common.ParsedURL.schemeIs(fileURL, 'file:')) { const path = Common.ParsedURL.ParsedURL.urlToRawPathString(fileURL, Host.Platform.isWin()); contextMenu.revealSection().appendItem( i18nString(UIStrings.openInContainingFolder), diff --git a/front_end/models/persistence/PersistenceUtils.ts b/front_end/models/persistence/PersistenceUtils.ts index 71bee4a1..861f5f20 100644 --- a/front_end/models/persistence/PersistenceUtils.ts +++ b/front_end/models/persistence/PersistenceUtils.ts @@ -48,7 +48,7 @@ export class PersistenceUtils { static iconForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): IconButton.Icon.Icon|null { const binding = PersistenceImpl.instance().binding(uiSourceCode); if (binding) { - if (!binding.fileSystem.url().startsWith('file://')) { + if (!Common.ParsedURL.schemeIs(binding.fileSystem.url(), 'file:')) { return null; } const icon = new IconButton.Icon.Icon(); @@ -62,7 +62,7 @@ export class PersistenceUtils { return icon; } if (uiSourceCode.project().type() !== Workspace.Workspace.projectTypes.FileSystem || - !uiSourceCode.url().startsWith('file://')) { + !Common.ParsedURL.schemeIs(uiSourceCode.url(), 'file:')) { return null; } diff --git a/front_end/panels/application/components/BackForwardCacheView.ts b/front_end/panels/application/components/BackForwardCacheView.ts index 86916ef4..27cb69c1 100644 --- a/front_end/panels/application/components/BackForwardCacheView.ts +++ b/front_end/panels/application/components/BackForwardCacheView.ts @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import * as Common from '../../../core/common/common.js'; import type * as Platform from '../../../core/platform/platform.js'; import * as i18n from '../../../core/i18n/i18n.js'; import * as Buttons from '../../../ui/components/buttons/buttons.js'; @@ -286,7 +287,7 @@ export class BackForwardCacheView extends HTMLElement { } const isTestRunning = (this.#screenStatus === ScreenStatusType.Running); // Prevent running BFCache test on the DevTools window itself via DevTools on DevTools - const isTestingForbidden = this.#frame.url.startsWith('devtools://'); + const isTestingForbidden = Common.ParsedURL.schemeIs(this.#frame.url, 'devtools:'); // clang-format off return LitHtml.html` ${this.#renderBackForwardCacheStatus(this.#frame.backForwardCacheDetails.restoredFromCache)} diff --git a/front_end/panels/console/ConsoleContextSelector.ts b/front_end/panels/console/ConsoleContextSelector.ts index 9c01851a..695686ce 100644 --- a/front_end/panels/console/ConsoleContextSelector.ts +++ b/front_end/panels/console/ConsoleContextSelector.ts @@ -229,7 +229,7 @@ export class ConsoleContextSelector implements SDK.TargetManager.SDKModelObserve const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel); frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId); } - if (executionContext.origin.startsWith('chrome-extension://')) { + if (Common.ParsedURL.schemeIs(executionContext.origin, 'chrome-extension:')) { return i18nString(UIStrings.extension); } const sameTargetParentFrame = frame && frame.sameTargetParentFrame(); diff --git a/front_end/panels/console/ConsoleFormat.ts b/front_end/panels/console/ConsoleFormat.ts index 623d030c..af4d629d 100644 --- a/front_end/panels/console/ConsoleFormat.ts +++ b/front_end/panels/console/ConsoleFormat.ts @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import * as Common from '../../core/common/common.js'; +import type * as Platform from '../../core/platform/platform.js'; import type * as SDK from '../../core/sdk/sdk.js'; // VGA color palette @@ -216,7 +218,8 @@ export const updateStyle = (currentStyle: Map match[1]); - if (potentialUrls.some(potentialUrl => !potentialUrl.startsWith('data:'))) { + if (potentialUrls.some( + potentialUrl => !Common.ParsedURL.schemeIs(potentialUrl as Platform.DevToolsPath.UrlString, 'data:'))) { continue; } currentStyle.set(property, { diff --git a/front_end/panels/coverage/CoverageModel.ts b/front_end/panels/coverage/CoverageModel.ts index 664fe91c..43f14d11 100644 --- a/front_end/panels/coverage/CoverageModel.ts +++ b/front_end/panels/coverage/CoverageModel.ts @@ -469,7 +469,7 @@ export class CoverageModel extends SDK.SDKModel.SDKModel { continue; } const url = urlInfo.url(); - if (url.startsWith('extensions::') || url.startsWith('chrome-extension://')) { + if (url.startsWith('extensions::') || Common.ParsedURL.schemeIs(url, 'chrome-extension:')) { continue; } result.push(...await urlInfo.entriesForExport()); diff --git a/front_end/panels/snippets/ScriptSnippetFileSystem.ts b/front_end/panels/snippets/ScriptSnippetFileSystem.ts index c3b8104e..49377f55 100644 --- a/front_end/panels/snippets/ScriptSnippetFileSystem.ts +++ b/front_end/panels/snippets/ScriptSnippetFileSystem.ts @@ -143,7 +143,7 @@ export class SnippetFileSystem extends Persistence.PlatformFileSystem.PlatformFi } export async function evaluateScriptSnippet(uiSourceCode: Workspace.UISourceCode.UISourceCode): Promise { - if (!uiSourceCode.url().startsWith('snippet://')) { + if (!Common.ParsedURL.schemeIs(uiSourceCode.url(), 'snippet:')) { return; } @@ -199,7 +199,7 @@ export async function evaluateScriptSnippet(uiSourceCode: Workspace.UISourceCode } export function isSnippetsUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean { - return uiSourceCode.url().startsWith('snippet://'); + return Common.ParsedURL.schemeIs(uiSourceCode.url(), 'snippet:'); } export function isSnippetsProject(project: Workspace.Workspace.Project): boolean { diff --git a/front_end/panels/timeline/TimelineUIUtils.ts b/front_end/panels/timeline/TimelineUIUtils.ts index 40ffdc0a..e5240923 100644 --- a/front_end/panels/timeline/TimelineUIUtils.ts +++ b/front_end/panels/timeline/TimelineUIUtils.ts @@ -3254,8 +3254,8 @@ export class TimelineUIUtils { if (!trimAt) { trimAt = 30; } - return url.startsWith('about:') ? `"${Platform.StringUtilities.trimMiddle(frame.name, trimAt)}"` : - frame.url.trimEnd(trimAt); + return Common.ParsedURL.schemeIs(url, 'about:') ? `"${Platform.StringUtilities.trimMiddle(frame.name, trimAt)}"` : + frame.url.trimEnd(trimAt); } } diff --git a/front_end/ui/components/chrome_link/ChromeLink.ts b/front_end/ui/components/chrome_link/ChromeLink.ts index caab8e44..2990e00a 100644 --- a/front_end/ui/components/chrome_link/ChromeLink.ts +++ b/front_end/ui/components/chrome_link/ChromeLink.ts @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import * as Common from '../../../core/common/common.js'; import * as Platform from '../../../core/platform/platform.js'; import * as SDK from '../../../core/sdk/sdk.js'; import * as LitHtml from '../../lit-html/lit-html.js'; @@ -28,8 +29,8 @@ export class ChromeLink extends HTMLElement { void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } - set href(href: string) { - if (!href.startsWith('chrome://')) { + set href(href: Platform.DevToolsPath.UrlString) { + if (!Common.ParsedURL.schemeIs(href, 'chrome:')) { throw new Error('ChromeLink href needs to start with \'chrome://\''); } this.#href = href; diff --git a/front_end/ui/legacy/components/utils/Linkifier.ts b/front_end/ui/legacy/components/utils/Linkifier.ts index 3801caa3..2f4db5f5 100644 --- a/front_end/ui/legacy/components/utils/Linkifier.ts +++ b/front_end/ui/legacy/components/utils/Linkifier.ts @@ -516,7 +516,7 @@ export class Linkifier implements SDK.TargetManager.Observer { const preventClick = options.preventClick; const maxLength = options.maxLength || UI.UIUtils.MaxLengthForDisplayedURLs; const bypassURLTrimming = options.bypassURLTrimming; - if (!url || url.trim().toLowerCase().startsWith('javascript:')) { + if (!url || Common.ParsedURL.schemeIs(url, 'javascript:')) { const element = document.createElement('span'); if (className) { element.className = className; @@ -948,7 +948,7 @@ export class ContentProviderContextMenuProvider implements UI.ContextMenu.Provid return; } - if (!contentUrl.startsWith('file://')) { + if (!Common.ParsedURL.schemeIs(contentUrl, 'file:')) { contextMenu.revealSection().appendItem( UI.UIUtils.openLinkExternallyLabel(), () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( diff --git a/test/unittests/front_end/ui/components/ChromeLink_test.ts b/test/unittests/front_end/ui/components/ChromeLink_test.ts index d84928f1..51c15899 100644 --- a/test/unittests/front_end/ui/components/ChromeLink_test.ts +++ b/test/unittests/front_end/ui/components/ChromeLink_test.ts @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import type * as Platform from '../../../../../front_end/core/platform/platform.js'; import * as ChromeLink from '../../../../../front_end/ui/components/chrome_link/chrome_link.js'; import * as Coordinator from '../../../../../front_end/ui/components/render_coordinator/render_coordinator.js'; import * as LitHtml from '../../../../../front_end/ui/lit-html/lit-html.js'; @@ -51,7 +52,7 @@ describe('ChromeLink', () => { it('throws an error when given a non-\'chrome://\' URL', async () => { const component = new ChromeLink.ChromeLink.ChromeLink(); assert.throws(() => { - component.href = 'https://www.example.com'; + component.href = 'https://www.example.com' as Platform.DevToolsPath.UrlString; }, 'ChromeLink href needs to start with \'chrome://\''); }); }); -- Gitee