Bỏ qua tới nội dung
Mục lục

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.

Bản Markdown
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ơiChứa gìAi đọc được
Ứng dụng của bạnEvent trước khi gửi; SDK lọc trướcCode 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àyChỉ 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ạnKhông ai — không giữ lại gì
Node của bạn, trong project Hetzner của bạnEvent, issue, tệp đính kèm, source map — được lọc lại trước khi lưuNgười trong workspace của bạn, qua ứng dụng
Phần điều khiển của BelvadorThông tin tài khoản, workspace, project, cấu hình và số đếmBelvador, để 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ạnNế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ìnhNgười vận hành địa chỉ đó
Backup trong Cloudflare R2Bản sao đã mã hoá của dữ liệu nodeNgườ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-IP và Forwarded;

  • xoá body request, cookie và dữ liệu môi trường trong thông tin request;

  • chỉ giữ user.id trong 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ứa password, passwd, pwd, secret, api_key/apikey, access_token, auth, credentials, credit_card/card_number, cvv, private_key, session, cookie, token, bearer, ssn hoặc dob — 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=value và chuỗi JSON có tên nhạy cảm, bearer token và các dòng Authorization: <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ành jane%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-Cookie và 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:

  1. 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á.

  2. 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.

  3. Luật của bạn, theo thứ tự, tối đa 100.

  4. Bộ dò có sẵn (lớp 2).

Mỗi luật gồm selector, loại và cách xử lý:

PhầnGiá 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ạianything (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áchremove (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:

TypeScript
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ư x hay value sẽ 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_count hay token_count cũ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 attachments cho 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 hay setContext.

  • 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

Thấy chỗ sai hoặc thiếu? Gửi cho chúng tôi: hello@belvador.dev