Fix/epicgames and paypal password inputs (#2863)

Fix Epicgames, Paypal and Reddit password input detection
This commit is contained in:
Sami Vänttinen 2026-02-16 08:21:19 +02:00 committed by GitHub
parent 89cc1bb40d
commit 9d254d1ffe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 42 additions and 12 deletions

View file

@ -71,7 +71,7 @@ kpxcSites.detectUsernameFromPage = function() {
* @returns {boolean} True if an Element has a match with the identifier and document location
*/
kpxcSites.exceptionFound = function(identifier, field) {
if (!identifier || identifier.length === 0) {
if ((!identifier || identifier.length === 0) && !field) {
return;
}
@ -80,7 +80,7 @@ kpxcSites.exceptionFound = function(identifier, field) {
|| (typeof identifier === 'object' && [ 'password', 'form-row', 'show-password' ].every(c => identifier.contains(c))))) {
return true;
} else if (document.location.origin.startsWith('https://signin.ebay.')
&& (identifier === 'null' || identifier.value === 'null' || identifier === 'pass')) {
&& (identifier === 'null' || identifier?.value === 'null' || identifier === 'pass')) {
return true;
} else if (document.location.origin.startsWith('https://www.fidelity.com')) {
if (typeof identifier === 'string') {
@ -108,6 +108,33 @@ kpxcSites.exceptionFound = function(identifier, field) {
return true;
} else if (document.location.origin === 'https://accounts.google.com' && field?.id === 'password') {
return true;
} else if (document.location.origin === 'https://www.epicgames.com'
&& ((field?.style?.opacity === '1' && field?.style?.willChange === 'auto') || identifier === 'password')) {
return true;
} else if (document.location.origin === 'https://www.paypal.com' && field?.id === 'splitPassword') {
return true;
}
return false;
};
// Handles exceptions when returning or modifying existing combinations
kpxcSites.combinationExceptionFound = function(existingCombination) {
if (!existingCombination) {
return false;
}
// Exception for e.g. Google. They replace the username input with password input using identical className.
// If detected, remove the username from the combination.
if (existingCombination?.username?.className?.length > 0
&& existingCombination?.password?.className?.length > 0
&& existingCombination?.username?.className === existingCombination?.password?.className) {
return true;
}
if (document.location.origin === 'https://www.paypal.com'
&& existingCombination.password?.className?.includes('pin-password')) {
return true;
}
return false;

View file

@ -108,11 +108,8 @@ kpxcFields.getExistingCombination = function(combination) {
existingCombination.passwordInputs.push(combination.password);
}
// Exception for Google. They replace the username input with password input using identical className.
// If detected, remove the username from the combination.
if (existingCombination?.username?.className?.length > 0
&& existingCombination?.password?.className?.length > 0
&& existingCombination?.username?.className === existingCombination?.password?.className) {
// Remove username field from combination with certain sites (replaced by password input)
if (kpxcSites.combinationExceptionFound(existingCombination)) {
existingCombination.username = null;
}

View file

@ -27,7 +27,7 @@ kpxcForm.activateCredentialBanner = async function(usernameValue, passwordInputs
return;
}
if (passwordField) {
if (passwordField && kpxcFields.isVisible(passwordField)) {
await kpxc.setPasswordFilled(true);
}

View file

@ -45,7 +45,13 @@ kpxcIcons.addIconsFromForm = async function(form) {
// Special case where everything else has been hidden, but a single password field is now displayed.
// For example PayPal and Amazon is handled like this.
if (c.username && !c.password && c.passwordInputs.length === 1) {
kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.DEFAULT);
// Use password input directly from form if found (Epicgames)
const passwordField = c.form?.querySelector('input[type=password]');
if (c.form && passwordField) {
kpxcIcons.addIcon(passwordField, kpxcIcons.iconTypes.DEFAULT);
} else {
kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.DEFAULT);
}
}
if (c.username && !c.username.readOnly) {

View file

@ -25,7 +25,6 @@ kpxcObserverHelper.ignoredNodeNames = [
];
kpxcObserverHelper.ignoredPartialNodeNames = [
'FACEPLATE',
'REDDIT-PDP',
'RENDER-TEMPLATE',
'SHREDDIT',
@ -247,8 +246,9 @@ kpxcObserverHelper.findInputsFromShadowDOM = function(target) {
// Detects animations and transitions. Triggers handleObserverAdd() again on animationend/transitionend.
kpxcObserverHelper.handleTransitions = function(target) {
const targetHasAnimations = target?.classList?.toString()?.includes('animate');
const targetHasDurations = target?.classList?.toString()?.includes('duration');
const classList = target?.classList?.toString();
const targetHasAnimations = classList?.includes('animate');
const targetHasDurations = classList?.includes('duration') || classList?.includes('transform');
if (targetHasAnimations || targetHasDurations) {
const animations = target.getAnimations();