Bỏ qua tới nội dung

Kỹ thuật

Lọc PII trong error monitoring mà không mất ngữ cảnh

Mình chạy bộ lọc của Belvador trên 16 mẫu lỗi giả lập, sửa ba lỗ hổng là lỗi của chính mình rồi chạy lại. Secret có hình dạng quen thuộc đều bị xoá; số điện thoại và tên người vẫn lọt.

Andrew Babo7 phút đọc

Chia sẻ
Trong bài này
Lọc PII trong error monitoring mà không mất ngữ cảnh

Bộ lọc tự động trong error monitoring giỏi đúng một việc: secret có hình dạng dễ nhận ra. API key, token, JWT, số thẻ và mật khẩu trong URL đều có mẫu để một luật bắt được. Dữ liệu cá nhân không có hình dạng cố định, như tên người hay số điện thoại trong nước, thì lọt qua, còn luật dựa trên tên key lại xoá cả thứ bạn muốn giữ.

Mình đo cả hai chuyện vào ngày 26/10/2026. Mình chạy chính bộ lọc trên node của Belvador, bật mọi luật, trên 16 mẫu giả lập, và ghi ra trước những gì một người cẩn thận muốn xoá. Ba chỗ bị sót là lỗi trong luật của chính mình, nên mình sửa rồi chạy lại đúng các mẫu đó với code đã phát hành thành node 0.1.30.

Vì sao cần bộ lọc#

Báo cáo lỗi cố tình gom ngữ cảnh, mà ngữ cảnh gồm mọi thứ đang nằm trong bộ nhớ lúc hỏng. Sentry chẳng hạn bật sẵn bộ lọc phía server: “Data scrubbing is enabled by default and we highly recommend you keep it that way.” Hướng dẫn của OpenTelemetry nói rõ giới hạn: một công cụ “can’t determine what data is sensitive in your specific context on its own”, tức tự nó không biết dữ liệu nào nhạy cảm trong bối cảnh của bạn.

Vậy là có hai việc. Bộ lọc chung xoá những thứ trông nguy hiểm ở mọi nơi. Code của bạn xoá những thứ nhạy cảm trong chính ứng dụng của bạn.

16 mẫu thử#

Bộ lọc đã làm gì với từng mẫu trong 16 mẫu, ở lần chạy đầu và sau khi sửa
Thí nghiệm 26/10/2026 · bộ lọc trên node của Belvador, bật mọi nhóm · lần đầu và node 0.1.30
MẫuMong muốnLần đầuSau khi sửa (node 0.1.30)
Email trong message lỗixoáxoá phần tên, giữ tên miềnnhư cũ
JWT trong messagexoáđã xoánhư cũ
Key sk_live_… trong messagexoáđã xoánhư cũ
Số thẻ hợp lệ theo Luhnxoáđã xoánhư cũ
16 chữ số không hợp lệ theo Luhngiữđã giữnhư cũ
?token= trong URLxoáđã xoá, giữ order=ORD-42như cũ
email=linh%40example.test trong queryxoávẫn giữ: dấu @ bị mã hoá thành %40xoá phần tên
Authorization: Basic … trong chữxoáđã xoánhư cũ
https://user:pass@hostxoá cả haixoá mật khẩu, giữ tên đăng nhậpxoá cả hai
phone=0912345678 trong breadcrumbxoávẫn giữvẫn giữ
Tên người và số +84 trong một ghi chúxoávẫn giữvẫn giữ
Địa chỉ IP nằm trong một câuxoávẫn giữsố cuối thành 0
Địa chỉ IP là giá trị của một trườngchesố cuối thành 0: 192.0.2.0như cũ
order_id, trace_id, status, retriesgiữđã giữnhư cũ
author, session_count, token_countgiữcả ba bị lọccả ba bị lọc
password, api_key, sessionxoáđã xoánhư cũ

Mười ba mẫu lẽ ra phải mất bớt dữ liệu. Ở lần đầu, bảy mẫu được làm sạch hoàn toàn và một mẫu được che đúng thiết kế; hai mẫu chỉ sạch một phần, ba mẫu bị bỏ sót. Sau khi sửa, chín mẫu sạch hoàn toàn, hai mẫu được che, và chỉ hai mẫu có số điện thoại là còn lọt. Cả hai mẫu cần giữ đều được giữ ở cả hai lần, và vẫn là ba key vô hại đó bị lọc mất.

Những chỗ bị sót có điểm chung#

Bốn mẫu trước và sau khi lọc, ở lần đầu và sau bản sửa
Thí nghiệm 26/10/2026 · lần chạy nào cũng ra cùng kết quả · lần đầu và node 0.1.30

