Bảo vệ dữ liệu và lọc thông tin nhạy cảm
Những gì SDK và node tự xoá hoặc che, những gì không thể đảm bảo, và cách kiểm tra an toàn.
Trong bài này
Báo cáo lỗi có thể mang theo những thứ bạn không hề định thu thập: mật khẩu trong một ô nhập liệu, token trong URL, email trong một câu thông báo. Belvador lọc ở hai lớp độc lập — trong ứng dụng của bạn và trên node của bạn — và giữ dữ liệu trong chính project Hetzner của bạn. Lọc giúp giảm rủi ro; không xoá được rủi ro.
Dữ liệu của bạn đi đâu#
| Nơi | Chứa gì | Ai đọc được |
|---|---|---|
| Ứng dụng của bạn | Event trước khi gửi; SDK lọc trước | Code của bạn |
Edge của Belvador (ingest.belvador.dev) | Event đang trên đường đi. Nếu node mất kết nối, một bản đã niêm phong bằng khoá của node được giữ tạm tới 14 ngày | Chỉ node của bạn mở được dữ liệu đã niêm phong |
Edge của Belvador (edge.belvador.dev) | Không lưu gì. Khi người trong workspace mở lỗi, trace hay log, edge chuyển dữ liệu từ node tới trình duyệt của họ trong bộ nhớ, sau khi kiểm vé ngắn hạn | Không ai — không giữ lại gì |
| Node của bạn, trong project Hetzner của bạn | Event, issue, tệp đính kèm, source map — được lọc lại trước khi lưu | Người trong workspace của bạn, qua ứng dụng |
| Phần điều khiển của Belvador | Thông tin tài khoản, workspace, project, cấu hình và số đếm | Belvador, để vận hành dịch vụ |
Dịch vụ heartbeat của Belvador (ping.belvador.dev) | Chỉ cho monitor ping URL: dấu vân tay của từng ping URL, tín hiệu nào tới và lúc nào, hạn chờ và trạng thái sự cố — không bao giờ có body, header hay địa chỉ IP (output job gửi kèm đi về node của bạn, như một event) | Belvador, để vẫn báo khi mất ping ngay cả lúc node của bạn ngừng |
| Webhook của chính bạn | Nếu bạn thêm: metadata của cảnh báo (tên, mã, thời điểm, link dashboard), có chữ ký — xem Webhook tự cấu hình | Người vận hành địa chỉ đó |
| Backup trong Cloudflare R2 | Bản sao đã mã hoá của dữ liệu node | Người giữ khoá backup — xem Backup |
Event được giữ theo thời hạn lưu của gói (mặc định 30 ngày); số liệu tổng hợp theo ngày giữ 13 tháng.
Lớp 1 — SDK, trước khi bất cứ thứ gì rời ứng dụng#
SDK của Belvador (@belvador/*) luôn:
xoá các header
Authorization,Proxy-Authorization,Cookie,Set-Cookie,X-Forwarded-For,X-Real-IP,X-Client-IP,CF-Connecting-IP,True-Client-IPvàForwarded;xoá body request, cookie và dữ liệu môi trường trong thông tin request;
chỉ giữ
user.idtrong dữ liệu người dùng (tối đa 128 ký tự) — email, tên và địa chỉ IP bị bỏ;che thành
[Filtered]mọi giá trị nằm dưới tên nhạy cảm — tên chứapassword,passwd,pwd,secret,api_key/apikey,access_token,auth,credentials,credit_card/card_number,cvv,private_key,session,cookie,token,bearer,ssnhoặcdob— trong dữ liệu lồng nhau, tag, ngữ cảnh, dữ liệu extra, breadcrumb và query string;che trong văn bản: thông tin đăng nhập trong URL, cặp
name=valuevà chuỗi JSON có tên nhạy cảm, bearer token và các dòngAuthorization: <scheme> <giá trị>khác, JWT, khoá có tiền tố của nhà cung cấp (Stripe, GitHub, GitLab, OpenAI, Anthropic, AWS access key ID, Slack, Google API key, Stripe webhook secret, npm, Supabase secret key và khoá ingest của Belvador; trừ Stripe, tất cả từ SDK 0.5.2), phần đường dẫn bí mật trong URL webhook của Slack, Discord và URL bot Telegram, số thẻ vượt qua kiểm tra Luhn, phần trước@của địa chỉ email kể cả khi bị mã hoá thànhjane%40example.com(giữ tên miền), và phần cuối của địa chỉ IPv4 công khai.
Dữ liệu sâu quá 10 cấp hoặc quá 1.000 khoá sẽ không được duyệt tiếp. Hook beforeSend của bạn chạy trước bước lọc này.
Cách cài Node.js và Python thêm một hook beforeSend dùng cùng danh sách tên và các quy tắc văn bản tương tự.
Lớp 2 — node của bạn, trước khi lưu#
Node chạy bộ lọc riêng, viết tách khỏi SDK để một lỗi không thể làm tắt cả hai:
cùng danh sách tên nhạy cảm, che thành
[Filtered];mẫu cho bearer token và các dòng
Authorization: <scheme> <giá trị>khác, khoá bí mật Stripe, JWT, số thẻ và địa chỉ email (kể cả dạng mã hoá%40);từ node 0.1.31, cùng các khoá có tiền tố nhà cung cấp và đường dẫn webhook như SDK;
xoá tên đăng nhập và mật khẩu trong URL kiểu
https://user:pass@db.example.com;che địa chỉ IP: phần cuối của IPv4 về 0, IPv6 chỉ giữ 48 bit đầu. Trong văn bản tự do, ví dụ message của lỗi, IPv4 công khai cũng bị che như vậy; địa chỉ nội bộ, loopback, CGNAT và link-local (
10.0.3.17,127.0.0.1) được giữ nguyên vì thường là máy chủ của chính bạn;ID người dùng được thay bằng mã băm có muối;
xoá các header
Authorization,Cookie,Set-CookievàProxy-Authorization.
Bộ lọc áp dụng cho giá trị exception, biến và đoạn code trong stack frame, breadcrumb, tag, ngữ cảnh, dữ liệu extra, message, thông tin người dùng và dữ liệu request.
Bộ dò có sẵn#
Project → Quyền riêng tư → Bộ dò có sẵn liệt kê các nhóm này; mặc định bật hết. Tắt một nhóm nghĩa là dữ liệu loại đó do SDK gửi sẽ được lưu nguyên và mọi người trong workspace đều thấy. Chỉ owner và admin đổi được; tắt một nhóm cần mã xác thực, owner nhận email và mọi thay đổi được ghi vào nhật ký.
Lớp 3 — luật của project (trang Quyền riêng tư)#
Project → Quyền riêng tư quyết định node không bao giờ lưu gì cho project đó. Node áp luật trước khi ghi bất cứ thứ gì — cho lỗi, span và log OpenTelemetry — từ agent node 0.1.36. Thay đổi đã lưu áp cho dữ liệu đến sau; dữ liệu đã lưu không bị viết lại.
Thứ tự luôn cố định:
Danh sách cho phép (chỉ ở chế độ Nghiêm ngặt). Nghiêm ngặt giữ mức tối thiểu mà một lỗi, span hay log cần — mức lỗi, loại lỗi, stack frame không có biến, release, môi trường, trace id — cộng các trường bạn liệt kê. Tiêu chuẩn giữ mọi thứ mà các bước sau không xoá.
Luôn xoá, dù project đặt gì (không tắt được, không đưa vào danh sách cho phép được): cookie, header xác thực, mã dùng một lần và mã xác minh, mật khẩu, secret và khoá riêng, body của request, response và tin nhắn, số thẻ (kiểm Luhn) và CVV, biến của stack frame.
Luật của bạn, theo thứ tự, tối đa 100.
Bộ dò có sẵn (lớp 2).
Mỗi luật gồm selector, loại và cách xử lý:
| Phần | Giá trị |
|---|---|
| Selector | Đường dẫn viết thường như extra.phone, request.headers.x-api-key hay contexts.*.token; * là một cấp, ** là mọi độ sâu. Selector có kiểu: $string (mọi giá trị chữ), $request, $user, $frame.vars, $log.attributes, $span.attributes. Kết hợp bằng &&, || và !. Nội dung của một log là message. |
| Loại | anything (toàn bộ giá trị), pattern (biểu thức chính quy), creditcard, ip, email, phone_e164 (số quốc tế như +84901234567) |
| Cách | remove (xoá), replace (thay bằng chữ cố định tối đa 32 ký tự), mask (giữ 2 ký tự cuối), hash (mã băm có khoá riêng của project, 16 ký tự hex: cùng đầu vào cho cùng kết quả, nên vẫn đếm và tìm được) |
Pattern phải an toàn để chạy trên mọi event: tham chiếu ngược, look-around, lặp lồng nhau kiểu (a+)+ và pattern dài hơn 256 ký tự bị từ chối khi lưu. Mỗi giá trị chữ được kiểm tối đa 16 KiB; nếu một payload chạy quá ngân sách thời gian, các trường còn lại mà luật chạm tới bị xoá và trang có đếm.
Thử luật chạy luật ngay trong trình duyệt trên mẫu bạn dán hoặc mẫu tổng hợp — mẫu không bao giờ được gửi đi. Kết quả là payload sau nhóm luôn xoá và luật của bạn (bộ dò có sẵn chạy sau đó, trên node), kèm luật nào khớp đường dẫn nào, không bao giờ hiện lại giá trị bị khớp. Mã băm hiện là [hash] vì chỉ node giữ khoá.
Lưu tạo một phiên bản mới; Lịch sử phiên bản cho biết ai đổi gì, lúc nào, kèm phần khác nhau. Thay đổi giữ lại nhiều dữ liệu hơn — xoá hoặc tắt một luật, chuyển về Tiêu chuẩn, thêm vào danh sách cho phép, tắt một bộ dò có sẵn — cần mã xác thực; owner nhận email và thay đổi được ghi vào nhật ký. Owner và admin sửa được; thành viên khác chỉ xem. Qua API và MCP, privacy.get đọc chính sách còn privacy.set luôn chờ một người duyệt.
Trạng thái node. Node báo phiên bản đang áp. Nếu node không có chính sách hợp lệ — ví dụ không xác minh được cấu hình — node chỉ lưu mức tối thiểu nghiêm ngặt và đếm các payload đó; trang hiện con số này.
Cùng luật đó ngay trong app (tuỳ chọn)#
Từ SDK 0.6.0, app có thể áp luật của project trước khi bất cứ thứ gì rời app, bằng đúng engine node đang chạy. Sao chép dạng code trên trang Quyền riêng tư sao chép chính sách đã lưu dưới dạng JSON; lưu nó trong app và truyền vào init:
import { init, privacyPolicy } from "@belvador/browser"; // mọi gói @belvador/* đều cóimport policy from "./belvador-privacy.json";init({ dsn: "https://<public-key>@ingest.belvador.dev/<project-id>", privacyPolicy: privacyPolicy(policy) });Node vẫn áp chính sách hiện tại của project, nên app giữ bản cũ không bao giờ kém an toàn hơn — sao chép lại sau mỗi lần đổi nếu muốn lọc cả trong app. JSON không phải chính sách hợp lệ thì không được áp và báo BLV_PRIVACY_POLICY_INVALID. Engine luật chỉ được đóng gói vào app có import privacyPolicy.
Xem đúng thứ sẽ được gửi. preview: true trong init (hoặc BELVADOR_PREVIEW=1 trên máy chủ) in từng envelope — sau beforeSend của bạn, các luật này và bộ che của Belvador — ra console (stderr trên máy chủ) và không gửi gì. Dùng khi đang phát triển; tắt đi để gửi.
Monitor và trace#
Một check-in mang slug của monitor, trạng thái, thời lượng, môi trường, release, số lần thử, một mã lý do ngắn (nếu có) và trace ID — không có nội dung thông báo, dữ liệu request hay dữ liệu người dùng. Check-in được lưu trên node của bạn. Cơ sở dữ liệu của Belvador chỉ giữ cấu hình và trạng thái của từng monitor (khoẻ, hỏng, từ lúc nào) cùng các sự cố, để trang và cảnh báo vẫn chạy khi node mất kết nối. Trace ID là mã ngẫu nhiên; được lưu cùng lỗi và lượt chạy trên node, và không bao giờ có trong tin cảnh báo. Span và log OpenTelemetry bạn gửi cũng chỉ được lưu trên node của bạn và được lọc ở đó trước — xem Quyền riêng tư OpenTelemetry.
Những gì bộ lọc không đảm bảo#
Tên lạ. Bí mật nằm dưới tên như
xhayvaluesẽ không được nhận ra.Văn bản tự do. Một câu như
`Login failed for jane@example.com with Hunter2!`sẽ được che một phần email, nhưng mật khẩu chỉ là chữ bình thường. Tên người, số điện thoại, địa chỉ nhà trong câu không được nhận ra, IPv6 viết giữa câu cũng vậy.Tên quá rộng. Bộ lọc so theo kiểu "có chứa", nên cả những tên vô hại như
author,session_counthaytoken_countcũng bị che. Đổi tên trường nếu bạn cần đọc giá trị.Tệp đính kèm được kiểm tra kích thước, không được lọc nội dung. Chỉ bật
attachmentscho những tệp bạn biết là an toàn.Metadata của bạn.
release,environment, fingerprint và tên tag được gửi nguyên văn.SDK khác. Nếu bạn giữ một SDK không phải của Belvador, mặc định của SDK đó áp dụng cho tới khi bộ lọc của node chạy.
Thói quen an toàn#
Không bao giờ đưa bí mật, token hoặc nguyên object người dùng vào ngữ cảnh của
captureException, tag haysetContext.Dùng
setUser({ id })với ID nội bộ, không dùng email.Thử bộ lọc bằng giá trị giả, ví dụ
password=not-a-real-secret— không bao giờ dùng thông tin đăng nhập thật.Nếu một bí mật thật lỡ tới Belvador, hãy đổi bí mật đó trước tiên; xoá event không làm mất việc nó đã bị lộ.
Pháp lý#
Trang Bảo mật mô tả các biện pháp của Belvador và cách báo lỗ hổng. Trang Xử lý dữ liệu giải thích vai trò theo luật bảo vệ dữ liệu.
Bài viết về chủ đề này
Tất cả bài viết- Gửi lỗi production cho LLM thế nào cho an toànTrước khi dán lỗi vào ChatGPT, Claude hay coding agent: xoá secret, rào phần chữ không tin được, kiểm thời gian lưu. Thử injection 72 lần cho thấy vì sao.
- Lưu trữ dữ liệu lỗi và nơi nhà cung cấp AI xử lý: hai lựa chọn riêngNơi lưu dữ liệu lỗi và nơi AI xử lý là hai lựa chọn riêng. So cài đặt của OpenAI, Anthropic, Google, Azure, kèm Luật Bảo vệ dữ liệu cá nhân 2025.
- Lọc PII trong error monitoring mà không mất ngữ cảnhMột bộ lọc dữ liệu thật trên 16 mẫu lỗi giả lập: luật theo mẫu xoá được gì, bỏ sót gì, xoá nhầm gì, và bạn nên tự thêm gì trong beforeSend.
Thấy chỗ sai hoặc thiếu? Gửi cho chúng tôi: hello@belvador.dev