[PM-3574] Fix leak of login credentials to foreign origin due to race condition during autofill (#6700)

* [PM-3574] Fix leak of login credentials to foreign origin due to race condition during autofill

* [PM-3574] Adding a temporary artificial delay to facilitate QA testing

* [PM-3574] Adding a temporary artificial delay to facilitate QA testing

* [PM-4590] Cached Page Details of Formless Input Fields Breaks Autofill

* [PM-3574] Reworking implementation to take into account the page details url

* [PM-3574] Fixing jest tests

* [PM-3574] Fixing jest tests

* [PM-3574] Removing 5 second delay on autofill
This commit is contained in:
Cesar Gonzalez 2023-11-15 13:17:11 -06:00 committed by GitHub
parent 90bad00cb5
commit 8e047f615e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 8 deletions

View File

@ -5,6 +5,8 @@ type AutofillExtensionMessage = {
tab?: chrome.tabs.Tab; tab?: chrome.tabs.Tab;
sender?: string; sender?: string;
fillScript?: AutofillScript; fillScript?: AutofillScript;
url?: string;
pageDetailsUrl?: string;
}; };
type AutofillExtensionMessageHandlers = { type AutofillExtensionMessageHandlers = {

View File

@ -73,13 +73,36 @@ describe("AutofillInit", () => {
}); });
describe("fillForm", () => { describe("fillForm", () => {
it("will call the InsertAutofillContentService to fill the form", () => { beforeEach(() => {
const fillScript = mock<AutofillScript>();
jest jest
.spyOn(bitwardenAutofillInit.insertAutofillContentService, "fillForm") .spyOn(bitwardenAutofillInit.insertAutofillContentService, "fillForm")
.mockImplementation(); .mockImplementation();
});
bitwardenAutofillInit.fillForm(fillScript); it("skips calling the InsertAutofillContentService and does not fill the form if the url to fill is not equal to the current tab url", () => {
const fillScript = mock<AutofillScript>();
const message = {
command: "fillForm",
fillScript,
pageDetailsUrl: "https://a-different-url.com",
};
bitwardenAutofillInit.fillForm(message);
expect(bitwardenAutofillInit.insertAutofillContentService.fillForm).not.toHaveBeenCalledWith(
fillScript
);
});
it("will call the InsertAutofillContentService to fill the form", () => {
const fillScript = mock<AutofillScript>();
const message = {
command: "fillForm",
fillScript,
pageDetailsUrl: window.location.href,
};
bitwardenAutofillInit.fillForm(message);
expect(bitwardenAutofillInit.insertAutofillContentService.fillForm).toHaveBeenCalledWith( expect(bitwardenAutofillInit.insertAutofillContentService.fillForm).toHaveBeenCalledWith(
fillScript fillScript

View File

@ -1,5 +1,4 @@
import AutofillPageDetails from "../models/autofill-page-details"; import AutofillPageDetails from "../models/autofill-page-details";
import AutofillScript from "../models/autofill-script";
import CollectAutofillContentService from "../services/collect-autofill-content.service"; import CollectAutofillContentService from "../services/collect-autofill-content.service";
import DomElementVisibilityService from "../services/dom-element-visibility.service"; import DomElementVisibilityService from "../services/dom-element-visibility.service";
import InsertAutofillContentService from "../services/insert-autofill-content.service"; import InsertAutofillContentService from "../services/insert-autofill-content.service";
@ -17,7 +16,7 @@ class AutofillInit implements AutofillInitInterface {
private readonly extensionMessageHandlers: AutofillExtensionMessageHandlers = { private readonly extensionMessageHandlers: AutofillExtensionMessageHandlers = {
collectPageDetails: ({ message }) => this.collectPageDetails(message), collectPageDetails: ({ message }) => this.collectPageDetails(message),
collectPageDetailsImmediately: ({ message }) => this.collectPageDetails(message, true), collectPageDetailsImmediately: ({ message }) => this.collectPageDetails(message, true),
fillForm: ({ message }) => this.fillForm(message.fillScript), fillForm: ({ message }) => this.fillForm(message),
}; };
/** /**
@ -76,10 +75,14 @@ class AutofillInit implements AutofillInitInterface {
/** /**
* Fills the form with the given fill script. * Fills the form with the given fill script.
* @param {AutofillScript} fillScript *
* @private * @param {AutofillExtensionMessage} message
*/ */
private fillForm(fillScript: AutofillScript) { private fillForm({ fillScript, pageDetailsUrl }: AutofillExtensionMessage) {
if ((document.defaultView || window).location.href !== pageDetailsUrl) {
return;
}
this.insertAutofillContentService.fillForm(fillScript); this.insertAutofillContentService.fillForm(fillScript);
} }

View File

@ -398,6 +398,7 @@ describe("AutofillService", () => {
untrustedIframe: false, untrustedIframe: false,
}, },
url: currentAutofillPageDetails.tab.url, url: currentAutofillPageDetails.tab.url,
pageDetailsUrl: "url",
}, },
{ {
frameId: currentAutofillPageDetails.frameId, frameId: currentAutofillPageDetails.frameId,

View File

@ -208,6 +208,7 @@ export default class AutofillService implements AutofillServiceInterface {
command: "fillForm", command: "fillForm",
fillScript: fillScript, fillScript: fillScript,
url: tab.url, url: tab.url,
pageDetailsUrl: pd.details.url,
}, },
{ frameId: pd.frameId } { frameId: pd.frameId }
); );