Những chỗ bị sót không có hình dạng nào để một luật chung dựa vào.

  • Số điện thoại có rất nhiều cách viết. Một luật đủ rộng để bắt cả 0912345678 lẫn +84 912 345 678 sẽ ăn luôn mã đơn hàng, mốc thời gian và ID.
  • Tên người chỉ là chữ. Không mẫu nào phân biệt được “Nguyễn Văn An” với tên một sản phẩm.
  • Email bị mã hoá có đúng hình dạng, nhưng chỉ sau khi giải mã. Lần đầu, bộ lọc so với chữ thô.
  • IP trong câu bị bỏ qua vì lần đầu bộ lọc chỉ che IP khi cả giá trị là một địa chỉ IP.

Email bị mã hoá, tên đăng nhập trong URL và IP trong câu là lỗ hổng trong luật của chính mình, và node 0.1.30 đã vá (SDK 0.4.1 vá luôn phần email và IP): bộ lọc giờ đọc %40 như @, bỏ cả phần user:pass@ trong URL, và đổi số cuối của địa chỉ IPv4 public trong câu thành 0. Địa chỉ nội bộ như 10.0.3.17 vẫn giữ nguyên, vì chúng giúp debug mà không chỉ ra ai cả. Tên người và số điện thoại thì lúc nào cũng cần code của bạn giúp.

Vì sao key vô hại biến mất#

Luật theo tên key hoạt động kiểu “có chứa”: key nào có auth, session hay token trong tên đều bị lọc. Nhờ vậy nó bắt được user_auth_header và sessionToken, đúng như bạn muốn. Nhưng nó cũng bắt luôn author, session_count và token_count, thứ bạn không hề muốn.

Đánh đổi này là có chủ ý: bộ lọc để lọt một secret thì tệ hơn bộ lọc giấu mất một con số đếm. Nếu một trường quan trọng cho việc debug, hãy đổi tên nó, ví dụ llm_tokens_used thành llm_usage_units, hoặc giữ nó trong một tag mà team đã kiểm tra.

Nên tự thêm gì trong code#

SDK báo lỗi có một hook chạy trước khi gửi bất cứ thứ gì. Tài liệu của Sentry mô tả beforeSend là hook “can be used, for instance, for manual PII stripping before sending”, tức dùng được để tự xoá PII trước khi gửi. Hãy dùng nó cho những thứ chỉ ứng dụng của bạn biết:

  • Thay object user bằng một ID nội bộ. Đừng bao giờ gửi email hay tên làm thông tin user.
  • Xoá các trường chữ tự do bạn thu thập: ghi chú, địa chỉ, tin nhắn, từ khoá tìm kiếm.
  • Chuẩn hoá số điện thoại theo định dạng của bạn rồi che đi.
  • Giải mã query string trước khi chạy các kiểm tra của riêng bạn.
  • Giữ lại những gì giúp debug mà không phải dữ liệu cá nhân: mã đơn, trace ID, mã trạng thái, số lần thử lại, feature flag.

Chỉ thử bằng giá trị giả. Danh sách những thứ không bao giờ được ghi log của OWASP mở đầu bằng “Authentication passwords Database connection strings Encryption keys”; một bài test dùng giá trị thật là đã làm lộ nó rồi.

Belvador giúp ở đâu#

Belvador lọc hai lần: SDK làm sạch event trước khi rời ứng dụng, ngay sau khi beforeSend của bạn chạy, rồi node của bạn lọc lại bằng bộ luật viết riêng trước khi lưu bất cứ thứ gì. Trang bảo vệ dữ liệu liệt kê mọi luật và những trường hợp không bộ lọc nào đảm bảo được, còn trang cấu hình SDK chỉ chỗ đặt beforeSend. Event đã lọc được lưu trên một node trong chính dự án Hetzner của bạn, như trang BYOC trên Hetzner giải thích, còn trang bảo mật nói về các biện pháp kiểm soát còn lại của Belvador.

Đọc tiếp#

Andrew Babo

Nhà sáng lập

Thuộc bài hướng dẫn: Gửi lỗi production cho LLM thế nào cho an toàn

Mọi bài viết

Hướng dẫn

Gửi lỗi production cho LLM thế nào cho an toàn

Một event lỗi chứa secret, dữ liệu cá nhân và chữ người dùng gõ vào. Mình gửi một event có lệnh ẩn cho bốn model 72 lần; dán nguyên văn, một model làm theo cả sáu lần và có lần khuyên tắt xác thực.

Andrew Babo8 phút đọc

Đọc tiếp trong tài liệu

Xem lỗi production của chính bạn như thế này

Belvador chạy trên máy chủ Hetzner của chính bạn: lỗi, cron, uptime và trace — dữ liệu vẫn là của bạn.