소스 검색

Fix logic for recaptcha v3 on error states (#698)

Certain error states in the recaptcha v3 API do not return a score.
However, we were defaulting to a "good" score and therefore the errors
were being let through.

This first checks if the request was successful. If so, it then compares
the score.

Fallbacks have also been changed from "good" states to sentinel values,
which should be helpful for debugging in production.
Vince Salvino 2 일 전
부모
커밋
9b0fc7017c
2개의 변경된 파일11개의 추가작업 그리고 7개의 파일을 삭제
  1. 4 1
      coderedcms/models/page_models.py
  2. 7 6
      coderedcms/recaptcha.py

+ 4 - 1
coderedcms/models/page_models.py

@@ -1640,7 +1640,10 @@ class CoderedFormMixin(models.Model):
                 utils.get_ip(request),
             )
             # Score ranges from 0 (likely spam) to 1 (likely good).
-            return rr.score < ls.recaptcha_threshold
+            if rr.success and rr.score >= 0:
+                return rr.score < ls.recaptcha_threshold
+            else:
+                return True
         elif ls.spam_service == ls.SpamService.RECAPTCHA_V2:
             rr = verify_response(
                 request.POST.get("g-recaptcha-response", ""),

+ 7 - 6
coderedcms/recaptcha.py

@@ -10,7 +10,7 @@ logger = logging.getLogger("coderedcms")
 
 
 class RecaptchaResponse(typing.NamedTuple):
-    success: bool
+    success: typing.Union[bool, None]
     score: float
     error_codes: typing.List[str]
     original_data: typing.Dict[str, typing.Any]
@@ -43,11 +43,12 @@ def verify_response(recaptcha_response: str, secret_key: str, remoteip: str):
     response = urlopen(request)
     data = json.loads(response.read().decode("utf8"))
     response.close()
-    logger.info(f"reCAPTCHA response: {data}")
-    # Default to good (likely not spam) values if they are not present.
-    return RecaptchaResponse(
-        success=data.get("success", True),
-        score=data.get("score", 1.0),
+    # Default to sentinel values if not provided by Google.
+    rr = RecaptchaResponse(
+        success=data.get("success", None),
+        score=data.get("score", -1.0),
         error_codes=data.get("error-codes", []),
         original_data=data,
     )
+    logger.info(f"reCAPTCHA response: {rr}")
+    return rr