From 4e50690af2a66029f6ffdd7d361520be326e6439 Mon Sep 17 00:00:00 2001 From: GioSensation Date: Tue, 30 Jan 2024 13:10:29 +0000 Subject: [PATCH] Update autofill to 10.1.0 --- .../autofill/dist/autofill-debug.js | 299 ++++++++++++++++-- .../@duckduckgo/autofill/dist/autofill.js | 299 ++++++++++++++++-- .../autofill/dist/shared-credentials.json | 9 + package-lock.json | 4 +- package.json | 2 +- 5 files changed, 552 insertions(+), 61 deletions(-) diff --git a/node_modules/@duckduckgo/autofill/dist/autofill-debug.js b/node_modules/@duckduckgo/autofill/dist/autofill-debug.js index e242335e851c..3627f1372b9d 100644 --- a/node_modules/@duckduckgo/autofill/dist/autofill-debug.js +++ b/node_modules/@duckduckgo/autofill/dist/autofill-debug.js @@ -6748,7 +6748,7 @@ module.exports={ "password-rules": "minlength: 8; max-consecutive: 3; required: lower; required: upper; required: digit; allowed: [-!@#$%^&*_+=`|(){}[:;,.?]];" }, "fidelity.com": { - "password-rules": "minlength: 6; maxlength: 20; required: lower; required: upper; required: digit; required: [!$%'()+,./:;=?@^_|~]; max-consecutive: 2;" + "password-rules": "minlength: 6; maxlength: 20; required: lower; required: upper; required: digit; required: [-!$%+,./:;=?@^_|]; max-consecutive: 2;" }, "flysas.com": { "password-rules": "minlength: 8; maxlength: 14; required: lower; required: upper; required: digit; required: [-~!@#$%^&_+=`|(){}[:\"'<>,.?]];" @@ -6789,9 +6789,147 @@ module.exports={ "hawaiianairlines.com": { "password-rules": "maxlength: 16;" }, + "hertz-japan.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz-kuwait.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz-saudi.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.at": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.be": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.bh": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ca": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ch": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cn": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.ao": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.id": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.kr": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.nz": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.th": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.uk": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, "hertz.com": { "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" }, + "hertz.com.au": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.bh": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.hk": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.kw": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.mt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.pl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.pt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.sg": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.tw": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cv": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cz": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.de": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ee": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.es": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.fi": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.fr": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.hu": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ie": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.it": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.jo": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.lt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.nl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.no": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.nu": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.pl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.pt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.qa": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ru": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.se": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.si": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertzcaribbean.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, "hetzner.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit, special;" }, @@ -6948,6 +7086,9 @@ module.exports={ "microsoft.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: special;" }, + "milogin.michigan.gov": { + "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: [@#$!~&];" + }, "mintmobile.com": { "password-rules": "minlength: 8; maxlength: 20; required: lower; required: upper; required: digit; required: special; allowed: [!#$%&()*+:;=@[^_`{}~]];" }, @@ -7215,6 +7356,9 @@ module.exports={ "vetsfirstchoice.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; allowed: [?!@$%^+=&];" }, + "vince.com": { + "password-rules": "minlength: 8; required: digit; required: lower; required: upper; required: [$%/(){}=?!.,_*|+~#[]];" + }, "virginmobile.ca": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: [!#$@];" }, @@ -9092,7 +9236,7 @@ class InterfacePrototype { postSubmit(values, form) { if (!form.form) return; if (!form.hasValues(values)) return; - const checks = [form.shouldPromptToStoreData, this.passwordGenerator.generated]; + const checks = [form.shouldPromptToStoreData && !form.submitHandlerExecuted, this.passwordGenerator.generated]; if (checks.some(Boolean)) { const formData = (0, _Credentials.appendGeneratedKey)(values, { password: this.passwordGenerator.password, @@ -9516,20 +9660,21 @@ function initFormSubmissionsApi(forms, matching) { * @param {PointerEvent} event */ window.addEventListener('pointerdown', event => { + const realTarget = (0, _autofillUtils.pierceShadowTree)(event); const formsArray = [...forms.values()]; const matchingForm = formsArray.find(form => { const btns = [...form.submitButtons]; // @ts-ignore - if (btns.includes(event.target)) return true; + if (btns.includes(realTarget)) return true; // @ts-ignore - if (btns.find(btn => btn.contains(event.target))) return true; + if (btns.find(btn => btn.contains(realTarget))) return true; }); matchingForm?.submitHandler('global pointerdown event + matching form'); if (!matchingForm) { const selector = matching.cssSelector('submitButtonSelector') + ', a[href="#"], a[href^=javascript], *[onclick], [class*=button i]'; // check if the click happened on a button - const button = /** @type HTMLElement */event.target?.closest(selector); + const button = /** @type HTMLElement */realTarget?.closest(selector); if (!button) return; // If the element we've found includes a form it can't be a button, it's a false match @@ -9547,7 +9692,7 @@ function initFormSubmissionsApi(forms, matching) { // TODO: Temporary hack to support Google signin in different languages // https://app.asana.com/0/1198964220583541/1201650539303898/f - if ( /** @type HTMLElement */event.target?.closest('#passwordNext button, #identifierNext button')) { + if ( /** @type HTMLElement */realTarget?.closest('#passwordNext button, #identifierNext button')) { // check if there's a form with values const filledForm = formsArray.find(form => form.hasValues()); filledForm?.submitHandler('global pointerdown event + google escape hatch'); @@ -9724,8 +9869,8 @@ class Form { this.activeInput = null; // We set this to true to skip event listeners while we're autofilling this.isAutofilling = false; - this.handlerExecuted = false; - this.shouldPromptToStoreData = true; + this.submitHandlerExecuted = false; + this.shouldPromptToStoreData = deviceInterface.settings.featureToggles.credentials_saving; this.shouldAutoSubmit = this.device.globalConfig.isMobileApp; /** @@ -9761,14 +9906,7 @@ class Form { } } }); - - // This ensures we fire the handler again if the form is changed - this.addListener(form, 'input', () => { - if (!this.isAutofilling) { - this.handlerExecuted = false; - this.shouldPromptToStoreData = true; - } - }); + this.initFormListeners(); this.categorizeInputs(); this.logFormInfo(); if (shouldAutoprompt) { @@ -9808,19 +9946,19 @@ class Form { * @param {KeyboardEvent | null} [e] */ hasFocus(e) { - return this.form.contains(document.activeElement) || this.form.contains( /** @type HTMLElement */e?.target); + return this.form.contains((0, _autofillUtils.getActiveElement)()) || this.form.contains( /** @type HTMLElement */e?.target); } submitHandler() { let via = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unknown'; if (this.device.globalConfig.isDDGTestMode) { console.log('Form.submitHandler via:', via, this); } - if (this.handlerExecuted) return; + if (this.submitHandlerExecuted) return; const values = this.getValuesReadyForStorage(); this.device.postSubmit?.(values, this); // mark this form as being handled - this.handlerExecuted = true; + this.submitHandlerExecuted = true; } /** @@ -9933,8 +10071,8 @@ class Form { // This ensures we are not removing the highlight ourselves when autofilling more than once if (e && !e.isTrusted) return; - // If the user has changed the value, we prompt to update the stored data - this.shouldPromptToStoreData = true; + // If the user has changed the value, reset shouldPromptToStoreData to initial value + this.resetShouldPromptToStoreData(); this.execOnInputs(input => this.removeInputHighlight(input), dataType); } removeInputDecoration(input) { @@ -9988,6 +10126,7 @@ class Form { this.initialScanComplete = false; this.removeAllDecorations(); this.forgetAllInputs(); + this.initFormListeners(); this.categorizeInputs(); } resetAllInputs() { @@ -9998,6 +10137,9 @@ class Form { if (this.activeInput) this.activeInput.focus(); this.matching.clear(); } + resetShouldPromptToStoreData() { + this.shouldPromptToStoreData = this.device.settings.featureToggles.credentials_saving; + } dismissTooltip() { this.removeTooltip(); } @@ -10011,6 +10153,24 @@ class Form { this.intObs = null; this.device.scanner.forms.delete(this.form); } + initFormListeners() { + // This ensures we fire the handler again if the form is changed + this.addListener(this.form, 'input', () => { + if (!this.isAutofilling) { + this.submitHandlerExecuted = false; + this.resetShouldPromptToStoreData(); + } + }); + + // If it's a form within a shadow tree, attach the submit listener, because it doesn't bubble outside + if (this.form instanceof HTMLFormElement && this.form.getRootNode()) { + this.addListener(this.form, 'submit', () => { + this.submitHandler('in-form submit handler'); + }, { + capture: true + }); + } + } categorizeInputs() { const selector = this.matching.cssSelector('formInputsSelector'); // If there's no form container and it's just a lonely input field (this.form is an input field) @@ -10727,7 +10887,8 @@ class FormAnalyzer { } else { // Here we don't think this is a submit, so if there is another submit in the form, flip the score const thereIsASubmitButton = Boolean(this.form.querySelector('input[type=submit], button[type=submit]')); - shouldFlip = thereIsASubmitButton; + const isSocialButton = /facebook|twitter|google|apple/i.test(string); + shouldFlip = thereIsASubmitButton && !isSocialButton; } const strength = likelyASubmit ? 20 : 4; this.updateSignal({ @@ -12389,7 +12550,7 @@ const matchingConfiguration = exports.matchingConfiguration = { emailAddress: { match: /.mail\b|apple.?id|posta elettronica|e.?mailadres|correo electr|correo-e|^correo$|\be.?post|e.?postadress/iu, skip: /phone|(first.?|last.?)name|number|code/iu, - forceUnknown: /search|filter|subject|title|tab|otp/iu + forceUnknown: /search|filter|subject|title|\btab\b|otp/iu }, password: { match: /password|passwort|kennwort|wachtwoord|mot de passe|clave|contraseña|lösenord/iu, @@ -12397,13 +12558,13 @@ const matchingConfiguration = exports.matchingConfiguration = { forceUnknown: /captcha|mfa|2fa|two factor|otp|pin/iu }, newPassword: { - match: /new|re.?(enter|type)|repeat|update|reset/iu + match: /new|re.?(enter|type)|repeat|update|reset\b/iu }, currentPassword: { match: /current|old|previous|expired|existing/iu }, username: { - match: /(user|account|log(i|o)n|net)((.)?(name|i.?d.?|log(i|o)n).?)?(.?((or|\/).+|\*|:)( required)?)?$|(nome|id|login).?utente|(nome|id) (dell.)?account|codice cliente|nutzername|anmeldename|gebruikersnaam|nom d.utilisateur|identifiant|pseudo|usuari|cuenta|identificador|apodo|\bdni\b|\bnie\b| del? documento|documento de identidad|användarnamn|kontonamn|användar-id/iu, + match: /(user|account|online.?id|log(i|o)n|net)((.)?(name|i.?d.?|log(i|o)n).?)?(.?((or|\/).+|\*|:)( required)?)?$|(nome|id|login).?utente|(nome|id) (dell.)?account|codice cliente|nutzername|anmeldename|gebruikersnaam|nom d.utilisateur|identifiant|pseudo|usuari|cuenta|identificador|apodo|\bdni\b|\bnie\b| del? documento|documento de identidad|användarnamn|kontonamn|användar-id/iu, skip: /phone/iu, forceUnknown: /search|policy|choose a user\b/iu }, @@ -12471,7 +12632,7 @@ const matchingConfiguration = exports.matchingConfiguration = { skip: /country/iu }, addressPostalCode: { - match: /\bzip\b|postal|post.?code|\bcap\b|codice postale/iu + match: /\bzip\b|postal\b|post.?code|\bcap\b|codice postale/iu }, addressCountryCode: { match: /country|\bnation\b|nazione|paese/iu @@ -14052,7 +14213,8 @@ var _deviceApiCalls = require("./deviceApiCalls/__generated__/deviceApiCalls.js" const { MAX_INPUTS_PER_PAGE, MAX_FORMS_PER_PAGE, - MAX_INPUTS_PER_FORM + MAX_INPUTS_PER_FORM, + ATTR_INPUT_TYPE } = _constants.constants; /** @@ -14151,6 +14313,13 @@ class DefaultScanner { flag: 'autofill' })); } + + // Add the shadow DOM listener. Handlers in handleEvent + window.addEventListener('pointerdown', this, true); + // We don't listen for focus events on mobile, they can cause keyboard flashing + if (!this.device.globalConfig.isMobileApp) { + window.addEventListener('focus', this, true); + } const delay = this.options.initialDelay; // if the delay is zero, (chrome/firefox etc) then use `requestIdleCallback` if (delay === 0) { @@ -14221,6 +14390,8 @@ class DefaultScanner { clearTimeout(this.debounceTimer); this.changedElements.clear(); this.mutObs.disconnect(); + window.removeEventListener('pointerdown', this, true); + window.removeEventListener('focus', this, true); this.forms.forEach(form => { form.destroy(); }); @@ -14402,6 +14573,32 @@ class DefaultScanner { } this.enqueue(outgoing); }); + handleEvent(event) { + switch (event.type) { + case 'pointerdown': + case 'focus': + this.scanShadow(event); + break; + } + } + + /** + * Scan clicked input fields, even if they're within a shadow tree + * @param {FocusEvent | PointerEvent} event + */ + scanShadow(event) { + // If the scanner is stopped or there's no shadow root, just return + if (this.stopped || !(event.target instanceof Element) || !event.target?.shadowRoot) return; + window.performance?.mark?.('scan_shadow:init:start'); + const realTarget = (0, _autofillUtils.pierceShadowTree)(event, HTMLInputElement); + + // If it's an input we haven't already scanned, scan the whole shadow tree + if (realTarget instanceof HTMLInputElement && !realTarget.hasAttribute(ATTR_INPUT_TYPE)) { + this.findEligibleInputs(realTarget.getRootNode()); + } + window.performance?.mark?.('scan_shadow:init:end'); + (0, _autofillUtils.logPerformance)('scan_shadow'); + } } /** @@ -16289,14 +16486,18 @@ Object.defineProperty(exports, "__esModule", { }); exports.buttonMatchesFormType = exports.autofillEnabled = exports.addInlineStyles = exports.SIGN_IN_MSG = exports.ADDRESS_DOMAIN = void 0; exports.escapeXML = escapeXML; -exports.isEventWithinDax = exports.isAutofillEnabledFromProcessedConfig = exports.getTextShallow = exports.getDaxBoundingBox = exports.formatDuckAddress = void 0; +exports.formatDuckAddress = void 0; +exports.getActiveElement = getActiveElement; +exports.isEventWithinDax = exports.isAutofillEnabledFromProcessedConfig = exports.getTextShallow = exports.getDaxBoundingBox = void 0; exports.isFormLikelyToBeUsedAsPageWrapper = isFormLikelyToBeUsedAsPageWrapper; exports.isLikelyASubmitButton = exports.isIncontextSignupEnabledFromProcessedConfig = void 0; exports.isLocalNetwork = isLocalNetwork; exports.isPotentiallyViewable = void 0; exports.isValidTLD = isValidTLD; exports.logPerformance = logPerformance; -exports.safeExecute = exports.removeInlineStyles = exports.notifyWebApp = void 0; +exports.notifyWebApp = void 0; +exports.pierceShadowTree = pierceShadowTree; +exports.safeExecute = exports.removeInlineStyles = void 0; exports.safeRegexTest = safeRegexTest; exports.setValue = exports.sendAndWaitForAnswer = void 0; exports.shouldLog = shouldLog; @@ -16851,6 +17052,46 @@ function safeRegexTest(regex, string) { return regex.test(string); } +/** + * Returns the event target, or an element that matches wantedTargetType, piercing the shadow tree + * @param {PointerEvent | FocusEvent} event + * @param {typeof Element} [wantedTargetType] + * @returns {EventTarget | null} + */ +function pierceShadowTree(event, wantedTargetType) { + const { + target + } = event; + + // Sanity checks + if (!(target instanceof Element) || !target?.shadowRoot || !event.composedPath) return target; + const clickStack = event.composedPath(); + + // If we're not looking for a specific element, get the top of the stack + if (!wantedTargetType) { + return clickStack[0]; + } + + // Otherwise, search the wanted target, or return the original target + return clickStack.find(el => el instanceof wantedTargetType) || target; +} + +/** + * Return the active element, piercing through shadow DOMs, or null + * @param {Document | DocumentOrShadowRoot} root + * @returns {Element | null} + */ +function getActiveElement() { + let root = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; + const activeElement = root.activeElement; + if (!(activeElement instanceof Element) || !activeElement.shadowRoot) return activeElement; + const innerActiveElement = activeElement.shadowRoot.activeElement; + if (innerActiveElement?.shadowRoot) { + return getActiveElement(innerActiveElement.shadowRoot); + } + return innerActiveElement; +} + },{"./Form/matching.js":43,"./constants.js":64}],62:[function(require,module,exports){ "use strict"; diff --git a/node_modules/@duckduckgo/autofill/dist/autofill.js b/node_modules/@duckduckgo/autofill/dist/autofill.js index d2dc44ddf833..51f2466a87d3 100644 --- a/node_modules/@duckduckgo/autofill/dist/autofill.js +++ b/node_modules/@duckduckgo/autofill/dist/autofill.js @@ -2582,7 +2582,7 @@ module.exports={ "password-rules": "minlength: 8; max-consecutive: 3; required: lower; required: upper; required: digit; allowed: [-!@#$%^&*_+=`|(){}[:;,.?]];" }, "fidelity.com": { - "password-rules": "minlength: 6; maxlength: 20; required: lower; required: upper; required: digit; required: [!$%'()+,./:;=?@^_|~]; max-consecutive: 2;" + "password-rules": "minlength: 6; maxlength: 20; required: lower; required: upper; required: digit; required: [-!$%+,./:;=?@^_|]; max-consecutive: 2;" }, "flysas.com": { "password-rules": "minlength: 8; maxlength: 14; required: lower; required: upper; required: digit; required: [-~!@#$%^&_+=`|(){}[:\"'<>,.?]];" @@ -2623,9 +2623,147 @@ module.exports={ "hawaiianairlines.com": { "password-rules": "maxlength: 16;" }, + "hertz-japan.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz-kuwait.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz-saudi.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.at": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.be": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.bh": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ca": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ch": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cn": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.ao": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.id": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.kr": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.nz": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.th": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.co.uk": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, "hertz.com": { "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" }, + "hertz.com.au": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.bh": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.hk": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.kw": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.mt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.pl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.pt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.sg": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.com.tw": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cv": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.cz": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.de": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ee": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.es": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.fi": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.fr": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.hu": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ie": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.it": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.jo": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.lt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.nl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.no": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.nu": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.pl": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.pt": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.qa": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.ru": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.se": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertz.si": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, + "hertzcaribbean.com": { + "password-rules": "minlength: 8; maxlength: 30; max-consecutive: 3; required: lower; required: upper; required: digit; required: [#$%^&!@];" + }, "hetzner.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit, special;" }, @@ -2782,6 +2920,9 @@ module.exports={ "microsoft.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: special;" }, + "milogin.michigan.gov": { + "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: [@#$!~&];" + }, "mintmobile.com": { "password-rules": "minlength: 8; maxlength: 20; required: lower; required: upper; required: digit; required: special; allowed: [!#$%&()*+:;=@[^_`{}~]];" }, @@ -3049,6 +3190,9 @@ module.exports={ "vetsfirstchoice.com": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; allowed: [?!@$%^+=&];" }, + "vince.com": { + "password-rules": "minlength: 8; required: digit; required: lower; required: upper; required: [$%/(){}=?!.,_*|+~#[]];" + }, "virginmobile.ca": { "password-rules": "minlength: 8; required: lower; required: upper; required: digit; required: [!#$@];" }, @@ -4926,7 +5070,7 @@ class InterfacePrototype { postSubmit(values, form) { if (!form.form) return; if (!form.hasValues(values)) return; - const checks = [form.shouldPromptToStoreData, this.passwordGenerator.generated]; + const checks = [form.shouldPromptToStoreData && !form.submitHandlerExecuted, this.passwordGenerator.generated]; if (checks.some(Boolean)) { const formData = (0, _Credentials.appendGeneratedKey)(values, { password: this.passwordGenerator.password, @@ -5350,20 +5494,21 @@ function initFormSubmissionsApi(forms, matching) { * @param {PointerEvent} event */ window.addEventListener('pointerdown', event => { + const realTarget = (0, _autofillUtils.pierceShadowTree)(event); const formsArray = [...forms.values()]; const matchingForm = formsArray.find(form => { const btns = [...form.submitButtons]; // @ts-ignore - if (btns.includes(event.target)) return true; + if (btns.includes(realTarget)) return true; // @ts-ignore - if (btns.find(btn => btn.contains(event.target))) return true; + if (btns.find(btn => btn.contains(realTarget))) return true; }); matchingForm?.submitHandler('global pointerdown event + matching form'); if (!matchingForm) { const selector = matching.cssSelector('submitButtonSelector') + ', a[href="#"], a[href^=javascript], *[onclick], [class*=button i]'; // check if the click happened on a button - const button = /** @type HTMLElement */event.target?.closest(selector); + const button = /** @type HTMLElement */realTarget?.closest(selector); if (!button) return; // If the element we've found includes a form it can't be a button, it's a false match @@ -5381,7 +5526,7 @@ function initFormSubmissionsApi(forms, matching) { // TODO: Temporary hack to support Google signin in different languages // https://app.asana.com/0/1198964220583541/1201650539303898/f - if ( /** @type HTMLElement */event.target?.closest('#passwordNext button, #identifierNext button')) { + if ( /** @type HTMLElement */realTarget?.closest('#passwordNext button, #identifierNext button')) { // check if there's a form with values const filledForm = formsArray.find(form => form.hasValues()); filledForm?.submitHandler('global pointerdown event + google escape hatch'); @@ -5558,8 +5703,8 @@ class Form { this.activeInput = null; // We set this to true to skip event listeners while we're autofilling this.isAutofilling = false; - this.handlerExecuted = false; - this.shouldPromptToStoreData = true; + this.submitHandlerExecuted = false; + this.shouldPromptToStoreData = deviceInterface.settings.featureToggles.credentials_saving; this.shouldAutoSubmit = this.device.globalConfig.isMobileApp; /** @@ -5595,14 +5740,7 @@ class Form { } } }); - - // This ensures we fire the handler again if the form is changed - this.addListener(form, 'input', () => { - if (!this.isAutofilling) { - this.handlerExecuted = false; - this.shouldPromptToStoreData = true; - } - }); + this.initFormListeners(); this.categorizeInputs(); this.logFormInfo(); if (shouldAutoprompt) { @@ -5642,19 +5780,19 @@ class Form { * @param {KeyboardEvent | null} [e] */ hasFocus(e) { - return this.form.contains(document.activeElement) || this.form.contains( /** @type HTMLElement */e?.target); + return this.form.contains((0, _autofillUtils.getActiveElement)()) || this.form.contains( /** @type HTMLElement */e?.target); } submitHandler() { let via = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'unknown'; if (this.device.globalConfig.isDDGTestMode) { console.log('Form.submitHandler via:', via, this); } - if (this.handlerExecuted) return; + if (this.submitHandlerExecuted) return; const values = this.getValuesReadyForStorage(); this.device.postSubmit?.(values, this); // mark this form as being handled - this.handlerExecuted = true; + this.submitHandlerExecuted = true; } /** @@ -5767,8 +5905,8 @@ class Form { // This ensures we are not removing the highlight ourselves when autofilling more than once if (e && !e.isTrusted) return; - // If the user has changed the value, we prompt to update the stored data - this.shouldPromptToStoreData = true; + // If the user has changed the value, reset shouldPromptToStoreData to initial value + this.resetShouldPromptToStoreData(); this.execOnInputs(input => this.removeInputHighlight(input), dataType); } removeInputDecoration(input) { @@ -5822,6 +5960,7 @@ class Form { this.initialScanComplete = false; this.removeAllDecorations(); this.forgetAllInputs(); + this.initFormListeners(); this.categorizeInputs(); } resetAllInputs() { @@ -5832,6 +5971,9 @@ class Form { if (this.activeInput) this.activeInput.focus(); this.matching.clear(); } + resetShouldPromptToStoreData() { + this.shouldPromptToStoreData = this.device.settings.featureToggles.credentials_saving; + } dismissTooltip() { this.removeTooltip(); } @@ -5845,6 +5987,24 @@ class Form { this.intObs = null; this.device.scanner.forms.delete(this.form); } + initFormListeners() { + // This ensures we fire the handler again if the form is changed + this.addListener(this.form, 'input', () => { + if (!this.isAutofilling) { + this.submitHandlerExecuted = false; + this.resetShouldPromptToStoreData(); + } + }); + + // If it's a form within a shadow tree, attach the submit listener, because it doesn't bubble outside + if (this.form instanceof HTMLFormElement && this.form.getRootNode()) { + this.addListener(this.form, 'submit', () => { + this.submitHandler('in-form submit handler'); + }, { + capture: true + }); + } + } categorizeInputs() { const selector = this.matching.cssSelector('formInputsSelector'); // If there's no form container and it's just a lonely input field (this.form is an input field) @@ -6561,7 +6721,8 @@ class FormAnalyzer { } else { // Here we don't think this is a submit, so if there is another submit in the form, flip the score const thereIsASubmitButton = Boolean(this.form.querySelector('input[type=submit], button[type=submit]')); - shouldFlip = thereIsASubmitButton; + const isSocialButton = /facebook|twitter|google|apple/i.test(string); + shouldFlip = thereIsASubmitButton && !isSocialButton; } const strength = likelyASubmit ? 20 : 4; this.updateSignal({ @@ -8223,7 +8384,7 @@ const matchingConfiguration = exports.matchingConfiguration = { emailAddress: { match: /.mail\b|apple.?id|posta elettronica|e.?mailadres|correo electr|correo-e|^correo$|\be.?post|e.?postadress/iu, skip: /phone|(first.?|last.?)name|number|code/iu, - forceUnknown: /search|filter|subject|title|tab|otp/iu + forceUnknown: /search|filter|subject|title|\btab\b|otp/iu }, password: { match: /password|passwort|kennwort|wachtwoord|mot de passe|clave|contraseña|lösenord/iu, @@ -8231,13 +8392,13 @@ const matchingConfiguration = exports.matchingConfiguration = { forceUnknown: /captcha|mfa|2fa|two factor|otp|pin/iu }, newPassword: { - match: /new|re.?(enter|type)|repeat|update|reset/iu + match: /new|re.?(enter|type)|repeat|update|reset\b/iu }, currentPassword: { match: /current|old|previous|expired|existing/iu }, username: { - match: /(user|account|log(i|o)n|net)((.)?(name|i.?d.?|log(i|o)n).?)?(.?((or|\/).+|\*|:)( required)?)?$|(nome|id|login).?utente|(nome|id) (dell.)?account|codice cliente|nutzername|anmeldename|gebruikersnaam|nom d.utilisateur|identifiant|pseudo|usuari|cuenta|identificador|apodo|\bdni\b|\bnie\b| del? documento|documento de identidad|användarnamn|kontonamn|användar-id/iu, + match: /(user|account|online.?id|log(i|o)n|net)((.)?(name|i.?d.?|log(i|o)n).?)?(.?((or|\/).+|\*|:)( required)?)?$|(nome|id|login).?utente|(nome|id) (dell.)?account|codice cliente|nutzername|anmeldename|gebruikersnaam|nom d.utilisateur|identifiant|pseudo|usuari|cuenta|identificador|apodo|\bdni\b|\bnie\b| del? documento|documento de identidad|användarnamn|kontonamn|användar-id/iu, skip: /phone/iu, forceUnknown: /search|policy|choose a user\b/iu }, @@ -8305,7 +8466,7 @@ const matchingConfiguration = exports.matchingConfiguration = { skip: /country/iu }, addressPostalCode: { - match: /\bzip\b|postal|post.?code|\bcap\b|codice postale/iu + match: /\bzip\b|postal\b|post.?code|\bcap\b|codice postale/iu }, addressCountryCode: { match: /country|\bnation\b|nazione|paese/iu @@ -9886,7 +10047,8 @@ var _deviceApiCalls = require("./deviceApiCalls/__generated__/deviceApiCalls.js" const { MAX_INPUTS_PER_PAGE, MAX_FORMS_PER_PAGE, - MAX_INPUTS_PER_FORM + MAX_INPUTS_PER_FORM, + ATTR_INPUT_TYPE } = _constants.constants; /** @@ -9985,6 +10147,13 @@ class DefaultScanner { flag: 'autofill' })); } + + // Add the shadow DOM listener. Handlers in handleEvent + window.addEventListener('pointerdown', this, true); + // We don't listen for focus events on mobile, they can cause keyboard flashing + if (!this.device.globalConfig.isMobileApp) { + window.addEventListener('focus', this, true); + } const delay = this.options.initialDelay; // if the delay is zero, (chrome/firefox etc) then use `requestIdleCallback` if (delay === 0) { @@ -10055,6 +10224,8 @@ class DefaultScanner { clearTimeout(this.debounceTimer); this.changedElements.clear(); this.mutObs.disconnect(); + window.removeEventListener('pointerdown', this, true); + window.removeEventListener('focus', this, true); this.forms.forEach(form => { form.destroy(); }); @@ -10236,6 +10407,32 @@ class DefaultScanner { } this.enqueue(outgoing); }); + handleEvent(event) { + switch (event.type) { + case 'pointerdown': + case 'focus': + this.scanShadow(event); + break; + } + } + + /** + * Scan clicked input fields, even if they're within a shadow tree + * @param {FocusEvent | PointerEvent} event + */ + scanShadow(event) { + // If the scanner is stopped or there's no shadow root, just return + if (this.stopped || !(event.target instanceof Element) || !event.target?.shadowRoot) return; + window.performance?.mark?.('scan_shadow:init:start'); + const realTarget = (0, _autofillUtils.pierceShadowTree)(event, HTMLInputElement); + + // If it's an input we haven't already scanned, scan the whole shadow tree + if (realTarget instanceof HTMLInputElement && !realTarget.hasAttribute(ATTR_INPUT_TYPE)) { + this.findEligibleInputs(realTarget.getRootNode()); + } + window.performance?.mark?.('scan_shadow:init:end'); + (0, _autofillUtils.logPerformance)('scan_shadow'); + } } /** @@ -12123,14 +12320,18 @@ Object.defineProperty(exports, "__esModule", { }); exports.buttonMatchesFormType = exports.autofillEnabled = exports.addInlineStyles = exports.SIGN_IN_MSG = exports.ADDRESS_DOMAIN = void 0; exports.escapeXML = escapeXML; -exports.isEventWithinDax = exports.isAutofillEnabledFromProcessedConfig = exports.getTextShallow = exports.getDaxBoundingBox = exports.formatDuckAddress = void 0; +exports.formatDuckAddress = void 0; +exports.getActiveElement = getActiveElement; +exports.isEventWithinDax = exports.isAutofillEnabledFromProcessedConfig = exports.getTextShallow = exports.getDaxBoundingBox = void 0; exports.isFormLikelyToBeUsedAsPageWrapper = isFormLikelyToBeUsedAsPageWrapper; exports.isLikelyASubmitButton = exports.isIncontextSignupEnabledFromProcessedConfig = void 0; exports.isLocalNetwork = isLocalNetwork; exports.isPotentiallyViewable = void 0; exports.isValidTLD = isValidTLD; exports.logPerformance = logPerformance; -exports.safeExecute = exports.removeInlineStyles = exports.notifyWebApp = void 0; +exports.notifyWebApp = void 0; +exports.pierceShadowTree = pierceShadowTree; +exports.safeExecute = exports.removeInlineStyles = void 0; exports.safeRegexTest = safeRegexTest; exports.setValue = exports.sendAndWaitForAnswer = void 0; exports.shouldLog = shouldLog; @@ -12685,6 +12886,46 @@ function safeRegexTest(regex, string) { return regex.test(string); } +/** + * Returns the event target, or an element that matches wantedTargetType, piercing the shadow tree + * @param {PointerEvent | FocusEvent} event + * @param {typeof Element} [wantedTargetType] + * @returns {EventTarget | null} + */ +function pierceShadowTree(event, wantedTargetType) { + const { + target + } = event; + + // Sanity checks + if (!(target instanceof Element) || !target?.shadowRoot || !event.composedPath) return target; + const clickStack = event.composedPath(); + + // If we're not looking for a specific element, get the top of the stack + if (!wantedTargetType) { + return clickStack[0]; + } + + // Otherwise, search the wanted target, or return the original target + return clickStack.find(el => el instanceof wantedTargetType) || target; +} + +/** + * Return the active element, piercing through shadow DOMs, or null + * @param {Document | DocumentOrShadowRoot} root + * @returns {Element | null} + */ +function getActiveElement() { + let root = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; + const activeElement = root.activeElement; + if (!(activeElement instanceof Element) || !activeElement.shadowRoot) return activeElement; + const innerActiveElement = activeElement.shadowRoot.activeElement; + if (innerActiveElement?.shadowRoot) { + return getActiveElement(innerActiveElement.shadowRoot); + } + return innerActiveElement; +} + },{"./Form/matching.js":33,"./constants.js":54}],52:[function(require,module,exports){ "use strict"; diff --git a/node_modules/@duckduckgo/autofill/dist/shared-credentials.json b/node_modules/@duckduckgo/autofill/dist/shared-credentials.json index 72be05d0d71e..0715247d99c7 100644 --- a/node_modules/@duckduckgo/autofill/dist/shared-credentials.json +++ b/node_modules/@duckduckgo/autofill/dist/shared-credentials.json @@ -371,6 +371,15 @@ "profile.callofduty.com" ] }, + { + "from": [ + "transferwise.com" + ], + "to": [ + "wise.com" + ], + "fromDomainsAreObsoleted": true + }, { "from": [ "tvnow.de", diff --git a/package-lock.json b/package-lock.json index 28e8dfc81220..d230e0a22b11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "dependencies": { "@duckduckgo/autoconsent": "^9.1.0", - "@duckduckgo/autofill": "github:duckduckgo/duckduckgo-autofill#10.0.3", + "@duckduckgo/autofill": "github:duckduckgo/duckduckgo-autofill#10.1.0", "@duckduckgo/content-scope-scripts": "github:duckduckgo/content-scope-scripts#4.59.2", "@duckduckgo/privacy-dashboard": "github:duckduckgo/privacy-dashboard#3.0.0", "@duckduckgo/privacy-reference-tests": "github:duckduckgo/privacy-reference-tests#1703196979" @@ -64,7 +64,7 @@ "integrity": "sha512-O5CR35by6A2i15pSDOzUN47RYxbw0EhZNYGyuQb7oIKBCSoiYqBqV3qayV5Idr0fQzz1fFSFVhT4a9vPikHf2g==" }, "node_modules/@duckduckgo/autofill": { - "resolved": "git+ssh://git@github.com/duckduckgo/duckduckgo-autofill.git#b972bc0ab6ee1d57a0a18a197dcc31e40ae6ac57", + "resolved": "git+ssh://git@github.com/duckduckgo/duckduckgo-autofill.git#03d3e3a959dd75afbe8c59b5a203ea676d37555d", "hasInstallScript": true, "license": "Apache-2.0" }, diff --git a/package.json b/package.json index 25e6c6eb011c..3a5ef384fc0b 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@duckduckgo/autoconsent": "^9.1.0", - "@duckduckgo/autofill": "github:duckduckgo/duckduckgo-autofill#10.0.3", + "@duckduckgo/autofill": "github:duckduckgo/duckduckgo-autofill#10.1.0", "@duckduckgo/content-scope-scripts": "github:duckduckgo/content-scope-scripts#4.59.2", "@duckduckgo/privacy-dashboard": "github:duckduckgo/privacy-dashboard#3.0.0", "@duckduckgo/privacy-reference-tests": "github:duckduckgo/privacy-reference-tests#1703196979"