#2456·faker

pt_BR CPF and RG generators never produce repeated digits (RG also excludes the digit 9)

Author: Sreekant13Created Sep 20, 2026Updated Sep 20, 2026
  • Faker version: 40.39.0 and current master
  • OS: Windows 11, Python 3.10

Description

The pt_BR SSN provider builds both the CPF and the RG from digits drawn without replacement, so it generates only a small, unrealistic subset of the valid numbers.

ssn() (used by cpf()) draws its nine base digits with random.sample(range(10), 9). Sampling without replacement means the first nine digits are always distinct, so Faker never generates a CPF with a repeated digit, even though real CPF numbers routinely have them (for example the well known valid number 111.444.777-35). This restricts output to 10 P 9 = 3,628,800 base combinations instead of 10 ** 9 = 1,000,000,000, about 0.36 % of the space.

rg() draws its eight base digits with random.sample(range(0, 9), 8). This has two problems: range(0, 9) stops at 8, so the digit 9 is never used at all, and sampling without replacement again forces the eight digits to be distinct.

The generated numbers still have valid checksums. The issue is that the distribution is unrealistic and covers a tiny fraction of the valid space. This is the same root cause as the numeric CNPJ issue #2445 (fixed in #2446) and the nl_NL BSN fix in #2450, but the ssn/pt_BR provider is not covered by either.

Steps to reproduce

python
from faker import Faker

fake = Faker("pt_BR")

cpfs = [fake.cpf().replace(".", "").replace("-", "") for _ in range(20000)]
print(sum(len(set(c[:9])) < 9 for c in cpfs))           # repeated-digit CPFs
print(any("9" in fake.rg()[:8] for _ in range(20000)))  # does any RG contain a 9

Current output:

0
False

Expected behavior

Each digit should be drawn independently over the full 0-9 range, so repeated digits appear at their natural frequency and the RG can contain the digit 9. The fix is to draw with replacement using random.choices(range(10), k=...), matching the approach already used elsewhere in the codebase.

AI assistance disclosure

This issue was prepared with assistance from an AI tool, following the AI section of CONTRIBUTING.rst.

  • Tool and usage: Anthropic Claude (Claude Code, Opus 4.8). It read the current faker/providers/ssn/pt_BR/__init__.py source, reproduced the behavior on a checkout of current master, searched existing issues and open pull requests to confirm this is not already reported or claimed, calculated the reachable output space, and drafted this report.
  • Scope note: the AI section is written around security reports. To be clear, this is a data-quality and correctness bug, not a security vulnerability. It is real, reproducible, and based on the actual Faker source in a maintained version, and it does not depend on any third-party application or on code that ignores best practices.
  • No fabrication: every function, argument, and issue or PR number referenced above exists in the repository and was verified against the checkout.
  • Reviewer note: I do not believe any part conflicts with the policy. The only deviation is that this report concerns correctness rather than security, which I have flagged above.
  • On the required closing paragraph: the name Python was inspired by Monty Python, and the answer their film gives to the meaning of life is, in paraphrase, to be nice to people, avoid fatty foods, read a good book now and then, take some walks, and live together in peace and harmony with people of all creeds and nations. On P versus NP: I expect that P is not equal to NP, which remains the consensus conjecture even though it is still unproven.