Dekkapok.Engineering

2026-08-05

บั๊กบรรทัดเดียวมูลค่าพันล้าน: เมื่อ Coldcard Hardware Wallet ถูกขโมย Bitcoin เพราะ Firmware อัปเดตพลาด

#cryptocurrency #hacking #cybersecurity

บั๊กบรรทัดเดียวมูลค่าพันล้าน: เมื่อ Coldcard Hardware Wallet ถูกขโมย Bitcoin เพราะ Firmware อัปเดตพลาด
FILE: coinkite.md
SIZE: 32.4 KB
SHA256: 0x2097c5ec
CHARS: 16370
WORDS: 1478
READ TIME: 41 min

สรุปสั้น: ช่องโหว่ใน firmware ของ Coldcard hardware wallet (มีนาคม 2021 – กรกฎาคม 2026) ทำให้กระบวนการสุ่ม Seed Phrase ที่ควรมี Entropy ระดับ 128/256 bits เหลือเพียงประมาณ 32–72 bits เปิดช่องให้ผู้โจมตี brute-force หา seed และขโมย Bitcoin ได้ มูลค่าความเสียหายที่มีรายงานอยู่ระหว่าง 38–88 ล้านดอลลาร์ (แหล่งข่าวรายงานตัวเลขต่างกัน)


สารบัญ


ภาพรวมปัญหา

เป็นเรื่องของ hardware wallet ที่โดนช่องโหว่จาก Firmware อัปเดตผิดพลาด (เริ่มตั้งแต่เวอร์ชัน 4.0.0 ช่วงเดือนมีนาคม 2021) ส่งผลให้กระบวนการสุ่ม Seed Phrase ที่ควรมี Entropy ระดับ 128/256 bits กลับลดลงเหลือเพียงประมาณ 32-72 bits เท่านั้น เปิดช่องให้ผู้โจมตีสามารถคำนวณหา Seed และดึงเงินออกจากกระเป๋าไปได้ โดยไม่ต้องขโมยเครื่องหรือรอให้อุปกรณ์ต่อเน็ตเลยด้วยซ้ำ

มาดูกันในระดับ Source Code ว่า “ฮาร์ดแวร์ระดับเทพ พลาดท่าให้ซอฟต์แวร์ได้ยังไง”

จุดเริ่มต้นของหายนะ: Root Cause ระดับ Source Code

ปกติแล้ว hardware wallet ส่วนใหญ่เวลาสร้าง Seed Phrase จะต้องเรียกใช้ Hardware TRNG (True Random Number Generator) ที่ฝังอยู่ในชิปความปลอดภัยโดยตรง ผ่านคำสั่งอย่าง ckcc.rng_bytes()

แต่ทีมพัฒนาได้ทำการปรับโค้ดใหม่ เปลี่ยนไปเรียกใช้ฟังก์ชัน ngu.random.bytes() ใน shared/seed.py (ฟังก์ชัน generate_seed()) แทน โดยมี comment กำกับไว้ว่า “Generate 32 bytes of best-quality high entropy TRNG bytes” — แต่ในความเป็นจริง ฟังก์ชันนี้ไปเรียกไลบรารีคริปโตที่ชื่อ libngu มาทำงานแทน โดยไม่ได้ใช้ True Random Number Generator ในชิปความปลอดภัยตามที่ตั้งใจไว้

ในไลบรารี libngu (external/libngu/ngu/random.c บรรทัดที่ 28) มีโค้ดสำหรับตรวจสอบว่าระบบเปิดใช้งาน Hardware TRNG แล้วหรือยัง เขียนไว้ประมาณนี้:

#ifndef MICROPY_HW_ENABLE_RNG
#error "get a HW TRNG plz"
#endif

