لاگ مفید باید بگوید چه رخدادی، چه زمانی و با چه شناسهای اتفاق افتاده؛ لازم نیست رمز، کوکی، بدنهٔ کامل درخواست یا دادهٔ مشتری را ذخیره کند. برای Node.js، یک فهرست مجاز از فیلدهای محدود معمولاً قابلکنترلتر از چاپ کل شیء req یا process.env است. نمونهٔ زیر الگوی سادهٔ انتخاب فیلد را نشان میدهد، نه یک سامانهٔ کامل لاگ تولید.
۱. برای هر رخداد قرارداد بنویسید
| فیلد | فایده | محدودیت |
|---|---|---|
event |
نوع رخداد قابلجستوجو | نام ثابت و روشن |
requestId |
پیوند چند پیام مربوط به یک درخواست | قالب و طول محدود؛ بدون دادهٔ مشتری |
status |
نتیجهٔ طبقهبندیشده | عدد معتبر HTTP در صورت ارتباط |
durationMs |
هزینهٔ زمانی در صورت نیاز | اندازهگیری واقعی، نه حدس |
برای رخدادهای واقعی، timestamp معتبر و منطقهٔ زمانی، سطح severity و سیاست نگهداری هم لازماند. شناسهٔ درخواست خودکار بیخطر نیست؛ اگر مقدار ورودی کاربر را بیبررسی کپی کنید، میتواند حاوی دادهٔ خصوصی یا newline باشد.
۲. نمونهٔ allowlist بدون چاپ راز
function logEvent(input) {
const event = {
level: input.ok === true ? 'info' : 'error',
event: 'checkout_completed',
requestId: /^[a-zA-Z0-9_-]{1,64}$/.test(input.requestId || '')
? input.requestId : 'invalid',
status: Number.isInteger(input.status) &&
input.status >= 100 && input.status <= 599 ? input.status : 500
};
return JSON.stringify(event);
}
console.log(logEvent({
ok: false, requestId: 'req_demo_1', status: 503,
password: 'DUMMY_ONLY', body: 'CUSTOMER_DEMO_ONLY'
}));
این دو مقدار پایانی صرفاً نشانگر آموزشیاند و هیچ رمز یا دادهٔ واقعی نیستند. خروجی واقعیِ نمونه فقط level، event، requestId و status را داشت؛ password و body به دلیل خارجبودن از فهرست مجاز وارد خروجی نشدند.
۳. از تزریق خط جدید جلوگیری کنید
در آزمون دوم، شناسهای دارای newline به تابع داده شد و به invalid تبدیل شد. انتخاب قالب محدود جلوی ورود همان مقدار خام را گرفت. JSON.stringify هم رشتهها را طبق JSON escape میکند، ولی اعتبارسنجی فیلد و کنترل مسیر خروجی همچنان لازم است.
نکته: پاکسازی با چند replace ساده، تضمین حذف همهٔ رازها نیست. خطاهای کتابخانه میتوانند در URL، stack، header یا شیء nested دادهٔ حساس داشته باشند. قبل از ثبت خطای کامل، قرارداد فیلدهای مجاز و مسیر sanitization را مشخص کنید.
اگر سامانهٔ مقصد ساختار JSON را به متن دیگری تبدیل میکند، خط خروجی همان مقصد را هم بررسی کنید؛ سالمبودن تابع اولیه تمام زنجیرهٔ جمعآوری را تأیید نمیکند.
۴. چه چیزهایی معمولاً نباید ثبت شوند؟
- رمز و کلید API، Authorization و توکن نشست.
- Cookie کامل و رشتهٔ اتصال دیتابیس.
- بدنهٔ کامل فرم، شماره تماس یا اطلاعات پرداخت بدون ضرورت و مجوز.
- کل process.env یا شیء درخواست.
- مسیر خصوصی و متن خطای خامِ دارای مقدار راز.
انتخاب فیلد بر اساس نیاز عیبیابی و مسئولیت حفاظت داده انجام میشود. ماسککردن بخشی از یک توکن، همیشه آن را بیخطر نمیکند. در صورت افشای واقعی راز در لاگ، صرف حذف یک خط از فایل مسئله را تمام نمیکند؛ رسیدگی باید طبق فرایند امنیتی مجاز انجام شود.
۵. عملیات لاگ را هم طراحی کنید
دسترسی به فایل، انتقال، محدودیت حجم، retention و مانیتورکردن شکستِ نوشتن لازماند. پرشدن دیسک بهخاطر لاگ یا retry بیپایانِ ارسال، نباید برنامه را از خدمت بیندازد. از طرف دیگر، نادیدهگرفتن همهٔ خطاهای logger هم عیبیابی را کور میکند.
سطح debug در تولید میتواند حجم و حساسیت داده را زیاد کند. قبل از روشنکردن، محدوده، زمان پایان و فرد مسئول مشخص باشد؛ این مقاله تنظیم لاگ حساب یا برنامهٔ زنده را عوض نمیکند.
۶. کنترل خروجی با دادهٔ آموزشی
- مقدارهای نشانگرِ غیرواقعی را در فیلدهای ممنوع قرار دهید.
- بررسی کنید این نشانگرها در خروجی وجود نداشته باشند.
- ورودی newline، طول زیاد و status نامعتبر را آزمایش کنید.
- نمایش خروجی در مقصد نهایی و خوانایی پیام را کنترل کنید.
نمونهٔ محلی این مقاله دو ورودی را بررسی کرده است؛ پوشش همهٔ ورودیها، امنیت کل برنامه یا درستی logger شما ادعا نمیشود. برای تشخیص محل لاگ روی هاست، راهنمای Errors مکمل است؛ اینجا هدف طراحی محتوای امن هر پیام است.
۷. مسیر مطالعهٔ مرتبط
۸. منابع و روش بررسی
منابع رسمی در ۲۴ اکتبر ۲۰۲۶ بررسی شدند. مثالهای کدِ این متن در Node.js نسخهٔ ۲۴.۱۹.۰ روی محیط محلی ایزوله بررسی شدهاند؛ نصب روی هاست، اتصال دیتابیس یا کارایی تولید با این آزمایش اثبات نشده است.