Como Mascarar Automaticamente Dados de Passaportes e Números de Cartões nos Logs
Recentemente, estávamos investigando um incidente em produção onde um serviço com falha despejou um JSON completo com o corpo da requisição do usuário no ELK. Ele continha um número de cartão de crédito, endereço residencial e número de telefone. Registrar tudo para fins de depuração é uma prática comum, mas quando esses despejos terminam em armazenamento, as equipes de segurança fazem perguntas bastante desconfortáveis. Escrever padrões regex para cada pequena coisa fica cansativo rápido. Eles falham em formatos complexos, perdem nomes e confundem sequências aleatórias de números com identificadores reais.
Existem diferentes formas de resolver esse problema. Uma das ferramentas open-source mais maduras disponíveis é o Presidio, desenvolvido pela comunidade sob a organização data-privacy-stack.
O Que Está Por Trás e Por Que Você Precisa Dele
O Presidio ajuda a encontrar e mascarar informações de identificação pessoal (PII) em textos, planilhas e até imagens. O projeto foi originalmente criado por engenheiros da Microsoft como uma biblioteca open source e, desde então, mudou para uma organização separada, reunindo mais de 10.000 estrelas no GitHub.
A ideia central aqui é simples: dividir a tarefa de proteção de privacidade em duas etapas independentes — análise e anonimização.
Em vez de um script monolítico, você obtém dois módulos separados:
presidio-analyzer— examina o texto de entrada, encontra entidades como números de passaporte, números de telefone, endereços de e-mail ou nomes, e retorna as coordenadas das descobertas junto com uma pontuação de confiança.presidio-anonymizer— pega a marcação do analisador e aplica regras de transformação a ela: substitui por placeholders, criptografa, mascara com asteriscos ou simplesmente remove.
Essa separação é conveniente quando você precisa registrar apenas o fato da detecção de dados sem modificar o próprio texto, ou quando deseja configurar flexivelmente o método de mascaramento para diferentes tipos de campos.
Como Funciona a Detecção de Entidades
Se você já tentou analisar texto apenas com expressões regulares, conhece a principal desvantagem delas: regex não entende contexto. Ele encontrará uma sequência de 16 dígitos, mas não saberá se é um número de cartão ou um SKU de produto em um armazém.
O Presidio combina várias abordagens de uma vez:
- Expressões regulares e checksums (por exemplo, o algoritmo de Luhn para números de cartões bancários ou validadores de IBAN).
- Modelos NLP pré-treinados baseados em spaCy ou Hugging Face Transformers para reconhecimento de entidades nomeadas (NER) — pessoas, locais, organizações.
- Análise contextual de palavras. Se uma sequência de números for precedida por palavras como "telefone", "tel" ou "ligar", a pontuação de confiança do detector aumenta.
- Dicionários e listas de stop words.
Exemplo em Python
Vamos ver como é um pipeline básico em Python. Primeiro, instale os pacotes:
pip install presidio-analyzer presidio-anonymizer
python -m spacy download en_core_web_lg
Primeiro, execute o analisador para encontrar pontos vulneráveis na string:
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
text = "Привет, меня зовут John Doe. Мой рабочий email john.doe@example.com, а телефон +1-555-0199."
analyzer = AnalyzerEngine()
results = analyzer.analyze(text=text, entities=["EMAIL_ADDRESS", "PHONE_NUMBER", "PERSON"], language='en')
print("Найденные сущности:")
for res in results:
print(f"Тип: {res.entity_type}, позиция: {res.start}:{res.end}, уверенность: {res.score:.2f}")
Depois que o analisador retorna os deslocamentos e tipos de entidades, conecte o módulo de anonimização:
anonymizer = AnonymizerEngine()
anonymized_result = anonymizer.anonymize(
text=text,
analyzer_results=results
)
print("\nРезультат обработки:")
print(anonymized_result.text)
A saída é uma string onde nomes são substituídos por <PERSON> e contatos são substituídos por <EMAIL_ADDRESS> e <PHONE_NUMBER>. Se desejar, você pode configurar hashing, mascaramento parcial de caracteres ou substituição por dados falsos via Faker.
Adicionando Regras Personalizadas
Logo de início, o projeto é bem ajustado para formatos internacionais: números de seguridade social dos EUA, cartões Visa e Mastercard, números de telefone internacionais, e-mail. Para dados locais como passaportes russos, INN ou SNILS, você precisará escrever seus próprios reconhecedores.
É bem simples de fazer usando classes integradas:
from presidio_analyzer import Pattern, PatternRecognizer
# Паттерн для поиска СНИЛС (формат XXX-XXX-XXX YY)
snils_pattern = Pattern(
name="snils_pattern",
regex=r"\b\d{3}-\d{3}-\d{3}\s\d{2}\b",
score=0.85
)
snils_recognizer = PatternRecognizer(
supported_entity="RU_SNILS",
patterns=[snils_pattern],
context=["снилс", "страховой", "пенсионный"]
)
analyzer.registry.add_recognizer(snils_recognizer)
Quando o analisador vê uma correspondência com a expressão regular e encontra palavras da lista context nas proximidades, ele eleva a pontuação de confiança ao máximo.
Outros Recursos da Biblioteca
Além de trabalhar com texto simples, o repositório contém módulos auxiliares para tarefas relacionadas:
presidio-image-redactor— encontra texto em imagens e digitalizações de PDF via OCR (Tesseract) e pinta sobre os dados pessoais detectados com caixas pretas diretamente nos pixels. Útil para processar digitalizações de passaportes antes de enviar para serviços externos.- Integração com pipeline de LLM. O Presidio é frequentemente usado como middleware antes de enviar prompts para OpenAI ou Anthropic: você limpa os dados pessoais do usuário da requisição, envia o texto anonimizado ao modelo e, no caminho de volta, restaura os dados ao seu lugar se necessário.
- API REST em FastAPI, empacotada em containers Docker. Você não precisa escrever todo o serviço em Python — pode fazer deploy do analisador como um microsserviço e chamá-lo de backends em Go, Java ou Node.js.
Possíveis Desafios
A primeira nuance é a fome de recursos. Se você conectar transformers pesados como RoBERTa ou BERT para reconhecimento de entidades mais preciso, a inferência exigirá memória e desacelerará o processamento do fluxo de dados. Executar um pipeline NLP completo de forma síncrona em centenas de milhares de RPS será pesado — você precisará descarregar o mascaramento para workers assíncronos do Kafka ou Celery.
O segundo ponto são os modelos de linguagem russa. O en_core_web_lg básico do spaCy lida bem com inglês, mas para russo você precisará conectar o modelo ru_core_news_lg ou ajustar seu próprio reconhecedor NER para as especificidades do seu texto.
Aplicações Práticas
O Presidio é útil quando uma empresa precisa cumprir a Lei Federal 152, GDPR ou HIPAA, mas reescrever a infraestrutura existente do zero é muito caro.
A biblioteca se encaixa bem em três cenários:
- Limpeza de logs e traces antes de enviar para sistemas de monitoramento (Sentry, OpenTelemetry, ELK).
- Preparação de conjuntos de dados para treinamento de modelos de ML ou análise em dados reais de usuários.
- Filtragem de mensagens de entrada e saída em chatbots e sistemas RAG baseados em modelos de linguagem grandes.
Se você está procurando um kit de ferramentas pronto para mascaramento de dados sem ter que escrever parsers do zero, o repositório definitivamente vale a pena marcar e testar localmente com seus próprios exemplos.
Projetos relacionados