Repository: nvaccess/nvda

Issue:
NVDA announces the last number of the typed pin on Windows 10 Lockscreen window
If one selects to sign into Windows 10 by typing a pin (instead of typing a password or using a fingerprint), NVDA announces the last number of the pin instead of replacing it with an asterisk (star). This happens regardless of whether or not the typed pin is correct.
This is with Windows 10 Pro 64-Bit, all recent Win 10 releases, and NVDA 2017.4, 2017.3, and 2017.2.
Quite interestingly, this doesn't affect the "Password" option.


Discussion:
CC @MichaelDCurran, requesting slightly above priority consideration as it concerns possible security issue. And yes, I can confirm it myself.
Hi,

Technical: this is because there is no "submit" button when entering a pin, whereas password field does. This means the last character will be spoken, as winlogon will immediately validate the pin as soon as last pin character is entered. This is an unintended side effect from #6017.

To confirm that this is indeed the side effect from keyboard handler changes made recently, can you try with NVDA 2016.4 and 2017.1 and see if NVDA even announces pin entries or asterisks?

Thanks.
Hi,

Unfortunately testing this with those older NVDA releases will take a
couple of days as modifying my work machine which depends on NVDA is
rather challenging. However, I just tested it with the demo copy of
the latest JAWS 2018 release, and it doesn't exhibit this behavior --
the last number of the pin is properly announced as asterisk.

Cheers.

On 1/15/18, Joseph Lee <notifications@github.com> wrote:
> Hi,
>
> Technical: this is because there is no "submit" button when entering a pin,
> whereas password field does. This means the last character will be spoken,
> as winlogon will immediately validate the pin as soon as last pin character
> is entered. This is an unintended side effect from #6017.
>
> To confirm that this is indeed the side effect from keyboard handler changes
> made recently, can you try with NVDA 2016.4 and 2017.1 and see if NVDA even
> announces pin entries or asterisks?
>
> Thanks.
>
> --
> You are receiving this because you authored the thread.
> Reply to this email directly or view it on GitHub:
> https://github.com/nvaccess/nvda/issues/7908#issuecomment-357585445


Resolving patch:
diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -766,7 +766,14 @@ def _get_isProtected(self):
 		@return: True if this object is protected (hides its input for passwords), or false otherwise
 		@rtype: boolean
 		"""
-		return False
+		# Objects with the protected state, or with a role of passWordEdit should always be protected.
+		isProtected=(controlTypes.STATE_PROTECTED in self.states or self.role==controlTypes.ROLE_PASSWORDEDIT)
+		# #7908: If this object is currently protected, keep it protected for the rest of its lifetime.
+		# The most likely reason it would lose its protected state is because the object is dying.
+		# In this case it is much more secure to assume it is still protected, thus the end of PIN codes will not be accidentally reported. 
+		if isProtected:
+			self.isProtected=isProtected
+		return isProtected
 
 	def _get_indexInParent(self):
 		"""The index of this object in its parent object.
diff --git a/source/api.py b/source/api.py
--- a/source/api.py
+++ b/source/api.py
@@ -244,7 +244,7 @@ def isTypingProtected():
 @rtype: boolean
 """
 	focusObject=getFocusObject()
-	if focusObject and (controlTypes.STATE_PROTECTED in focusObject.states or focusObject.role==controlTypes.ROLE_PASSWORDEDIT):
+	if focusObject and focusObject.isProtected:
 		return True
 	else:
 		return False


Test patch: