# Cargo cooldown คืออะไร: Rust 1.100 ให้หน่วงการใช้ crate รุ่นใหม่ ลดเสี่ยงห่วงโซ่ซัพพลาย

> Cargo cooldown คือค่าที่ให้ Cargo ไม่เลือก crate รุ่นที่เพิ่งออกไม่ถึงเวลาที่กำหนด จะเสถียรใน Rust 1.100 วันที่ 12 พ.ย. 2026 แต่ค่าเริ่มต้นเป็น 0 ต้องเปิดใช้เอง

- ประเภท: อธิบาย · หมวด: Software
- เผยแพร่: 2026-10-22T19:12:00.000Z · อัปเดต: 2026-10-22T19:12:00.000Z
- โดย: กองบรรณาธิการ THAI DATA, THAI DATA IT BUSINESS ENTERPRISE
- ที่มา: https://thaidata.co.th/software/cargo-cooldown-rust-1-100-min-publish-age/

## สรุปประเด็นสำคัญ

- **Cargo cooldown** หรือ minimum publish age ถูกประกาศเป็นฟีเจอร์เสถียรใน changelog ของ **Cargo 1.100** ซึ่งมีกำหนดออกพร้อม Rust 1.100 วันที่ **12 พฤศจิกายน 2026**
- ตั้งค่าด้วย `registry.global-min-publish-age` เช่น `"7 days"` หรือ `"14 days"` แต่ **ค่าเริ่มต้นคือ "0"** การอัปเกรด Rust อย่างเดียวจึงยังไม่เปิดการป้องกัน
- เมื่อเปิดแล้ว resolver จะ **ข้ามรุ่นที่ใหม่เกินกำหนด** เว้นแต่รุ่นนั้นอยู่ใน Cargo.lock แล้ว และถ้าไม่มีรุ่นที่ผ่านเงื่อนไข Cargo จะแจ้ง error แทนการดึงรุ่นใหม่
- แนวคิดมาจาก **RFC 3923** ที่เริ่มเมื่อ **23 กุมภาพันธ์ 2026** ซึ่งระบุว่าการโจมตีห่วงโซ่ซัพพลายบางแบบถูกเครื่องสแกนอัตโนมัติจับได้ภายในไม่นานหลังเผยแพร่
- Cargo 1.100 ยังเปิดใช้ **ระบบ lint ของ Cargo** พร้อม lint `cargo::unused_dependencies` เปลี่ยนโครงสร้างโฟลเดอร์ build และให้ `cargo install` ใช้ lockfile ในแพ็กเกจเป็นค่าเริ่มต้น

**Cargo cooldown** คือการตั้งอายุขั้นต่ำให้ Cargo ตัวจัดการแพ็กเกจของภาษา Rust ไม่เลือกใช้ crate รุ่นที่เพิ่งเผยแพร่ไม่ถึงระยะเวลาที่กำหนด เช่น 7 หรือ 14 วัน ฟีเจอร์นี้จะเป็นฟีเจอร์เสถียรใน Rust 1.100 ที่มีกำหนดออกวันที่ 12 พฤศจิกายน 2026 แต่ค่าเริ่มต้นคือ 0 วัน ทีมจึงต้องเปิดใช้เอง

RFC 3923 ที่เป็นต้นทางของฟีเจอร์นี้อ้างถึงการโจมตีห่วงโซ่ซัพพลายในระบบนิเวศ npm ที่ทำให้คนหันมาสนใจการรอ เพราะการโจมตีบางแบบถูกเครื่องสแกนอัตโนมัติพบได้หลังรุ่นใหม่เผยแพร่ไม่นาน การรอให้รุ่นใหม่ "เย็นลง" ก่อนใช้จึงลดโอกาสที่ build หรือเครื่องของนักพัฒนาจะดึงรุ่นนั้นไปก่อนที่ปัญหาจะถูกพบ

## Cargo cooldown คืออะไร

ในเอกสารทางการ ฟีเจอร์นี้ชื่อ minimum publish age ส่วน changelog ของ Cargo 1.100 เรียกว่า dependency cooldowns หลักการคือ registry อย่าง crates.io บันทึกเวลาเผยแพร่ (pubtime) ของแต่ละรุ่นไว้ เมื่อ Cargo เลือกรุ่นของ dependency จะเทียบเวลานั้นกับอายุขั้นต่ำที่ทีมตั้งไว้ รุ่นที่ใหม่เกินจะถูกนับว่า "pubtime-incompatible" และถูกข้าม

