experimental_taintUniqueValue
taintUniqueValue
cho phép bạn ngăn các giá trị duy nhất được truyền đến Client Components như mật khẩu, khóa hoặc mã thông báo.
taintUniqueValue(errMessage, lifetime, value)
Để ngăn việc truyền một đối tượng chứa dữ liệu nhạy cảm, hãy xem taintObjectReference
.
Tham khảo
taintUniqueValue(message, lifetime, value)
Gọi taintUniqueValue
với mật khẩu, mã thông báo, khóa hoặc hàm băm để đăng ký nó với React như một thứ gì đó không được phép chuyển đến Client như hiện tại:
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Không chuyển khóa bí mật cho máy khách.',
process,
process.env.SECRET_KEY
);
Tham số
-
message
: Thông báo bạn muốn hiển thị nếuvalue
được chuyển đến Client Component. Thông báo này sẽ được hiển thị như một phần của Lỗi sẽ được đưa ra nếuvalue
được chuyển đến Client Component. -
lifetime
: Bất kỳ đối tượng nào cho biết thời gianvalue
nên bị nhiễm độc.value
sẽ bị chặn gửi đến bất kỳ Client Component nào khi đối tượng này vẫn tồn tại. Ví dụ: chuyểnglobalThis
sẽ chặn giá trị trong suốt thời gian tồn tại của một ứng dụng.lifetime
thường là một đối tượng có các thuộc tính chứavalue
. -
value
: Một chuỗi, bigint hoặc TypedArray.value
phải là một chuỗi các ký tự hoặc byte duy nhất có entropy cao, chẳng hạn như mã thông báo mật mã, khóa riêng, hàm băm hoặc mật khẩu dài.value
sẽ bị chặn gửi đến bất kỳ Client Component nào.
Trả về
experimental_taintUniqueValue
trả về undefined
.
Lưu ý
- Tạo các giá trị mới từ các giá trị bị nhiễm độc có thể làm tổn hại đến việc bảo vệ chống nhiễm độc. Các giá trị mới được tạo bằng cách viết hoa các giá trị bị nhiễm độc, nối các giá trị chuỗi bị nhiễm độc thành một chuỗi lớn hơn, chuyển đổi các giá trị bị nhiễm độc thành base64, lấy chuỗi con của các giá trị bị nhiễm độc và các chuyển đổi tương tự khác không bị nhiễm độc trừ khi bạn gọi rõ ràng
taintUniqueValue
trên các giá trị mới được tạo này. - Không sử dụng
taintUniqueValue
để bảo vệ các giá trị entropy thấp như mã PIN hoặc số điện thoại. Nếu bất kỳ giá trị nào trong yêu cầu bị kẻ tấn công kiểm soát, chúng có thể suy ra giá trị nào bị nhiễm độc bằng cách liệt kê tất cả các giá trị có thể có của bí mật.
Cách sử dụng
Ngăn mã thông báo được chuyển đến Client Components
Để đảm bảo rằng thông tin nhạy cảm như mật khẩu, mã thông báo phiên hoặc các giá trị duy nhất khác không vô tình được chuyển đến Client Components, hàm taintUniqueValue
cung cấp một lớp bảo vệ. Khi một giá trị bị nhiễm độc, bất kỳ nỗ lực nào để chuyển nó đến Client Component sẽ dẫn đến lỗi.
Đối số lifetime
xác định khoảng thời gian giá trị vẫn bị nhiễm độc. Đối với các giá trị nên bị nhiễm độc vô thời hạn, các đối tượng như globalThis
hoặc process
có thể đóng vai trò là đối số lifetime
. Các đối tượng này có tuổi thọ kéo dài toàn bộ thời gian thực thi ứng dụng của bạn.
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Không chuyển mật khẩu người dùng cho máy khách.',
globalThis,
process.env.SECRET_KEY
);
Nếu tuổi thọ của giá trị bị nhiễm độc gắn liền với một đối tượng, thì lifetime
phải là đối tượng bao bọc giá trị. Điều này đảm bảo giá trị bị nhiễm độc vẫn được bảo vệ trong suốt thời gian tồn tại của đối tượng bao bọc.
import {experimental_taintUniqueValue} from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintUniqueValue(
'Không chuyển mã thông báo phiên người dùng cho máy khách.',
user,
user.session.token
);
return user;
}
Trong ví dụ này, đối tượng user
đóng vai trò là đối số lifetime
. Nếu đối tượng này được lưu trữ trong bộ nhớ cache toàn cục hoặc có thể truy cập được bởi một yêu cầu khác, thì mã thông báo phiên vẫn bị nhiễm độc.
Tìm hiểu sâu
Nếu bạn đang chạy một môi trường Server Components có quyền truy cập vào các khóa riêng hoặc mật khẩu như mật khẩu cơ sở dữ liệu, bạn phải cẩn thận để không chuyển nó cho Client Component.
export async function Dashboard(props) {
// KHÔNG LÀM ĐIỀU NÀY
return <Overview password={process.env.API_PASSWORD} />;
}
"use client";
import {useEffect} from '...'
export async function Overview({ password }) {
useEffect(() => {
const headers = { Authorization: password };
fetch(url, { headers }).then(...);
}, [password]);
...
}
Ví dụ này sẽ làm rò rỉ mã thông báo API bí mật cho máy khách. Nếu mã thông báo API này có thể được sử dụng để truy cập dữ liệu mà người dùng cụ thể này không được phép truy cập, nó có thể dẫn đến vi phạm dữ liệu.
Lý tưởng nhất là các bí mật như thế này được trừu tượng hóa thành một tệp trợ giúp duy nhất chỉ có thể được nhập bởi các tiện ích dữ liệu đáng tin cậy trên máy chủ. Trình trợ giúp thậm chí có thể được gắn thẻ bằng server-only
để đảm bảo rằng tệp này không được nhập trên máy khách.
import "server-only";
export function fetchAPI(url) {
const headers = { Authorization: process.env.API_PASSWORD };
return fetch(url, { headers });
}
Đôi khi những sai lầm xảy ra trong quá trình tái cấu trúc và không phải tất cả đồng nghiệp của bạn có thể biết về điều này. Để bảo vệ chống lại những sai lầm này xảy ra sau này, chúng ta có thể “làm nhiễm độc” mật khẩu thực tế:
import "server-only";
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Không chuyển mật khẩu mã thông báo API cho máy khách. ' +
'Thay vào đó, hãy thực hiện tất cả các tìm nạp trên máy chủ.'
process,
process.env.API_PASSWORD
);
Bây giờ, bất cứ khi nào ai đó cố gắng chuyển mật khẩu này cho Client Component hoặc gửi mật khẩu cho Client Component bằng Server Function, một lỗi sẽ được đưa ra với thông báo bạn đã xác định khi bạn gọi taintUniqueValue
.