KI: PRAKTEK 11: AI untuk Audit Data Pribadi
PRAKTEK 11: AI untuk Audit Data Pribadi Di dunia nyata, kebocoran data sering bukan karena hacker super canggih—tapi karena data pribadi “nyangkut” di tempat yang tidak seharusnya: file CSV di folder proyek, log aplikasi, backup SQL lama, export Excel, atau chat yang dipaste ke dokumen. Di sesi ini, mahasiswa akan bikin tool audit yang bertindak seperti “robot auditor”: ia masuk ke folder data, membaca file satu per satu, lalu mendeteksi PII (Personally Identifiable Information), memberi skor risiko, dan menghasilkan laporan. Mindset penting: Audit itu kebiasaan (continuous), bukan tugas akhir semester. Target kita bukan “sempurna”, tapi lebih aman tiap iterasi. Tujuan Mahasiswa mampu: Mendesian pipeline audit data: scan → detect → classify → report → protect Mendeteksi PII dengan pendekatan Regex + NLP/ML ringan Memberi risk score untuk membantu prioritas perbaikan Menghasilkan AI Data Scanner (CLI tool) + laporan JSON/CSV Melakukan langkah “tindak lanjut” menggunakan GnuPG: enkripsi / redaksi Konsep: PII Detection (Realistic) PII adalah data yang bisa mengidentifikasi seseorang, baik langsung maupun kombinasi. Contoh PII yang sering ditemukan di data kampus/perusahaan: Email (nama@domain) Nomor HP (08xx… / +62…) NIK (16 digit, kadang dipisah spasi/strip) No. Rekening (variasi panjang) Alamat (lebih sulit—banyak variasi) IP address (bukan selalu PII, tapi bisa sensitif) API token / session token (bukan PII, tapi sensitif) Trik audit yang benar: Deteksi bukan hanya “ada email”, tapi juga konteks: Email muncul di data “publik” → risiko sedang Email + NIK + tanggal lahir → risiko tinggi Token API di log → risiko kritikal Tools (Open Source) 1. Python (Utama) re untuk regex json, csv, pathlib (opsional) scikit-learn untuk ML ringan (opsional) spacy untuk NLP (bisa berat, tapi open-source) 2. GnuPG (GNU Privacy Guard) Dipakai untuk “aksi setelah audit”: enkripsi file yang mengandung PII sign laporan audit (integritas) dekripsi saat perlu akses aman Tahap Praktikum (Step-by-step) Tahap 0 — Setup Environment (Ubuntu 24.04) Jalankan: sudo apt update sudo apt install -y python3 python3-venv python3-pip gnupg jq python3 -m venv venv source venv/bin/activate pip install --upgrade pip Buat folder proyek: mkdir -p ai_auditor/{data,output} Tahap 1 — Siapkan Dataset Contoh (Realistic) Buat file data/sample.txt: cat > data/sample.txt << 'EOF' Nama: Budi Santoso Email: budi.santoso@gmail.com NIK: 3174012301990002 HP: +62 812-3456-7890 Alamat: Jl. Melati No. 10, Tangerang Selatan Catatan: reset token = sk_live_51Hxxxxxxx IP Login: 103.10.20.30 EOF
Buat juga contoh CSV data/mahasiswa.csv: cat > data/mahasiswa.csv << 'EOF' nama,email,nik,no_hp Ayu,ayu@kampus.ac.id,3174020101010003,081234567890 Doni,doni@gmail.com,3174030202020004,628123111222 EOF Tahap 2 — Bangun “AI Data Scanner” Versi 1 (Regex Engine) Buat file ai_auditor.py:
- !/usr/bin/env python3
import re import json from pathlib import Path from datetime import datetime
- --- Pola PII (sengaja sederhana dulu, nanti bisa ditingkatkan) ---
PATTERNS = {
"EMAIL": re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b"),
"PHONE_ID": re.compile(r"\b(\+62\s?8\d{2}[-\s]?\d{3,4}[-\s]?\d{3,4}|\b08\d{8,12}\b|\b62\d{9,13}\b)"),
"NIK_ID": re.compile(r"\b\d{16}\b"),
"IP_ADDR": re.compile(r"\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\b"),
# Token contoh (jangan terlalu agresif biar tidak banyak false positive)
"API_TOKEN": re.compile(r"\b(sk_live|sk_test|token|apikey|api_key|bearer)\S{6,}\b", re.IGNORECASE),
}
- Bobot risiko (bisa disesuaikan)
RISK_WEIGHT = {
"EMAIL": 2, "PHONE_ID": 3, "NIK_ID": 5, "IP_ADDR": 1, "API_TOKEN": 6,
}
def classify_risk(found_types):
score = sum(RISK_WEIGHT.get(t, 0) for t in found_types)
if score >= 10:
return score, "HIGH"
if score >= 5:
return score, "MEDIUM"
return score, "LOW"
def scan_text(text):
findings = []
found_types = set()
for t, rx in PATTERNS.items():
matches = rx.findall(text)
if matches:
found_types.add(t)
# Normalisasi hasil findall (kadang tuple)
norm = []
for m in matches:
norm.append(m[0] if isinstance(m, tuple) else m)
findings.append({
"type": t,
"count": len(norm),
"samples": list(dict.fromkeys(norm))[:3], # max 3 sample unik
})
score, level = classify_risk(found_types)
return findings, score, level
def read_file(path: Path):
# Baca sebagai text "best effort"
try:
return path.read_text(encoding="utf-8", errors="replace")
except Exception:
return ""
def main(input_dir="data", output_dir="output"):
input_path = Path(input_dir) out_path = Path(output_dir) out_path.mkdir(parents=True, exist_ok=True)
report = {
"generated_at": datetime.utcnow().isoformat() + "Z",
"scanned_dir": str(input_path.resolve()),
"files": [],
"summary": {"total_files": 0, "flagged_files": 0, "by_level": {"LOW": 0, "MEDIUM": 0, "HIGH": 0}},
}
for p in input_path.rglob("*"):
if not p.is_file():
continue
# Filter file sederhana (bisa diperluas)
if p.suffix.lower() not in [".txt", ".csv", ".log", ".json"]:
continue
text = read_file(p)
findings, score, level = scan_text(text)
report["summary"]["total_files"] += 1
file_entry = {
"path": str(p),
"size_bytes": p.stat().st_size,
"risk_score": score,
"risk_level": level,
"findings": findings,
}
if findings:
report["summary"]["flagged_files"] += 1
report["summary"]["by_level"][level] += 1
report["files"].append(file_entry)
# Simpan laporan out_file = out_path / "audit_report.json" out_file.write_text(json.dumps(report, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"[OK] Report saved: {out_file}")
print(json.dumps(report["summary"], indent=2))
if __name__ == "__main__":
main()
Jalankan: chmod +x ai_auditor.py ./ai_auditor.py Cek laporan: cat output/audit_report.json | jq .
Tahap 3 — “Tandai Risiko” + Output yang Bisa Dipakai (CSV Ringkas) Tambahkan output ringkas output/audit_summary.csv (ini real dipakai tim audit). Buat file export_summary.py:
- !/usr/bin/env python3
import json import csv from pathlib import Path
def main(report_path="output/audit_report.json", out_csv="output/audit_summary.csv"):
report = json.loads(Path(report_path).read_text(encoding="utf-8"))
rows = []
for f in report["files"]:
if not f["findings"]:
continue
types = ",".join(x["type"] for x in f["findings"])
rows.append([f["path"], f["risk_level"], f["risk_score"], types, f["size_bytes"]])
with open(out_csv, "w", newline="", encoding="utf-8") as fp:
w = csv.writer(fp)
w.writerow(["path", "risk_level", "risk_score", "finding_types", "size_bytes"])
w.writerows(rows)
print(f"[OK] CSV saved: {out_csv}")
if __name__ == "__main__":
main()
Run: chmod +x export_summary.py ./export_summary.py column -t -s, output/audit_summary.csv
Tahap 4 — Upgrade ke “Regex + ML ringan” (Opsional tapi Keren)
Regex bagus untuk pola tetap (email, NIK). Tapi untuk alamat / nama / kalimat sensitif, kita butuh ML sederhana.
Konsep ML ringan yang realistis untuk kelas:
Kita bikin text classifier yang menentukan kalimat termasuk “sensitif” atau “tidak”
Model: Logistic Regression / Linear SVM
Fitur: TF-IDF
Install:
pip install scikit-learn
Buat file ml_sensitive_classifier.py:
- !/usr/bin/env python3
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression
- Dataset mini (contoh). Di kelas, mahasiswa harus menambah data sendiri.
TRAIN_TEXT = [
"NIK saya 3174012301990002", "Nomor HP saya 081234567890", "Email saya budi@gmail.com", "Token reset: sk_live_123xxx", "Alamat saya Jl. Melati No. 10", "Hari ini cuaca cerah", "Saya suka belajar keamanan informasi", "Meeting jam 2 siang",
] TRAIN_LABEL = [1,1,1,1,1,0,0,0] # 1 = sensitif, 0 = non-sensitif
def build_model():
vec = TfidfVectorizer(ngram_range=(1,2)) X = vec.fit_transform(TRAIN_TEXT) clf = LogisticRegression(max_iter=200) clf.fit(X, TRAIN_LABEL) return vec, clf
def predict_lines(lines, threshold=0.6):
vec, clf = build_model()
X = vec.transform(lines)
proba = clf.predict_proba(X)[:,1]
results = []
for line, p in zip(lines, proba):
results.append((line, float(p), "SENSITIVE" if p >= threshold else "OK"))
return results
if __name__ == "__main__":
test = [
"Silakan kirim NIK dan nomor HP untuk verifikasi",
"Jangan lupa rapat jam 3",
"Password admin adalah admin123",
"Email saya ayu@kampus.ac.id",
]
for line, p, label in predict_lines(test):
print(f"{label}\t{p:.2f}\t{line}")
Ini bukan “AI super”, tapi realistic ML pipeline yang bisa dibesarkan dataset-nya. Tahap 5 — Aksi Setelah Audit dengan GnuPG Audit tanpa aksi = cuma “tahu masalah”. Sekarang kita lakukan aksi aman. 1. Generate Key (untuk kelas, pakai mode cepat)
gpg --full-generate-key Cek key: gpg --list-keys
2. Enkripsi Laporan Audit Enkripsi file laporan supaya aman saat dikirim ke dosen/tim: gpg -c output/audit_report.json Hasilnya: output/audit_report.json.gpg Dekripsi: gpg -d output/audit_report.json.gpg > output/audit_report.decrypted.json 3. Sign Laporan (Integritas) Ini penting untuk audit: laporan harus bisa dibuktikan tidak diubah. gpg --clearsign output/audit_summary.csv Hasil: output/audit_summary.csv.asc Verifikasi: gpg --verify output/audit_summary.csv.asc Output yang Wajib Dikumpulkan (Sesuai Modul) Mahasiswa menyerahkan: ai_auditor.py (AI data scanner) output/audit_report.json (detail) output/audit_summary.csv (ringkas) output/audit_report.json.gpg (enkripsi) output/audit_summary.csv.asc (signature) Laporan singkat (1–2 halaman) berisi: Temuan PII paling sering File paling berisiko Rekomendasi perbaikan Challenge (Fun & Menantang) Pilih minimal 2: Tambah deteksi PII lain: NPWP / Passport / KK (buat regex-nya) Buat fitur redaction: output file versi “tersensor” (contoh: email jadi ***@***) Buat rule “HIGH jika NIK + email muncul di file yang sama” Buat whitelist domain email kampus (mis. @kampus.ac.id) dan beri skor lebih rendah Tambah deteksi “leak token” dengan pola lebih baik Bonus: Redaction (Contoh Kode yang Real Dipakai) Buat redact.py:
- !/usr/bin/env python3
import re from pathlib import Path
EMAIL = re.compile(r"\b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Za-z]{2,})\b") NIK = re.compile(r"\b\d{16}\b") PHONE = re.compile(r"\b(\+62\s?8\d{2}[-\s]?\d{3,4}[-\s]?\d{3,4}|\b08\d{8,12}\b|\b62\d{9,13}\b)")
def redact_text(t: str) -> str:
t = EMAIL.sub(r"***@\1", t)
t = NIK.sub("****************", t)
t = PHONE.sub("***REDACTED_PHONE***", t)
return t
def main(infile="data/sample.txt", outfile="output/sample.redacted.txt"):
p = Path(infile)
text = p.read_text(encoding="utf-8", errors="replace")
out = redact_text(text)
Path(outfile).write_text(out, encoding="utf-8")
print(f"[OK] Redacted saved: {outfile}")
if __name__ == "__main__":
main()
Run: chmod +x redact.py ./redact.py cat output/sample.redacted.txt