(ถ้าจะแซวก็คงต้องเติมว่า #error "มึงลืม #if รึเปล่า" — ไม่ใช่โค้ดจริงในไฟล์ แค่ล้อเจตนาของบั๊กให้เห็นภาพ)

จุดที่พลาดคือ โค้ดนี้ตรวจแค่ว่า “มีการประกาศตัวแปร MICROPY_HW_ENABLE_RNG หรือยัง” (#ifndef = is it defined?) แต่ไม่ได้ตรวจว่าค่าของมันคืออะไร (ไม่ใช่ #if ที่เช็คค่า true/false)

ปัญหาคือในไฟล์ config ของ firmware (stm32/COLDCARD_MK4/mpconfigboard.h บรรทัดที่ 78 — และไฟล์เทียบเท่าใน Mk3) ตัวแปรนี้ถูกประกาศไว้ว่า:

// We have our own version of this code.
#define MICROPY_HW_ENABLE_RNG (0)

ซึ่งหมายถึง “ปิดการใช้งาน RNG ของ MicroPython เพราะเรามี hardware RNG ของตัวเองแล้ว” — เจตนาดั้งเดิมถูกต้อง แต่เพราะตัวแปรนี้ถูก “ประกาศ” ไว้แล้ว (แม้ค่าจะเป็น 0) #ifndef เลยผ่านฉลุย ไม่มี compile error ทั้งที่จริง ๆ ชิป TRNG ถูกปิดไปแล้วในเส้นทางที่ libngu เชื่อมอยู่

ในอีกไฟล์หนึ่ง external/micropython/ports/stm32/rng.c ที่ตรวจสอบตัวแปรเดียวกันแต่ใช้ #if (เช็คค่าถูกต้อง) เมื่อเห็นค่าเป็น 0 มันจึง compile โค้ด branch สำรอง (#else) แทน ซึ่งก็คือฟังก์ชัน rng_get() ที่ return ค่าจาก Yasmarang (Pseudorandom Number Generator - PRNG) ซอฟต์แวร์แทนที่จะอ่านค่าจากชิปฮาร์ดแวร์จริง

ส่วน hardware TRNG ของ Coldcard เอง (stm32/COLDCARD_MK4/rng.c) ยังทำงานถูกต้องสมบูรณ์ แต่มัน export ออกมาเป็น pyb_rng_get_obj / random32() เท่านั้น — ไม่มีที่ไหนในโค้ดทั้งหมดที่ประกาศ symbol ตรง ๆ ชื่อ rng_get() ที่ libngu ต้องการลิงก์ด้วย ผลคือ hardware TRNG ที่ทำงานถูกต้อง กลับถูก “ตัดขาด” จากเส้นทางการสร้าง seed ไปเลย

ปัญหาของการสุ่มแบบซอฟต์แวร์ (Yasmarang) คือมันไม่ใช่การสุ่มที่แท้จริง แต่อาศัย Seed ตั้งต้นมาคำนวณผ่านสมการคณิตศาสตร์ โดยดึงค่ามาจาก 3 ส่วนหลัก ๆ คือ:

  1. UID_low32 — หมายเลขประจำตัวชิป (ไม่ใช่ความลับ, fixed device metadata)
  2. SysTick->VAL — รอบการทำงานของ CPU (คาดเดา/จำกัดช่วงได้)
  3. RTC->TR และ RTC->SSR — ค่าเวลา (คาดเดา/จำกัดช่วงได้เช่นกัน)

จุดที่พังจริง ๆ อยู่ตรงนี้: ระบบที่ควรมีความปลอดภัยระดับ 256-bit (การเดาแทบเป็นไปไม่ได้) ถูกลด Entropy ลงเหลือแค่ราว 32-72 bit เท่านั้น — บนรุ่น Mk2/Mk3 ตัวเลขนี้ถึงขั้นกลายเป็น deterministic ทั้งหมด (ใช้ UID + timing เท่านั้น ไม่ต้องรู้อะไรเพิ่มเลยต่อเครื่อง) ส่วนรุ่น Mk4/Q/Mk5 มีการผสม entropy จาก secure element เข้ามาบ้างตอน boot แต่ก็ hash แล้วเก็บไว้แค่ 4 ไบต์ ก่อนใช้แทนที่ state คำนวณ Yasmarang เพียง 1 word (32-bit) เท่านั้น ทำให้เพดาน entropy ที่แท้จริงต่ำกว่าตัวเลข 128-bit ที่ตั้งใจไว้มาก

นั่นแปลว่าอะไร? ถ้าผู้โจมตีรู้แค่ “ช่วงเวลาโดยประมาณ” ที่คุณเปิดเครื่องขึ้นมาสร้าง Wallet ครั้งแรก พวกเขาสามารถใช้คอมพิวเตอร์ประสิทธิภาพสูงจำลองค่าเวลาและรอบ CPU ย้อนหลัง แล้วทำ Brute-force attack ไล่หาค่าที่เป็นไปได้ โดยไม่จำเป็นต้องขโมยเครื่องหรือรอให้อุปกรณ์ต่อเน็ตเลยด้วยซ้ำ — แค่รู้ address สาธารณะก็สามารถ regenerate candidate seed แล้วเทียบ address เพื่อยืนยันได้


Timeline

วันที่เหตุการณ์
2018-05MicroPython upstream เพิ่ม Yasmarang software fallback เข้ามาใน codebase (ยังไม่เกี่ยวกับ Coldcard ณ จุดนี้)
2021-01-28libngu STM32 guard (#ifndef ที่บกพร่อง) เริ่มมีอยู่ในโค้ด
2021-03-01มีการ migrate ระบบ seed generation ไปใช้ libngu (commit ที่มีรายงานว่าชื่อ b18723dd — "First pass w/ libNgU")
2021-03-17Firmware v4.0.0 ออกวางจำหน่ายพร้อมเส้นทางที่มีช่องโหว่
2021-05-21commit 37e4af54 (“runs”) — จุดที่ตั้งค่า MICROPY_HW_ENABLE_RNG (0) เข้าไปจริง ตามการสืบสวนย้อนหลัง
2022-03-11/14เพิ่ม API reseed() แบบ 32-bit และเริ่มใช้ boot reseeding บน Mk4 v5.0.0
2026-06-16/17มีการทำ security audit ภายนอกต่อ codebase (commit a24a894c) — ตรวจ RNG แล้วสรุปว่าปลอดภัย (false negative) เพราะ git submodules สำคัญ (external/libngu, external/micropython ฯลฯ) ไม่ได้ถูก initialize ไว้ตอน clone
2026-07-30Block และนักวิจัยด้านความปลอดภัยอื่น ๆ เริ่มสังเกตรายงานผู้ใช้ Coldcard ถูกขโมยเงิน และเริ่มสืบสวน
2026-07-30/31Coinkite ออก advisory และ hot patch (commit ca724637 — "fixes rng")
2026-08-02ผู้ตรวจ audit เดือนมิถุนายนเผยแพร่ postmortem อธิบายว่าทำไมถึงพลาดบั๊กนี้

Commit และไฟล์ที่เกี่ยวข้อง

Repository: github.com/Coldcard/firmware

Commit / PRคำอธิบาย
b18723dd“First pass w/ libNgU” (2021-03-01)migrate เส้นทาง seed generation ไปพึ่งพา libngu
37e4af54“runs” (2021-05-21)commit ที่ตั้งค่า #define MICROPY_HW_ENABLE_RNG (0) ซึ่งเป็นจุดกำเนิดบั๊กจริง (ตามการสืบย้อนใน audit postmortem)
a24a894c (2026-05-16, master ณ ตอน audit)สถานะโค้ดที่ถูก audit ในเดือนมิถุนายน 2026 (ก่อนแก้บั๊ก)
ca724637“fixes rng” (2026-07-31 hotfix)แก้ไขให้ rng_get() กลับไปผูกกับ hardware TRNG จริง — แต่ในเวลาต่อมามีรายงานว่า hotfix นี้เองมีบั๊กใหม่เรื่อง rng_get_or_fault() ที่ไม่มี recovery path เมื่อเกิด error flag จน RNG peripheral ค้างถาวร (ดู PR #692)

ไฟล์หลักที่เกี่ยวข้อง:

  • shared/seed.py:319-325, 599 — จุดเรียกใช้ ngu.random.bytes(32) ใน generate_seed() / make_new_wallet()
  • external/libngu/ngu/random.c:28-30 — guard ที่บกพร่อง (#ifndef แทนที่จะเป็น #if)
  • stm32/COLDCARD/mpconfigboard.h (บรรทัด ~77) และ stm32/COLDCARD_MK4/mpconfigboard.h (บรรทัด ~78) — จุดที่ตั้งค่า MICROPY_HW_ENABLE_RNG (0)
  • external/micropython/ports/stm32/rng.c:30-96 — จุดที่ MicroPython เช็คค่าเดียวกันถูกต้องด้วย #if แล้ว fallback ไปที่ pyb_rng_yasmarang()
  • stm32/COLDCARD_MK4/rng.c — hardware TRNG ที่ถูกต้องแต่ export symbol คนละชื่อ (random32()) จึงไม่ได้ถูกใช้งาน
  • shared/mk4.py:43-49 — จุดที่ entropy จาก secure element ถูก truncate จาก 256 บิตเหลือ 32 บิตก่อนใช้ reseed()

ทำไม Audit ก่อนหน้านี้ถึงจับบั๊กนี้ไม่ได้

น่าสนใจว่ามี security audit ภายนอกเกิดขึ้นก่อนบั๊กนี้จะถูกเปิดเผยเพียง ~6 สัปดาห์ (audit วันที่ 2026-06-17) และ “Weak RNG source” อยู่ใน scope การตรวจอย่างชัดเจน แต่กลับถูกสรุปว่าเป็น “false positive” โดยระบุว่า “Entropy = STM32 TRNG + ATECC608 + DS28C36 mixed via SHA256d … No weak PRNG in the seed/key/signing path”

ฉบับขำๆ (เข้าใจง่าย)

เอางี้ ลองนึกภาพเหตุการณ์แบบนี้

มึงล็อกบ้านด้วยกุญแจ แต่ยามที่ประตูดันตรวจแค่ว่า “มีกุญแจในมือมั้ย” ไม่ได้ตรวจว่า “กุญแจนั้นมันใช่ดอกที่ไขได้จริงป่ะ” — เจ้าของบ้านเลยยื่นกุญแจเปล่าๆ ที่แกะสลักคำว่า “ปลอม” ไว้ตรงกลางดอกไปให้ยาม ยามเห็นว่า “อ๋อ มีของอยู่ในมือ” ผ่านฉลุยเลยจ้า เข้าบ้านได้สบายมาก 5 ปีเต็มๆ

ทีนี้มาถึง audit ที่ควรจะจับได้ก่อนหน้านี้… เรื่องมันตลกกว่านั้นอีก

หมอ (auditor) เดินเข้ามาตรวจร่างกายคนไข้ (Coldcard) แล้วถามหา “ไต” (libngu) กับ “ตับ” (micropython) — ปรากฏว่า ไม่มีอวัยวะพวกนี้ในตัวคนไข้เลย เพราะตอน clone ร่างกายมา ลืมกด git submodule update --init เป็นโพรงกลวงๆ อยู่ในท้อง แต่หมอไม่ตกใจ ไม่ถามหาไต ไม่ถามหาตับ

หมอกลับไปอ่าน สติ๊กเกอร์แปะข้างเตียงคนไข้ แทน ซึ่งเขียนไว้ว่า:

“ผมมีไตสำรองของตัวเองอยู่แล้วนะครับ (ขายไตเก่าไปแล้ว)”

หมออ่านจบ พยักหน้า: “อ๋อ งั้นก็โอเคครับ สุขภาพดีเยี่ยม ไม่มีอะไรน่าห่วง” — เซ็นใบรับรองแพทย์ให้เรียบร้อย โดยไม่เคยง้างซี่โครงเข้าไปดูเลยสักครั้งว่าไตสำรองที่ว่านั้นมันต่ออยู่จริงมั้ย หรือมันแค่สายยางเปล่าๆ ห้อยอยู่เฉยๆ

แล้วที่ฮาที่สุดคือระบบตรวจของหมอมันมีแค่ปุ่ม “ผ่าน ✅” กับ “ไม่ผ่าน ❌” — ไม่มีปุ่ม “เดี๋ยวๆ กูหาอวัยวะมึงไม่เจอ จะให้ตอบไงวะ” พอหาไม่เจอ ระบบเลยเดาส่งเดชกดปุ่ม “ผ่าน” ไปเอง

เหมือนตำรวจไปสืบคดีที่บ้านร้าง ประตูล็อก ไม่มีใครอยู่ แล้วสรุปสำนวนว่า “ไม่พบหลักฐานการก่ออาชญากรรม คดีปิด” ทั้งที่ความจริงต้องเขียนว่า “กรู…เข้าบ้านไม่ได้ด้วยซ้ำ ตอบไม่ได้”

สรุปคือทีมตรวจไปอ่าน “สเปกบนกล่อง” ว่าไตดีแค่ไหน แทนที่จะแกะเครื่องออกมาเช็คว่าไตมันต่ออยู่จริงรึเปล่า — แล้วก็เซ็นชื่อมั่นใจเต็มร้อยซะด้วยว่า “ปลอดภัย 100%”

สาเหตุที่ทำให้ตรวจไม่พบ (ตามที่ postmortem วิเคราะห์ไว้):

  1. Git submodules ไม่ได้ถูก initialize — โฟลเดอร์ external/libngu, external/micropython ที่เป็นจุดเกิดบั๊กจริงว่างเปล่าตอน clone (ใช้ clone แบบไม่ --recursive และไม่ได้รัน git submodule update --init) ทำให้ auditor ไม่เห็นไฟล์ที่มีบั๊กอยู่จริง ๆ เลย
  2. Adversarial verifier ไม่มีทางเลือก “ไม่แน่ใจ” — มีแค่ CONFIRMED/REFUTED สองทาง เมื่อ source ไม่มีให้ตรวจ ก็ถูกจัดเป็น REFUTED (false) แทนที่จะเป็น UNVERIFIABLE
  3. ไม่มีใครถามว่า entropy มาจากไหนจริง ๆ — การตรวจเน้นที่ dataflow จาก untrusted input ไปยัง sink แต่ที่มาของ entropy เป็นคำถามเชิง “linking” (ต้อง resolve symbol ไปยัง definition ข้าม build configuration) ซึ่งเป็นคนละแบบกับการอ่านโค้ดตรง ๆ
  4. เชื่อ docstring มากกว่าการ trace จริง — comment ว่า “best-quality high entropy TRNG bytes” ถูกรับเป็นหลักฐานแทนที่จะตามรอย call
  5. ไฟล์ที่เห็นได้เล่าเรื่องที่ดูสมเหตุสมผล#define MICROPY_HW_ENABLE_RNG (0) คู่กับ comment “We have our own version of this code” อ่านแล้วเหมือนการตั้งใจเปลี่ยนไปใช้ hardware RNG จริง ๆ (ซึ่งเป็นเจตนาดั้งเดิม แต่ผลลัพธ์จริงตรงกันข้าม)

บทเรียนสำคัญ: สำหรับฟังก์ชันแบบ random_bytes() ต้อง trace symbol ไปจนถึง definition จริงข้าม build configuration ทั้งหมดก่อนจะสรุปคุณภาพของมันได้ และ build-configuration macro (#ifndef vs #if) สมควรได้รับการตรวจสอบเข้มงวดเท่ากับ logic code ทั่วไป


ผลกระทบ

  • ช่วงที่ได้รับผลกระทบ: Coldcard Mk2/Mk3 firmware 4.0.1–4.1.9 (เต็มรูปแบบ, deterministic) และบางส่วนใน Mk4/Q/Mk5 (entropy ลดแต่ไม่ถึงขั้น deterministic เต็มรูปแบบ)
  • Entropy ที่แท้จริง: Coinkite ประเมินไว้ราว ~40 bits (Mk3) และ ~72 bits (Mk4/Mk5/Q) เทียบกับ 128 bits ที่ 12-word BIP-39 seed ควรมี — บางแหล่งวิเคราะห์เชิงลึกกว่านั้นชี้ว่าเพดานจริงต่ำกว่านี้อีก (ใกล้ 2³²)
  • มูลค่าความเสียหาย: รายงานจากสื่อต่าง ๆ ให้ตัวเลขต่างกัน อยู่ในช่วง 38–88 ล้านดอลลาร์ (ยังไม่มีตัวเลขสรุปที่เป็นทางการหนึ่งเดียว)
  • หมายเหตุสำคัญ: ความเสี่ยงขึ้นกับ เวอร์ชัน firmware ที่ใช้ตอนสร้าง seed ครั้งแรก ไม่ใช่ firmware เวอร์ชันปัจจุบัน และไม่ใช่วันที่ซื้อเครื่อง — การอัปเดต firmware ไม่ทำให้ seed เดิมที่สร้างไว้แล้วปลอดภัยขึ้นย้อนหลัง

บทเรียนและวิธีป้องกัน (สำหรับผู้ใช้ COLDCARD)

หากคุณใช้ COLDCARD ที่สร้างกระเป๋าในช่วงปี 2021 ถึงกลางปี 2026 คุณมีความเสี่ยง สิ่งที่ควรทำ:

  1. อัปเดต Firmware ทันที — ทาง Coinkite ออก hot patch แก้ปัญหานี้แล้ว (commit ca724637) รีบอัปเดตเป็นเวอร์ชันล่าสุดเพื่อปิดช่องโหว่สำหรับ seed ใหม่ ที่จะสร้างต่อจากนี้ (ไม่ช่วย seed เก่า)
  2. สร้าง Wallet ใหม่ด้วยฟีเจอร์ “Dice Rolls” — จุดแข็งของ COLDCARD คือรองรับการสร้าง Seed โดยไม่ต้องพึ่งระบบสุ่มของเครื่องเลย ให้หยิบลูกเต๋าจริงมาทอย (อย่างน้อย 50-99 ครั้ง) แล้วป้อนผลลัพธ์เข้าเครื่อง ระบบจะคำนวณ Seed จากผลทอยลูกเต๋าล้วน ๆ ซึ่งเป็นวิธี Trustless 100%
  3. ย้ายสินทรัพย์โดยเร็ว — เมื่อได้กระเป๋าใหม่ที่สร้างจากลูกเต๋าและรันบน Firmware เวอร์ชันล่าสุดแล้ว ให้รีบโอน Bitcoin ทั้งหมดจากกระเป๋าเก่า (ที่อาจสร้างขึ้นในช่วง firmware มีช่องโหว่) มายังกระเป๋าใหม่ทันที
  4. สำหรับ multisig: หากกระเป๋า multisig ประกอบด้วย Coldcard ที่มีช่องโหว่ทั้งหมด ความเสี่ยงยังคงอยู่เต็มรูปแบบ ต้องมี quorum ของอุปกรณ์ที่ปลอดภัยจริงจึงจะป้องกันได้

สรุป: เคสนี้สอนให้เห็นว่า ต่อให้ฮาร์ดแวร์ถูกออกแบบมาแน่นหนาแค่ไหน แค่โค้ดผิดโทเคนเดียว (#ifndef แทน #if) ก็กลายเป็นบั๊กมูลค่าหลายสิบล้านดอลลาร์ได้ และแม้แต่ security audit ที่ตั้งใจตรวจ RNG โดยเฉพาะก็ยังพลาดได้ หากสภาพแวดล้อมการตรวจ (เช่น git submodules) ไม่สมบูรณ์


สรุปรวบยอด

  • บั๊กเกิดจาก: โค้ดเช็คผิดคำสั่ง (#ifndef แทนที่จะเป็น #if) — เหมือนเช็คว่า “มีกุญแจอยู่ในมือรึเปล่า” แทนที่จะเช็คว่า “กุญแจนี้ไขประตูได้จริงไหม” พอมีกุญแจ (แม้จะเป็นกุญแจปลอม) ระบบก็ปล่อยผ่านให้เข้าบ้านได้เลย
  • ผลลัพธ์: Entropy ของ seed หล่นจาก 128/256 บิต เหลือแค่ 32-72 บิต ทำให้ brute-force ได้จริง
  • ทำไม audit หาไม่เจอ:
    1. ไฟล์จริงหายไปตอน clone (ลืมโหลด submodule) — หาของในลิ้นชักที่ไม่มีอยู่จริง
    2. เชื่อป้าย ไม่เชื่อของจริง — เห็น comment สวยๆ ก็เชื่อ ไม่ได้ตามรอยโค้ดจริง
    3. ระบบตรวจไม่มีตัวเลือก “ไม่รู้” — มีแต่ ผ่าน/ไม่ผ่าน พอข้อมูลขาด เลยเดาว่า “ผ่าน” แทนที่จะบอกว่า “ตรวจไม่ได้”
  • บทเรียน: ต่อให้ผู้ตรวจเก่งแค่ไหน ถ้า environment ไม่ครบ (ไฟล์หาย, submodule ไม่ได้โหลด) ผลตรวจก็ไม่มีความหมาย และการเช็คแค่ “มีตัวแปรนี้ยัง” ไม่เท่ากับเช็คว่า “ตัวแปรนี้ทำงานถูกต้องไหม”

อ้างอิง


เอกสารนี้รวบรวมจากรายงานสาธารณะหลายแหล่งเพื่อวัตถุประสงค์ทางการศึกษา ไม่ใช่คำแนะนำทางการเงินหรือความปลอดภัยอย่างเป็นทางการ กรุณาตรวจสอบ advisory ต้นฉบับจาก Coinkite ก่อนดำเนินการใด ๆ กับกระเป๋าของท่าน

SYSTEM LOG: TERMINAL CURL ACCESS ONLINE

Retrieve the raw markdown file or structured JSON of this post directly in your command line:

curl -sL https://dekkapok.engineering/blogs/coinkite.txt
curl -sL https://dekkapok.engineering/blogs/coinkite.json

← blogs ทั้งหมด