Bun.inspect.custom: ทำ log อ่านง่ายโดยไม่เผลอพ่น secret
เวลา console.log object ที่มี token หรือ header ทั้งก้อน ข้อมูลลับอาจติด log ไปโดยไม่ตั้งใจ Bun.inspect.custom เป็น symbol สำหรับกำหนดว่าควรแสดง object นั้นอย่างไรใน Bun.inspect และ console ช่วยให้ representation สั้นและปิดค่าที่ไม่ควรเห็นครับ
WHY: ทำป้ายหน้ากล่อง แทนเปิดของทุกชิ้น
เจ้าหน้าที่คลังต้องเห็นรหัสงานและสถานะ แต่ไม่จำเป็นต้องเปิดซองกุญแจ API การกำหนด custom inspector เหมือนติดป้ายที่ปลอดภัยไว้หน้ากล่อง ลดโอกาสที่ debug log จะพ่นทุก field โดยอัตโนมัติ
class SafeRequest {
constructor(
readonly id: string,
readonly endpoint: string,
private readonly token: string,
) {}
[Bun.inspect.custom]() {
return `SafeRequest(${this.id}, ${this.endpoint}, token=<redacted>)`;
}
}
const request = new SafeRequest("job-7", "/reports", "top-secret-value");
const rendered = Bun.inspect(request);
if (!rendered.includes("job-7") || !rendered.includes("<redacted>")) {
throw new Error("safe fields or redaction marker missing");
}
if (rendered.includes("top-secret-value")) throw new Error("secret leaked");
console.log(rendered);
HOW: inspector ไม่ได้ลบข้อมูลจริง
ค่าลับยังอยู่ใน object และโค้ดอื่นยังอ่านได้ การกำหนด inspector จึงไม่ใช่ encryption, access control หรือ secret store Logger บางตัว serialize ด้วย JSON.stringify, structured clone หรือเดิน property เอง ซึ่งจะไม่เรียก symbol นี้ ต้องตั้ง redaction ที่ transport ของ logger และทดสอบ output จริงทุกเส้นทาง
หลีกเลี่ยงการทำงานหนักหรือมี side effect ใน inspector เพราะ console อาจเรียกหลายครั้งระหว่าง debug ถ้า object มาจากผู้ใช้ ให้จำกัดความยาวของค่าที่แสดงและ escape control characters เพื่อกัน log forging ส่วน production ควรใช้ allowlist ของ field ที่เผยได้ แทน blacklist ชื่อ secret ที่อาจมีคำใหม่หลุดมา
Recap
- ใช้ custom inspector เพื่อทำ representation สำหรับคนอ่าน
- แสดงเฉพาะ allowlist และใส่ redaction marker ชัดเจน
- ทดสอบ console, logger และ JSON serializer แยกกัน
- อย่าถือ inspector เป็น security boundary
- เก็บ secret ใน credential store และจำกัดอายุ object