diff --git a/scripts/check_secrets.py b/scripts/check_secrets.py index 793f872..773a3d6 100644 --- a/scripts/check_secrets.py +++ b/scripts/check_secrets.py @@ -37,6 +37,7 @@ _URL_SECRET_RE = re.compile( r"(?ix)[?&](?:api[_-]?key|access[_-]?token|auth(?:orization)?|icalsecurise|password|secret|token)" r"=([^&#\s]{3,})" ) +_URL_PLACEHOLDER_RE = re.compile(r"(?x)^(?:\{[^{}\r\n]+\}|<[^<>\r\n]+>|\.+|[•…*]+)$") _EXTRA_NAMES = frozenset({"pronote_sync"}) @@ -185,7 +186,8 @@ def find_secrets( ) if is_literal_secret: findings.append(SecretFinding(relative_path, number, "affectation-litterale")) - if _URL_SECRET_RE.search(line): + url_match = _URL_SECRET_RE.search(line) + if url_match and not _URL_PLACEHOLDER_RE.fullmatch(url_match.group(1)): findings.append(SecretFinding(relative_path, number, "parametre-url")) return sorted(findings, key=lambda finding: (str(finding.path), finding.line, finding.rule)) diff --git a/tests/unit/test_check_secrets.py b/tests/unit/test_check_secrets.py index 554bc4b..6bdaedf 100644 --- a/tests/unit/test_check_secrets.py +++ b/tests/unit/test_check_secrets.py @@ -118,6 +118,33 @@ def test_main_detects_sensitive_url_parameter( assert sentinel not in output +def test_main_ignores_documentation_url_placeholders( + secret_checker: ModuleType, tmp_path: Path, capsys: CaptureFixture[str] +) -> None: + """Ignore les marqueurs de remplacement utilisés dans une documentation. + + :param secret_checker: Module du script sous test. + :param tmp_path: Répertoire temporaire représentant un dépôt. + :param capsys: Fixture de capture de sortie. + :return: None + """ + (tmp_path / "guide.md").write_text( + "\n".join( + ( + "https://example.invalid/?icalsecurise={jeton}", + "https://example.invalid/?icalsecurise=••••••••", + "https://example.invalid/?icalsecurise=", + "https://example.invalid/?icalsecurise=...", + ) + ) + + "\n", + encoding="utf-8", + ) + + assert secret_checker.main([], root=tmp_path) == 0 + assert "OK:" in capsys.readouterr().out + + def test_staged_mode_inspects_only_paths_provided_by_git( secret_checker: ModuleType, tmp_path: Path, capsys: CaptureFixture[str] ) -> None: