diff --git a/apps/browser/package.json b/apps/browser/package.json index cec3a9caab..87d78d61b7 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/browser", - "version": "2023.8.3", + "version": "2023.9.0", "scripts": { "build": "webpack", "build:mv3": "cross-env MANIFEST_VERSION=3 webpack", diff --git a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts index a6bff50a19..62c6c9c25a 100644 --- a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts +++ b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts @@ -189,7 +189,7 @@ export class ContextMenuClickedHandler { // we are actually unlocked we will do our best to find a good match of an item to autofill this is useful // in scenarios like unlock on autofill const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); - cipher = ciphers.find((c) => c.reprompt === CipherRepromptType.None); + cipher = ciphers[0]; } else { const ciphers = await this.cipherService.getAllDecrypted(); cipher = ciphers.find((c) => c.id === id); diff --git a/apps/browser/src/autofill/content/autofill.js b/apps/browser/src/autofill/content/autofill.js index 1833c09e15..2f3857d3fa 100644 --- a/apps/browser/src/autofill/content/autofill.js +++ b/apps/browser/src/autofill/content/autofill.js @@ -986,13 +986,18 @@ styleTimeout = 200; /** - * Fll an element `el` using the value `op` from the fill script + * Fill an element `el` using the value `op` from the fill script * @param {HTMLElement} el * @param {string} op */ function fillTheElement(el, op) { var shouldCheck; if (el && null !== op && void 0 !== op && !(el.disabled || el.a || el.readOnly)) { + const tabURLChanged = !fillScript.savedUrls?.some(url => url.startsWith(window.location.origin)) + // Check to make sure the page location didn't change + if (tabURLChanged) { + return; + } switch (markTheFilling && el.form && !el.form.opfilled && (el.form.opfilled = true), el.type ? el.type.toLowerCase() : null) { case 'checkbox': diff --git a/apps/browser/src/autofill/services/insert-autofill-content.service.spec.ts b/apps/browser/src/autofill/services/insert-autofill-content.service.spec.ts index 828d768ca2..0ab74875fb 100644 --- a/apps/browser/src/autofill/services/insert-autofill-content.service.spec.ts +++ b/apps/browser/src/autofill/services/insert-autofill-content.service.spec.ts @@ -108,6 +108,7 @@ describe("InsertAutofillContentService", () => { jest.spyOn(insertAutofillContentService as any, "fillingWithinSandboxedIframe"); jest.spyOn(insertAutofillContentService as any, "userCancelledInsecureUrlAutofill"); jest.spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill"); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged"); jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); insertAutofillContentService.fillForm(fillScript); @@ -119,6 +120,7 @@ describe("InsertAutofillContentService", () => { expect( insertAutofillContentService["userCancelledUntrustedIframeAutofill"] ).not.toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).not.toHaveBeenCalled(); expect(insertAutofillContentService["runFillScriptAction"]).not.toHaveBeenCalled(); }); @@ -128,6 +130,7 @@ describe("InsertAutofillContentService", () => { .mockReturnValue(true); jest.spyOn(insertAutofillContentService as any, "userCancelledInsecureUrlAutofill"); jest.spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill"); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged"); jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); insertAutofillContentService.fillForm(fillScript); @@ -139,6 +142,7 @@ describe("InsertAutofillContentService", () => { expect( insertAutofillContentService["userCancelledUntrustedIframeAutofill"] ).not.toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).not.toHaveBeenCalled(); expect(insertAutofillContentService["runFillScriptAction"]).not.toHaveBeenCalled(); }); @@ -150,6 +154,7 @@ describe("InsertAutofillContentService", () => { .spyOn(insertAutofillContentService as any, "userCancelledInsecureUrlAutofill") .mockReturnValue(true); jest.spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill"); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged"); jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); insertAutofillContentService.fillForm(fillScript); @@ -159,6 +164,7 @@ describe("InsertAutofillContentService", () => { expect( insertAutofillContentService["userCancelledUntrustedIframeAutofill"] ).not.toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).not.toHaveBeenCalled(); expect(insertAutofillContentService["runFillScriptAction"]).not.toHaveBeenCalled(); }); @@ -172,6 +178,7 @@ describe("InsertAutofillContentService", () => { jest .spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill") .mockReturnValue(true); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged").mockReturnValue(false); jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); insertAutofillContentService.fillForm(fillScript); @@ -181,6 +188,31 @@ describe("InsertAutofillContentService", () => { expect( insertAutofillContentService["userCancelledUntrustedIframeAutofill"] ).toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).not.toHaveBeenCalled(); + expect(insertAutofillContentService["runFillScriptAction"]).not.toHaveBeenCalled(); + }); + + it("returns early if the page location origin does not match against any of the cipher saved URLs", () => { + jest + .spyOn(insertAutofillContentService as any, "fillingWithinSandboxedIframe") + .mockReturnValue(false); + jest + .spyOn(insertAutofillContentService as any, "userCancelledInsecureUrlAutofill") + .mockReturnValue(false); + jest + .spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill") + .mockReturnValue(false); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged").mockReturnValue(true); + jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); + + insertAutofillContentService.fillForm(fillScript); + + expect(insertAutofillContentService["fillingWithinSandboxedIframe"]).toHaveBeenCalled(); + expect(insertAutofillContentService["userCancelledInsecureUrlAutofill"]).toHaveBeenCalled(); + expect( + insertAutofillContentService["userCancelledUntrustedIframeAutofill"] + ).toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).toHaveBeenCalled(); expect(insertAutofillContentService["runFillScriptAction"]).not.toHaveBeenCalled(); }); @@ -194,6 +226,7 @@ describe("InsertAutofillContentService", () => { jest .spyOn(insertAutofillContentService as any, "userCancelledUntrustedIframeAutofill") .mockReturnValue(false); + jest.spyOn(insertAutofillContentService as any, "tabURLChanged").mockReturnValue(false); jest.spyOn(insertAutofillContentService as any, "runFillScriptAction"); insertAutofillContentService.fillForm(fillScript); @@ -203,6 +236,7 @@ describe("InsertAutofillContentService", () => { expect( insertAutofillContentService["userCancelledUntrustedIframeAutofill"] ).toHaveBeenCalled(); + expect(insertAutofillContentService["tabURLChanged"]).toHaveBeenCalled(); expect(insertAutofillContentService["runFillScriptAction"]).toHaveBeenCalledTimes(3); expect(insertAutofillContentService["runFillScriptAction"]).toHaveBeenNthCalledWith( 1, diff --git a/apps/browser/src/autofill/services/insert-autofill-content.service.ts b/apps/browser/src/autofill/services/insert-autofill-content.service.ts index 89f644ba6b..4e47e73704 100644 --- a/apps/browser/src/autofill/services/insert-autofill-content.service.ts +++ b/apps/browser/src/autofill/services/insert-autofill-content.service.ts @@ -38,7 +38,8 @@ class InsertAutofillContentService implements InsertAutofillContentServiceInterf !fillScript.script?.length || this.fillingWithinSandboxedIframe() || this.userCancelledInsecureUrlAutofill(fillScript.savedUrls) || - this.userCancelledUntrustedIframeAutofill(fillScript) + this.userCancelledUntrustedIframeAutofill(fillScript) || + this.tabURLChanged(fillScript.savedUrls) ) { return; } @@ -46,6 +47,16 @@ class InsertAutofillContentService implements InsertAutofillContentServiceInterf fillScript.script.forEach(this.runFillScriptAction); } + /** + * Determines if the page URL no longer matches one of the cipher's savedURL domains + * @param {string[] | null} savedUrls + * @returns {boolean} + * @private + */ + private tabURLChanged(savedUrls?: AutofillScript["savedUrls"]): boolean { + return savedUrls && !savedUrls.some((url) => url.startsWith(window.location.origin)); + } + /** * Identifies if the execution of this script is happening * within a sandboxed iframe. diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index b6276b434e..0e75778f26 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.8.3", + "version": "2023.9.0", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index f10ac7f382..fabd611ad9 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -3,7 +3,7 @@ "minimum_chrome_version": "102.0", "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.8.3", + "version": "2023.9.0", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/cli/package.json b/apps/cli/package.json index f3c4a68b6d..153b8d9ce8 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/cli", "description": "A secure and free password manager for all of your devices.", - "version": "2023.8.2", + "version": "2023.9.0", "keywords": [ "bitwarden", "password", diff --git a/apps/cli/src/tools/import.command.ts b/apps/cli/src/tools/import.command.ts index c013d3c6b6..e3f24b960f 100644 --- a/apps/cli/src/tools/import.command.ts +++ b/apps/cli/src/tools/import.command.ts @@ -66,7 +66,7 @@ export class ImportCommand { try { let contents; - if (format === "1password1pux") { + if (format === "1password1pux" && filepath.endsWith(".1pux")) { contents = await CliUtils.extractZipContent(filepath, "export.data"); } else if (format === "protonpass" && filepath.endsWith(".zip")) { contents = await CliUtils.extractZipContent(filepath, "Proton Pass/data.json"); diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 92220c7551..8103f20311 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/desktop", "description": "A secure and free password manager for all of your devices.", - "version": "2023.8.5", + "version": "2023.9.0", "keywords": [ "bitwarden", "password", diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json index 3af376f862..b1b465d26a 100644 --- a/apps/desktop/src/package-lock.json +++ b/apps/desktop/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/desktop", - "version": "2023.8.5", + "version": "2023.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/desktop", - "version": "2023.8.5", + "version": "2023.9.0", "license": "GPL-3.0", "dependencies": { "@bitwarden/desktop-native": "file:../desktop_native" diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json index 0e4bff007f..77e29a988b 100644 --- a/apps/desktop/src/package.json +++ b/apps/desktop/src/package.json @@ -2,7 +2,7 @@ "name": "@bitwarden/desktop", "productName": "Bitwarden", "description": "A secure and free password manager for all of your devices.", - "version": "2023.8.5", + "version": "2023.9.0", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/apps/web/package.json b/apps/web/package.json index 08698b75a3..781d5d7526 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/web-vault", - "version": "2023.8.4", + "version": "2023.9.0", "scripts": { "build:oss": "webpack", "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", diff --git a/apps/web/src/app/tools/import-export/import.component.ts b/apps/web/src/app/tools/import-export/import.component.ts index fb7d1d5501..de2de35777 100644 --- a/apps/web/src/app/tools/import-export/import.component.ts +++ b/apps/web/src/app/tools/import-export/import.component.ts @@ -309,7 +309,7 @@ export class ImportComponent implements OnInit, OnDestroy { } private getFileContents(file: File): Promise { - if (this.format === "1password1pux") { + if (this.format === "1password1pux" && file.name.endsWith(".1pux")) { return this.extractZipContent(file, "export.data"); } if ( diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json index 2136611a2b..008ad22a98 100644 --- a/apps/web/src/locales/zh_CN/messages.json +++ b/apps/web/src/locales/zh_CN/messages.json @@ -142,7 +142,7 @@ "message": "文件夹" }, "newCustomField": { - "message": "新建自定义字段" + "message": "新增自定义字段" }, "value": { "message": "值" @@ -606,13 +606,13 @@ "message": "登录或者创建一个账户来访问您的安全密码库。" }, "loginWithDevice": { - "message": "使用设备登录" + "message": "设备登录" }, "loginWithDeviceEnabledNote": { "message": "设备登录必须在 Bitwarden 应用程序的设置中启用。需要其他登录选项吗?" }, "loginWithMasterPassword": { - "message": "使用主密码登录" + "message": "主密码登录" }, "createAccount": { "message": "创建账户" @@ -791,7 +791,7 @@ "message": "请输入验证器应用程序中的 6 位验证码。" }, "enterVerificationCodeEmail": { - "message": "请输入发送给电子邮件 $EMAIL$ 的 6 位验证码。", + "message": "请输入发送给电子邮件 $EMAIL$ 的 6 位数验证码。", "placeholders": { "email": { "content": "$1", @@ -812,7 +812,7 @@ "message": "记住我" }, "sendVerificationCodeEmailAgain": { - "message": "重发验证码电子邮件" + "message": "再次发送验证码电子邮件" }, "useAnotherTwoStepMethod": { "message": "使用其他两步登录方式" @@ -1104,7 +1104,7 @@ "message": "继续操作将更改您的账户电子邮件地址。这不会更改用于双重身份验证的电子邮件地址。您可以在两步登录设置中更改它。" }, "newEmail": { - "message": "新电子邮件" + "message": "新电子邮件地址" }, "code": { "message": "代码" @@ -1663,7 +1663,7 @@ "message": "单击下面的「保存」按钮,以启用此安全钥匙用于两步登录。" }, "twoFactorU2fProblemReadingTryAgain": { - "message": "读取安全钥匙时出现问题,请再试一次。" + "message": "读取安全钥匙时出现问题,请重试。" }, "twoFactorWebAuthnWarning": { "message": "由于平台限制,无法在所有 Bitwarden 应用程序中使用 WebAuthn。您应该启用另一个两步登录提供程序,以便在 WebAuthn 无法使用时可以访问您的账户。支持的平台有:" @@ -1968,7 +1968,7 @@ } }, "bitwardenFamiliesPlan": { - "message": "Bitwarden 家庭计划。" + "message": "Bitwarden 家庭版计划。" }, "addons": { "message": "附加项目" @@ -2304,7 +2304,7 @@ } }, "planNameFamilies": { - "message": "家庭" + "message": "家庭版" }, "planDescFamilies": { "message": "适用于个人使用,与家人和朋友共享。" @@ -2499,7 +2499,7 @@ "message": "群组" }, "newGroup": { - "message": "新建群组" + "message": "新增群组" }, "addGroup": { "message": "添加群组" @@ -2553,7 +2553,7 @@ "message": "只读" }, "newCollection": { - "message": "新建集合" + "message": "新增集合" }, "addCollection": { "message": "添加集合" @@ -4152,7 +4152,7 @@ "message": "紧急访问已批准" }, "viewDesc": { - "message": "可以查看您拥有的密码库中的所有项目。" + "message": "可以查看您的密码库中的所有项目。" }, "takeover": { "message": "接管" @@ -4646,7 +4646,7 @@ "message": "回收站中超过 30 天的条目将会被自动删除。" }, "trashCleanupWarningSelfHosted": { - "message": "回收站中超过一定时间的项目将会被自动删除。" + "message": "回收站中超过一定时间的条目将会被自动删除。" }, "passwordPrompt": { "message": "主密码重新提示" @@ -4730,7 +4730,7 @@ "message": "错误" }, "accountRecoveryManageUsers": { - "message": "管理用户也必须被授予管理账户恢复的权限" + "message": "授予「管理账户恢复」的权限,同时必须授予「管理用户」的权限" }, "setupProvider": { "message": "提供商设置" @@ -5080,7 +5080,7 @@ "message": "免费 Bitwarden 家庭" }, "sponsoredFamiliesEligible": { - "message": "您和您的家人可使用免费的 Bitwarden 家庭版计划。即使您不在公司上班,您也可以使用个人电子邮件兑换此计划,以保护您的数据安全。" + "message": "您和您的家人有资格享受免费的 Bitwarden 家庭版计划。即使您不在公司上班,您也可以使用个人电子邮件兑换此计划,以保护您的数据安全。" }, "sponsoredFamiliesEligibleCard": { "message": "立即兑换免费的 Bitwarden 家庭版计划,即使您不在公司上班也能确保您的数据安全。" @@ -5374,19 +5374,19 @@ "message": "计费同步令牌" }, "active": { - "message": "生效中" + "message": "已生效" }, "inactive": { "message": "已失效" }, "sentAwaitingSync": { - "message": "已发送(正在等待同步)" + "message": "已发送(等待同步)" }, "sent": { - "message": "发送" + "message": "已发送" }, "requestRemoved": { - "message": "已移除(正在等待同步)" + "message": "已移除(等待同步)" }, "requested": { "message": "已请求" @@ -5614,7 +5614,7 @@ "message": "启用设备验证" }, "deviceVerificationDesc": { - "message": "登录未识别的设备时,验证码会发送到您的电子邮件地址" + "message": "登录未识别的设备时,验证码会发送到您的电子邮箱" }, "updatedDeviceVerification": { "message": "已更新设备验证" @@ -6230,7 +6230,7 @@ "description": "Toast message after deleting one or multiple access tokens." }, "noAccessTokenSelected": { - "message": "未选中任何要撤销的访问令牌", + "message": "未选中任何要吊销的访问令牌", "description": "Toast error message after trying to delete access tokens but not selecting any access tokens." }, "submenu": { diff --git a/libs/components/src/link/link.directive.ts b/libs/components/src/link/link.directive.ts index b2e551ddef..0841388a94 100644 --- a/libs/components/src/link/link.directive.ts +++ b/libs/components/src/link/link.directive.ts @@ -58,7 +58,6 @@ const commonStyles = [ "before:tw-rounded-md", "before:tw-transition", "focus-visible:before:tw-ring-2", - "focus-visible:before:tw-ring-text-contrast", "focus-visible:tw-z-10", ]; diff --git a/libs/importer/src/models/import-options.ts b/libs/importer/src/models/import-options.ts index 2afe801d20..03c4e72e04 100644 --- a/libs/importer/src/models/import-options.ts +++ b/libs/importer/src/models/import-options.ts @@ -12,7 +12,7 @@ export const featuredImportOptions = [ { id: "keepass2xml", name: "KeePass 2 (xml)" }, { id: "lastpasscsv", name: "LastPass (csv)" }, { id: "safaricsv", name: "Safari and macOS (csv)" }, - { id: "1password1pux", name: "1Password (1pux)" }, + { id: "1password1pux", name: "1Password (1pux/json)" }, ] as const; export const regularImportOptions = [ diff --git a/package-lock.json b/package-lock.json index 640a45b239..935c06c99c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -190,11 +190,11 @@ }, "apps/browser": { "name": "@bitwarden/browser", - "version": "2023.8.3" + "version": "2023.9.0" }, "apps/cli": { "name": "@bitwarden/cli", - "version": "2023.8.2", + "version": "2023.9.0", "license": "GPL-3.0-only", "dependencies": { "@koa/multer": "3.0.2", @@ -230,7 +230,7 @@ }, "apps/desktop": { "name": "@bitwarden/desktop", - "version": "2023.8.5", + "version": "2023.9.0", "hasInstallScript": true, "license": "GPL-3.0" }, @@ -260,7 +260,7 @@ }, "apps/web": { "name": "@bitwarden/web-vault", - "version": "2023.8.4" + "version": "2023.9.0" }, "libs/angular": { "name": "@bitwarden/angular",