""" Проверка наличия чекбокса согласия на обработку персональных данных. Согласно 152-ФЗ, обработка данных допустима только при наличии согласия субъекта. Формы на сайте (обратная связь, регистрация, подписка и т.д.) должны содержать явное согласие пользователя. """ from __future__ import annotations import re from playwright.async_api import Page from scanner.checks.base import BaseCheck from scanner.models import CheckResult, RiskLevel class FormCheckboxCheck(BaseCheck): """Проверяет наличие чекбокса согласия в формах на сайте.""" name = "form_checkbox" title = "Чекбокс согласия в формах" description = "Проверяет, есть ли чекбокс согласия на обработку ПД в формах" risk_on_fail = RiskLevel.CRITICAL default_weight = 20 CONSENT_PATTERNS = [ r"согласие\s*на\s*обработку\s*данных", r"согласие\s*на\s*обработку\s*персональных?\s*данных?", r"я\s*согласен\s*на\s*", r"agree\s*to\s*the\s*", r"agree\s*to\s*privacy", r"я\s*принимаю\s*условия", r"processing\s*of\s*personal\s*data", r"обработк[аею]\s*персональных?\s*данных?", r"политик[ууе]?\s*конфиденциальност[иы]", ] async def check(self, page: Page, url: str) -> CheckResult: try: # Получаем все формы на странице forms = await page.query_selector_all("form") if not forms: return self._skip_result( message="Формы на странице не найдены.", ) forms_needing_consent = 0 forms_with_consent = 0 forms_without_consent = [] for form_idx, form in enumerate(forms): # Проверяем, есть ли чекбокс в форме checkboxes = await form.query_selector_all('input[type="checkbox"]') has_consent = False checkbox_texts = [] for cb in checkboxes: cb_text = await cb.inner_text() if not await cb.get_attribute("value") else await cb.get_attribute("value") cb_label = await form.evaluate( f'(el) => {{\n' f' const cb = el.closest("label") || el.parentElement;\n' f' return cb ? cb.innerText : "";\n' f'}}', form ) checkbox_texts.append(cb_text or cb_label or "без текста") combined = f"{cb_text} {cb_label}".lower() if any(re.search(p, combined, re.UNICODE | re.IGNORECASE) for p in self.CONSENT_PATTERNS): has_consent = True forms_needing_consent += 1 if has_consent: forms_with_consent += 1 else: forms_without_consent.append({ "form_index": form_idx, "checkboxes": checkbox_texts[:3], }) if forms_with_consent == forms_needing_consent: return self._pass_result( message=f"Все формы ({forms_with_consent}) содержат чекбокс согласия.", details={ "forms_count": forms_with_consent, "checked_forms": forms_with_consent, }, ) if forms_with_consent == 0: return self._fail_result( message=( f"Формы ({forms_needing_consent}) не содержат чекбокс согласия на обработку ПД. " f"Это прямое нарушение 152-ФЗ." ), details={ "total_forms": forms_needing_consent, "without_consent": forms_without_consent, "sample_texts": [f["checkboxes"][0] for f in forms_without_consent[:3]], }, ) # Частичное покрытие return self._fail_result( message=( f"Только {forms_with_consent} из {forms_needing_consent} форм содержат чекбокс согласия." ), details={ "total_forms": forms_needing_consent, "with_consent": forms_with_consent, "without_consent_count": forms_needing_consent - forms_with_consent, }, ) except Exception as e: return self._error_result(message=f"Ошибка при проверке чекбоксов: {str(e)}")