RFC 3923 ซึ่งเริ่มเมื่อ 23 กุมภาพันธ์ 2026 ให้เหตุผลไว้ 2 ข้อ

- **ลดความเสี่ยงห่วงโซ่ซัพพลาย** การโจมตีบางแบบถูกเครื่องสแกนอัตโนมัติจับได้หลังรุ่นใหม่เผยแพร่ไม่นาน การรอจึงให้เวลาเครื่องสแกนเหล่านี้ทำงาน
- **ทยอยรับรุ่นใหม่ทั้งระบบนิเวศ** รุ่นใหม่อาจมีบั๊ก การเปลี่ยนแปลงที่ทำให้ของเดิมพัง หรือช่องโหว่ที่ไม่ได้ตั้งใจ ถ้าทุกคนอัปเกรดพร้อมกัน ความเสียหายจะกว้าง ผู้ที่รับความเสี่ยงได้เป็นผู้ทดลองก่อน ส่วนผู้ที่ต้องการความเสถียรรอได้

![หน้า Cargo Changelog ส่วน Cargo 1.100 วันที่ 2026-11-12 ระบุการทำให้ระบบ lint ของ Cargo และ minimum publish age หรือ dependency cooldowns เป็นฟีเจอร์เสถียร](https://thaidata-co-th.s3.ap-southeast-1.amazonaws.com/thaidata.co.th/images/articles/cargo-cooldown-rust-1-100-min-publish-age/swb2-dev-cargo-1100-changelog.webp?v=ff592d20) _(ภาพ: The Rust Project (The Cargo Book))_

## Cargo cooldown ทำงานอย่างไร

เอกสาร Dependency Resolution ของ Cargo Book และ RFC 3923 อธิบายพฤติกรรมไว้ดังนี้

1. รุ่นที่เวลาเผยแพร่ใหม่กว่าอายุขั้นต่ำถือว่าไม่ผ่านเงื่อนไข
2. ถ้า `resolver.incompatible-publish-age` เป็น `"deny"` ซึ่งเป็นค่าเริ่มต้น resolver จะไม่เลือกรุ่นเหล่านั้น ยกเว้นรุ่นที่อยู่ใน Cargo.lock อยู่แล้ว
3. ถ้าไม่มีรุ่นใดผ่านทั้งเงื่อนไขเวอร์ชันและอายุขั้นต่ำ การ resolve จะ error คล้ายกรณีที่ทุกรุ่นถูก yank ในตัวอย่างของ RFC ข้อความ error บอกว่ารุ่นนั้นเผยแพร่มากี่วันและอายุขั้นต่ำคือเท่าไร
4. ถ้าตั้งเป็น `"allow"` Cargo จะไม่ตรวจเงื่อนไขนี้

ข้อ 3 สำคัญที่สุด Cargo cooldown ไม่ "ยอมแพ้" แล้วดึงรุ่นใหม่มาเองเพื่อให้ build ผ่าน ผู้ดูแลต้องตัดสินใจเองว่าจะลดเงื่อนไขเวอร์ชันลงหรือยกเว้นรุ่นนั้น ส่วนหน้า Configuration ระบุว่าการตั้งค่านี้จะถูกละไว้หาก registry ไม่รองรับข้อมูลเวลาเผยแพร่

## ตัวอย่างเมื่อ Cargo cooldown ข้ามรุ่นใหม่

RFC 3923 ยกตัวอย่างโปรเจกต์ที่ตั้งอายุขั้นต่ำไว้ 14 วัน เมื่อสั่ง `cargo update` แล้ว crate ชื่อ some-package มีรุ่น 1.3.0 ที่เพิ่งเผยแพร่มา 2 วัน Cargo จะเลือกรุ่น 1.2.3 ที่เก่ากว่าแทน และแสดงในบรรทัดผลลัพธ์ว่ามีรุ่น 1.3.0 ให้ใช้แต่เพิ่งเผยแพร่เมื่อ 2 วันก่อน นักพัฒนาจึงเห็นว่ามีรุ่นใหม่รออยู่โดยไม่ต้องรับมันมาทันที

อีกกรณีคือเมื่อไฟล์ Cargo.toml กำหนดให้ต้องใช้รุ่น 1.3 ขึ้นไป แต่รุ่นที่ตรงเงื่อนไขทั้งหมดยังใหม่เกินกำหนด ในตัวอย่างของ RFC Cargo จะหยุดพร้อมคำแนะนำ 2 ทาง คือลดเงื่อนไขเวอร์ชันลงมาเป็นรุ่นที่เก่าพอ หรือ resolve ใหม่โดยตั้งค่ายกเว้นชั่วคราว ทีมจึงต้องเลือกเองอย่างรู้ตัวทุกครั้ง

## Cargo cooldown เหมาะกับโปรเจกต์แบบไหน

ฟีเจอร์นี้ให้ผลชัดที่สุดกับแอปพลิเคชันและบริการที่ build จาก Cargo.lock ของตัวเอง เช่น บริการแบ็กเอนด์ เครื่องมือบรรทัดคำสั่ง หรือระบบที่ CI สั่ง `cargo update` อัตโนมัติเป็นประจำ เพราะจุดที่รุ่นใหม่เข้ามาคือการ resolve ครั้งใหม่ ซึ่ง Cargo cooldown ไปตรวจตรงนั้น

ส่วนทีมที่พัฒนาไลบรารีให้คนอื่นใช้ RFC เสนอให้คิดแบบผสม คือเปิดการรอสำหรับงานประจำวันเพื่อลดความเสี่ยง แต่มีงาน CI ที่ทำหน้าที่เป็น "นกขมิ้น" คอยทดสอบกับรุ่นล่าสุดเสมอ เพื่อให้รู้ปัญหาของ dependency ก่อนผู้ใช้ปลายทาง ทีมที่ต้องการความเสถียรสูงจะตั้งช่วงรอยาวขึ้นได้ โดยแลกกับการได้รับการแก้บั๊กช้าลง

## ตั้งค่า Cargo cooldown ได้ที่ไหน

ค่าที่เกี่ยวข้องอยู่ในไฟล์ `.cargo/config.toml` ของโปรเจกต์หรือของผู้ใช้ และตั้งผ่านตัวแปรสภาพแวดล้อมได้ทุกค่า

| ค่า | ค่าเริ่มต้น | ตัวแปรสภาพแวดล้อม | ใช้ทำอะไร |
| --- | --- | --- | --- |
| `registry.global-min-publish-age` | `"0"` | `CARGO_REGISTRY_GLOBAL_MIN_PUBLISH_AGE` | อายุขั้นต่ำที่ใช้กับทุก registry |
| `registries.<name>.min-publish-age` | ใช้ค่า global | `CARGO_REGISTRIES_<name>_MIN_PUBLISH_AGE` | อายุขั้นต่ำเฉพาะ registry นั้น เช่น registry ภายในองค์กร |
| `resolver.incompatible-publish-age` | `"deny"` | `CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE` | ข้ามรุ่นที่ใหม่เกิน (`deny`) หรือไม่ตรวจ (`allow`) |

ค่าอายุเขียนเป็นตัวเลขตามด้วยหน่วย seconds, minutes, hours, days, weeks หรือ months และ `"0"` คือยอมรับทุกรุ่น เอกสารบอกว่าที่ใช้กันทั่วไปคือ `"0"`, `"N days"` และ `"N weeks"` ทุกค่าในตารางนี้มีผลตั้งแต่ Cargo 1.100 ตัวอย่างที่ RFC ใช้คือ

```toml
[registry]
global-min-publish-age = "14 days"
```

องค์กรที่มี registry ภายในซึ่งเชื่อถือได้ ตั้ง `min-publish-age = "0"` ให้ registry นั้นโดยเฉพาะได้ เพื่อให้ crate ของทีมเองใช้ได้ทันที

![เอกสาร Cargo Book หัวข้อ registry.global-min-publish-age ระบุค่าเริ่มต้นเป็น "0" หน่วยเวลาที่รองรับ และมีผลตั้งแต่ Cargo 1.100](https://thaidata-co-th.s3.ap-southeast-1.amazonaws.com/thaidata.co.th/images/articles/cargo-cooldown-rust-1-100-min-publish-age/swb2-dev-cargo-global-min-publish-age-docs.webp?v=64bd8945) _(ภาพ: The Rust Project (The Cargo Book))_

## เมื่อต้องรีบใช้แพตช์ที่เพิ่งออก

กรณีที่ต้องใช้รุ่นใหม่ทันที เช่น รุ่นที่แก้ช่องโหว่ RFC 3923 ให้ตั้ง `CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow` ชั่วคราว แล้วสั่ง `cargo update` พร้อม `--precise` ระบุรุ่นที่ต้องการ เมื่อรุ่นนั้นถูกบันทึกใน Cargo.lock แล้ว การ resolve ครั้งต่อไปจะคงรุ่นนั้นไว้

RFC ยังเสนอรูปแบบที่ใช้ได้จริงในทีม คือเปิด Cargo cooldown สำหรับงานประจำวัน แต่มี CI job แยกที่ตั้ง `allow` แล้วรัน `cargo update`, build และ test กับรุ่นล่าสุดเสมอ ทีมจะรู้ล่วงหน้าว่ารุ่นใหม่ทำให้อะไรพังหรือไม่ โดยไม่ต้องให้ทุกเครื่องรับรุ่นใหม่ในวันแรก

## Cargo cooldown ป้องกันอะไรได้ และไม่ได้

RFC 3923 เขียนไว้ตรง ๆ ว่าฟีเจอร์นี้ "ไม่ใช่ทางแก้ครบวงจร" สำหรับ dependency ที่ถูกเจาะ มันช่วยกับการโจมตีบางประเภทเท่านั้น และไม่ควรใช้เป็นมาตรการความปลอดภัยเพียงอย่างเดียว ข้อจำกัดที่ทีมควรรู้มีดังนี้

- ช่วยเฉพาะกรณีที่มีคน **พบปัญหาภายในช่วงที่รอ** ถ้ารุ่นอันตรายไม่ถูกพบเลยภายใน 7 หรือ 14 วัน การรอก็ไม่ช่วย
- **แพตช์แก้ไขก็ถูกหน่วงด้วย** รุ่นที่แก้บั๊กหรือช่องโหว่จะติดเงื่อนไขเดียวกัน จึงต้องมีขั้นตอนยกเว้นที่ทีมรู้วิธีใช้
- รุ่นที่ **อยู่ใน Cargo.lock แล้ว** จะไม่ถูกตรวจซ้ำ การตั้งค่าจึงมีผลกับการ resolve ครั้งใหม่ ไม่ได้ย้อนตรวจของที่ล็อกไว้
- ใช้ได้กับ **registry ที่ให้ข้อมูลเวลาเผยแพร่** เท่านั้น

![หน้า RFC 3923 cargo_min_publish_age แสดงบทสรุปของข้อเสนอและตัวอย่างการตั้ง global-min-publish-age เป็น 14 days](https://thaidata-co-th.s3.ap-southeast-1.amazonaws.com/thaidata.co.th/images/articles/cargo-cooldown-rust-1-100-min-publish-age/swb2-dev-rfc-3923-cargo-min-publish-age.webp?v=d88b278b) _(ภาพ: The Rust Project (The Rust RFC Book))_

## Rust 1.100 และ Cargo 1.100 มีอะไรอีก

นอกจาก Cargo cooldown changelog ของ Cargo 1.100 มีการเปลี่ยนแปลงที่ทีม Rust ควรรู้ก่อนอัปเกรด

- **ระบบ lint ของ Cargo เป็นฟีเจอร์เสถียร** คำเตือนบางอย่างของ Cargo กลายเป็น lint ที่ปรับระดับได้ในตาราง `[lints.cargo]` ชุดแรกมี `cargo::unused_dependencies` สำหรับตรวจ dependency ที่ประกาศไว้แต่ไม่ได้ใช้
- **โครงสร้างโฟลเดอร์ของไฟล์ build ระหว่างทางเปลี่ยนใหม่** เครื่องมือที่อ่านโฟลเดอร์ build โดยตรงควรเปลี่ยนไปใช้ข้อความ JSON ของ Cargo เพราะโครงสร้างนี้ไม่ใช่อินเทอร์เฟซที่รับประกันว่าจะคงที่
- **`cargo install` ใช้ lockfile ที่มากับแพ็กเกจเป็นค่าเริ่มต้น** ตัวเลือก `--locked` จึงไม่มีผลอีก
- เมื่อตั้ง `build.warnings='deny'` สรุปผล build จะรายงานจำนวน error ด้วย ไม่ใช่เฉพาะคำเตือน

| เหตุการณ์ | วันที่ |
| --- | --- |
| เริ่ม RFC 3923 | 23 ก.พ. 2026 |
| Rust 1.100 และ Cargo 1.100 พร้อม Cargo cooldown แบบเสถียร | 12 พ.ย. 2026 (กำหนดการ) |

## ผลต่อองค์กรไทยและทีมพัฒนา

1. **กำหนดนโยบายอายุขั้นต่ำของ dependency** ทีมที่ใช้ Rust ในบริการจริงควรตกลงว่าจะใช้กี่วัน แล้วใส่ใน `.cargo/config.toml` ของ repository เพื่อให้ทุกเครื่องและ CI ใช้ค่าเดียวกันหลังอัปเกรดเป็น Rust 1.100
2. **เขียนขั้นตอนยกเว้นไว้ล่วงหน้า** เมื่อมีแพตช์ช่องโหว่ด่วน ทีมต้องรู้ว่าจะใช้ `CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow` กับ `cargo update --precise` อย่างไร และใครเป็นผู้อนุมัติ
3. **แยก CI job ที่ทดสอบรุ่นล่าสุด** ตามแนวทางใน RFC เพื่อไม่ให้ Cargo cooldown กลายเป็นการค้างรุ่นเก่าโดยไม่รู้ตัว
4. **ตั้งค่า registry ภายในแยก** ถ้าองค์กรมี registry ของตัวเอง ให้ตั้ง `min-publish-age` เฉพาะ registry นั้นตามความเชื่อถือ
5. **ใช้ร่วมกับมาตรการอื่น** เช่น การรีวิว dependency และเครื่องมือกรองแพ็กเกจอย่าง [GitHub package firewall](/software/github-package-firewall-npm-public-preview/) สำหรับระบบนิเวศอื่น ติดตามข่าวเครื่องมือนักพัฒนาได้ที่[หมวดการพัฒนาซอฟต์แวร์](/software/development/)

## คำถามที่พบบ่อย

### Cargo cooldown คืออะไร?

Cargo cooldown คือการตั้งอายุขั้นต่ำของ crate รุ่นที่ Cargo จะยอมเลือกใช้ เช่น 7 วันหลังเผยแพร่บน registry เพื่อให้เวลาเครื่องสแกนและชุมชนพบปัญหาในรุ่นใหม่ก่อนที่ build ของเราจะดึงไปใช้ ตั้งค่าได้ด้วย registry.global-min-publish-age และจะเสถียรใน Rust 1.100 วันที่ 12 พฤศจิกายน 2026

### อัปเกรดเป็น Rust 1.100 แล้ว Cargo cooldown เปิดเองหรือไม่?

ไม่เปิดเอง เอกสารของ Cargo ระบุว่าค่าเริ่มต้นของ registry.global-min-publish-age คือ 0 ซึ่งหมายถึงยอมรับทุกรุ่น ทีมต้องตั้งค่าเองใน .cargo/config.toml หรือผ่านตัวแปรสภาพแวดล้อม CARGO_REGISTRY_GLOBAL_MIN_PUBLISH_AGE

### ถ้าต้องใช้แพตช์ความปลอดภัยที่เพิ่งออกแต่ติด Cargo cooldown ทำอย่างไร?

RFC 3923 ออกแบบทางยกเว้นไว้ โดยตั้ง CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow ชั่วคราวแล้วสั่ง cargo update ระบุรุ่นที่ต้องการ เมื่อรุ่นนั้นถูกบันทึกใน Cargo.lock แล้ว การ resolve ครั้งต่อไปจะคงรุ่นนั้นไว้แม้ยังใหม่กว่าที่กำหนด

### Cargo cooldown กันมัลแวร์ใน crate ได้ทั้งหมดไหม?

ไม่ได้ RFC 3923 เขียนไว้ชัดว่าเป็นเพียงการลดความเสี่ยงจากการโจมตีบางแบบที่มักถูกพบเร็วหลังเผยแพร่ ไม่ใช่ทางแก้ครบวงจร และไม่ควรใช้เป็นมาตรการความปลอดภัยเพียงอย่างเดียว ทีมยังต้องรีวิว dependency และสแกนโค้ดตามปกติ


## แหล่งอ้างอิง

- [Cargo Changelog — Cargo 1.100 (2026-11-12)](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html) — The Rust Project
- [RFC 3923: cargo_min_publish_age](https://rust-lang.github.io/rfcs/3923-cargo-min-publish-age.html) — The Rust Project
- [Configuration — The Cargo Book](https://doc.rust-lang.org/nightly/cargo/reference/config.html) — The Rust Project
- [Dependency Resolution — The Cargo Book](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html) — The Rust Project
