Salvaguardia GDPR: oscurare codice fiscale, telefono e IBAN
Salvaguardia GDPR che oscura codice fiscale (con controllo), telefoni +39, IBAN ed email personali nelle risposte di un assistente IA. 12 test.
Regeln
Oscurare prima dell'invio qualsiasi dato che identifichi o renda contattabile una persona: - indirizzi email personali (mario.rossi@…); - numeri di telefono italiani, con o senza +39; - IBAN italiani; - codici fiscali (si verifica il carattere di controllo). Lasciar passare: indirizzi generici (info@, assistenza@…), nomi di aziende, importi, date, numeri d'ordine.
Testfälle
| Eingabe | Erwartet |
|---|---|
| Può scrivere a mario.rossi@gmail.com per aggiornamenti. | Blockieren |
| Il mio cellulare è 347 123 4567. | Blockieren |
| Mi chiami al +39 06 1234 5678 domani. | Blockieren |
| Bonifico su IT60 X054 2811 1010 0000 0123 456. | Blockieren |
| Codice fiscale: RSSMRA85T10A562S. | Blockieren |
| Fattura da inviare a giulia.bianchi@azienda.it. | Blockieren |
| Scriva ad assistenza@contextetech.com per qualsiasi domanda. | Zulassen |
| Il suo ordine n. 458712 parte domani. | Zulassen |
| L'importo è di 1.250,00 € IVA inclusa. | Zulassen |
| Appuntamento il 12/10/2026 alle 14. | Zulassen |
| L'azienda Costruzioni Esposito S.r.l. ha accettato il preventivo. | Zulassen |
| Buongiorno, come posso aiutarla? | Zulassen |
Code
import re
SCHEMI = {
"email": r"[\w.+-]+@[\w-]+\.[\w.-]+",
"telefono": r"(?:\+39[\s.-]?)?\b(?:3\d{2}|0\d{1,3})[\s.-]?\d{3,4}[\s.-]?\d{3,4}\b",
"iban": r"\bIT\d{2}\s?[A-Z]\d{3}(?:\s?[\dA-Z]{4}){5}\b",
"codice_fiscale": r"\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b",
}
GENERICI = ("info@", "contatti@", "assistenza@", "supporto@", "ciao@")
DISPARI = dict(zip("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
[1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23]))
def codice_fiscale_valido(cf: str) -> bool:
"""Il sedicesimo carattere è il carattere di controllo calcolato sui primi quindici."""
cf = cf.upper()
somma = sum(DISPARI[c] if i % 2 == 0 else (int(c) if c.isdigit() else ord(c) - 65) for i, c in enumerate(cf[:15]))
return chr(65 + somma % 26) == cf[15]
def mascherare(testo: str) -> tuple[str, bool]:
"""Sostituisce i dati personali con [<tipo> oscurato]; restituisce il testo e True se qualcosa è stato oscurato."""
trovato = False
for tipo, schema in SCHEMI.items():
def sostituire(m):
nonlocal trovato
valore = m.group(0)
if tipo == "email" and valore.lower().startswith(GENERICI):
return valore
if tipo == "codice_fiscale" and not codice_fiscale_valido(valore):
return valore
trovato = True
return f"[{tipo} oscurato]"
testo = re.sub(schema, sostituire, testo)
return testo, trovatoGeschätzte Kosten
Eingabe-Tokens pro Aufruf : ≈ 1.007
| Modell | Pro Aufruf | Pro 1.000 Aufrufe |
|---|---|---|
| Mistral Large · Mistral AI | 0,00044 € | 0,44 € |
| DeepSeek Flash · DeepSeek | 0,00027 € | 0,27 € |
| DeepSeek V4 Pro · DeepSeek | 0,00117 € | 1,17 € |
| GPT-6 Luna · OpenAI | 0,00009 € | 0,09 € |
| GPT-6 Sol · OpenAI | 0,00177 € | 1,77 € |
| Claude Sonnet 5.5 · Anthropic | 0,00177 € | 1,77 € |
| Claude Opus 5.5 · Anthropic | 0,00355 € | 3,55 € |
| Selbst gehostetes Open-Source-Modell (Ollama, vLLM) | 0 € API-Kosten (nur Serverkosten) | |
Nur Eingabekosten, ohne die Antwort des Modells. Öffentliche Standardpreise der Anbieter (Mistral AI, DeepSeek, OpenAI, Anthropic) von USD in Euro umgerechnet zum EZB-Kurs vom 29. September 2026. Schätzung: 1 Token ≈ 3,6 Zeichen.
Common to all 3 regions
Created by the author, no outside source.
Commercial use allowed · credit the author · changes allowed.
Text or data only: no access to files, network or commands.
Hosted in France (Scaleway, Paris). No transfer outside the EU.
European Union · 5/5
Fictional: invented names, addresses and numbers, no real person.
No training data: no summary required.
United States · 5/5
Fictional: invented names, addresses and numbers, no real person.
No training data: no documentation to publish.
China · 5/5
Fictional: invented names, addresses and numbers, no real person.
No training data; AI-generated content published in China must be labelled (2025).
Indicative summary as of 30/09/2026, not a legal certification. Method and sources →
Statistiken
Gefällt mir : 0 · Kommentare : 0
Klicken Sie auf einen Zähler, um ihn ein- oder auszublenden; fahren Sie über das Diagramm für Details. Ein Aufruf pro Besucher und Tag, ohne Bots; Zählung seit dem 30. September 2026.
- Kennung
- contextetech--oscurare-dati-personali-gdpr
- Typ
- Schutzregeln
- Datei
- oscurare-dati-personali-gdpr.guardrail.json
- Format
- JSON (application/json)
- Größe
- 2.029 Bytes (2 KB)
- Kodierung
- UTF-8
- Geschätzte Tokens
- ≈ 561
- Sprache
- Italienisch
- Lizenz
- MIT
- Kommerzielle Nutzung
- Erlaubt
- Personenbezogene Daten
- Fiktiv (erfunden)
- Version
- 1.0
- Veröffentlicht am
- 3. Oktober 2026 um 05:20
- Aktualisiert am
- 3. Oktober 2026 um 05:20
- Speicherung
- in der Datenbank
- Nutzungen
- 0
- Gefällt mir
- 0
oscurare-dati-personali-gdpr.guardrail.json
{
"format": "contextetech/guardrail/v1",
"id": "contextetech/oscurare-dati-personali-gdpr",
"description": "Salvaguardia GDPR che oscura codice fiscale (con controllo), telefoni +39, IBAN ed email personali nelle risposte di un assistente IA. 12 test.",
"tags": [
"gdpr",
"dati-personali",
"sicurezza"
],
"license": "MIT",
"language": "it",
"type": "pii",
"action": "mask",
"rules": "Oscurare prima dell'invio qualsiasi dato che identifichi o renda contattabile una persona:\n- indirizzi email personali (mario.rossi@…);\n- numeri di telefono italiani, con o senza +39;\n- IBAN italiani;\n- codici fiscali (si verifica il carattere di controllo).\nLasciar passare: indirizzi generici (info@, assistenza@…), nomi di aziende, importi, date, numeri d'ordine.",
"cases": [
{
"input": "Può scrivere a mario.rossi@gmail.com per aggiornamenti.",
"expected": "block"
},
{
"input": "Il mio cellulare è 347 123 4567.",
"expected": "block"
},
{
"input": "Mi chiami al +39 06 1234 5678 domani.",
"expected": "block"
},
{
"input": "Bonifico su IT60 X054 2811 1010 0000 0123 456.",
"expected": "block"
},
{
"input": "Codice fiscale: RSSMRA85T10A562S.",
"expected": "block"
},
{
"input": "Fattura da inviare a giulia.bianchi@azienda.it.",
"expected": "block"
},
{
"input": "Scriva ad assistenza@contextetech.com per qualsiasi domanda.",
"expected": "allow"
},
{
"input": "Il suo ordine n. 458712 parte domani.",
"expected": "allow"
},
{
"input": "L'importo è di 1.250,00 € IVA inclusa.",
"expected": "allow"
},
{
"input": "Appuntamento il 12/10/2026 alle 14.",
"expected": "allow"
},
{
"input": "L'azienda Costruzioni Esposito S.r.l. ha accettato il preventivo.",
"expected": "allow"
},
{
"input": "Buongiorno, come posso aiutarla?",
"expected": "allow"
}
]
}Text prüfen (Python)
import re
SCHEMI = {
"email": r"[\w.+-]+@[\w-]+\.[\w.-]+",
"telefono": r"(?:\+39[\s.-]?)?\b(?:3\d{2}|0\d{1,3})[\s.-]?\d{3,4}[\s.-]?\d{3,4}\b",
"iban": r"\bIT\d{2}\s?[A-Z]\d{3}(?:\s?[\dA-Z]{4}){5}\b",
"codice_fiscale": r"\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b",
}
GENERICI = ("info@", "contatti@", "assistenza@", "supporto@", "ciao@")
DISPARI = dict(zip("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
[1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23]))
def codice_fiscale_valido(cf: str) -> bool:
"""Il sedicesimo carattere è il carattere di controllo calcolato sui primi quindici."""
cf = cf.upper()
somma = sum(DISPARI[c] if i % 2 == 0 else (int(c) if c.isdigit() else ord(c) - 65) for i, c in enumerate(cf[:15]))
return chr(65 + somma % 26) == cf[15]
def mascherare(testo: str) -> tuple[str, bool]:
"""Sostituisce i dati personali con [<tipo> oscurato]; restituisce il testo e True se qualcosa è stato oscurato."""
trovato = False
for tipo, schema in SCHEMI.items():
def sostituire(m):
nonlocal trovato
valore = m.group(0)
if tipo == "email" and valore.lower().startswith(GENERICI):
return valore
if tipo == "codice_fiscale" and not codice_fiscale_valido(valore):
return valore
trovato = True
return f"[{tipo} oscurato]"
testo = re.sub(schema, sostituire, testo)
return testo, trovato
Community
Noch keine Kommentare. Teile deine Erfahrung, sie hilft den Nächsten.