5 คะแนน โดย GN⁺ 15 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • จากการทดสอบ OpenCode ซึ่งเป็นโอเพนซอร์ส AI coding agent ที่มี GitHub star 161k ด้วย Qwen3.6-27B แบบรันในเครื่อง พบว่าทั้งคุณภาพของเครื่องมือและการออกแบบด้านความปลอดภัยอยู่ในระดับที่ควรหยุดใช้งาน
  • การรีโหลด AGENTS.md, การตัดแต่งคอนเท็กซ์ตามระยะคงที่, การแทรกวันที่ปัจจุบัน, และการสลับโหมด ทำให้ prompt cache ถูกทำให้ใช้ไม่ได้ซ้ำๆ จนแม้แต่บน M4 Max ก็อาจต้องรอนานสูงสุด 10 นาทีกว่าจะเริ่มสร้างคำตอบได้
  • session compaction, system prompt, การยืนยันสิทธิ์, การควบคุม sub-agent, และ TUI ทำงานไม่ประสานกันดีพอ จนเกิด การสูญหายของคอนเท็กซ์และข้อความ และอาจเขียนโค้ดโดยลืมสเปกสำคัญไป
  • permission filter ที่อาศัย Bash AST และรูปแบบสตริง ไม่สามารถป้องกัน indirect execution, absolute path, ตัวแปร, Python, การ redirect ฯลฯ ได้ และยังเลี่ยงข้อจำกัดการเข้าถึงไฟล์ภายนอกกับสิทธิ์ถาวรได้ง่าย
  • เมื่อพิจารณาจากการเชื่อมต่อโมเดลระยะไกลเป็นค่าเริ่มต้น, การเข้าถึงอินเทอร์เน็ตแบบไม่จำกัด, และช่องโหว่ HTTP server RCE ในอดีต จะเห็นว่า Docker อย่างเดียวไม่พอ และจำเป็นต้องมีการบล็อก executable, เส้นทางแบบ read-only, และ การแยกระดับระบบปฏิบัติการ

ขอบเขตการประเมินและสมมติฐาน

  • OpenCode เป็นโปรเจ็กต์ที่ผู้สร้างแนะนำว่าเป็น AI coding agent และขณะตรวจสอบมี GitHub star 161k
  • ทดสอบโดยอิงกับ LLM แบบรันในเครื่อง Qwen3.6-27B และ OpenCode Git เวอร์ชัน baef5cd4
  • ไม่ได้เป็นการเปิดเผยด้านความปลอดภัยโดยเฉพาะ แต่เป็นการดูว่าเลเยอร์ท่อส่งล้มเหลวอย่างไรในโครงสร้างที่ส่งผลลัพธ์จาก LLM ไปยัง Bash
  • แยกประเด็นการใช้ LLM ออกจากประเด็นที่เครื่องของผู้ใช้จะถูกเจาะหรือถูกลบได้ง่าย

โครงสร้างที่ทำลาย prompt cache ซ้ำๆ

  • API ตระกูล OpenAI /v1/chat/completions ส่งบทสนทนาทั้งหมดจนถึงตอนนั้นเป็น JSON และตอบกลับด้วย SSE delta stream ที่แนบ JSON metadata
    • ยิ่ง session ยาว ค่าอัปโหลดก็ยิ่งเพิ่มแบบ กำลังสอง
    • การเรียกใช้เครื่องมือใช้การเข้ารหัสสองชั้น โดยประกอบ JSON delta หลายชุดกลับเป็น JSON อีกครั้ง
  • ฝั่งเซิร์ฟเวอร์เป็นโครงสร้างไร้สถานะ แต่มีการแคชผลลัพธ์เพื่อประสิทธิภาพ
    • ค้นหา cache prefix ที่ยาวที่สุดซึ่งตรงกับคำขอ
    • ทำ prefill จากท้าย prefix จนถึงข้อความล่าสุด
    • สร้างโทเค็นใหม่จนถึง token สิ้นสุด
  • บน M4 Max ที่มีแบนด์วิดท์หน่วยความจำราว 0.5TB/s การสร้างโทเค็นของ Qwen3.6-27B ยังพอใช้งานได้ แต่ prefill ของคอนเท็กซ์ยาวมีภาระคำนวณสูงมาก
    • หากหา prefix cache ที่เหมาะสมไม่เจอ อาจต้องรอ ราว 10 นาที โดยใช้ GPU เต็มที่ก่อนจะเริ่มสร้างคำตอบ
  • OpenCode จะ glob ไฟล์ซิสเต็มทุก SSE turn และอ่าน AGENTS.md ที่แทรกไว้ใน system prompt แรกซ้ำอีกครั้ง
    • แม้จะแก้ AGENTS.md เพื่อ session ถัดไป ก็ยังทำให้ session ปัจจุบันทั้งหมดต้องถูกประเมินใหม่
  • เมื่อสลับจาก agent ไปเป็น user จะมีการตัดแต่ง tool call context ทำให้ช่วง cache ขนาดใหญ่ใช้ไม่ได้
    • เนื่องจากทิ้งผลลัพธ์ของเครื่องมือที่เก่ากว่า PRUNE_PROTECT = 40_000 จึงเกิด cache miss 40k token แม้ในกรณีดีที่สุด
    • การขัดจังหวะก็ถูกนับเป็นการสลับไปฝั่งผู้ใช้ ดังนั้นหากแก้ทิศทางที่ผิดพลาด cache จะถูกทิ้งและต้องรอใหม่
  • เพราะมีการใส่ วันที่ปัจจุบัน ลงใน system prompt แรกและประเมินใหม่ทุก SSE turn เมื่อข้ามเที่ยงคืนจะเกิด cache miss ทั้งหมด

การตัดแต่งและ session compaction

  • การตัดแต่งถูกใช้กับผลลัพธ์ของเครื่องมือทุกตัว ยกเว้น skill และไม่ได้ปกป้องเอกสารสำคัญที่อ่านตอนต้นเป็นพิเศษ
    • อ่านสเปกก่อนใน session ใหม่
    • อ่านโค้ดที่เกี่ยวข้องเพิ่มเติมจนเกินเกณฑ์ 40k token
    • โมเดลหลุดไปสู่การให้เหตุผลที่ไม่จำเป็นหรือทิศทางที่ผิดจนผู้ใช้ต้องขัดจังหวะ
    • เมื่อขัดจังหวะ สเปกจะถูกลบออกจากคอนเท็กซ์
    • โมเดลจึงนำไปใช้ต่อโดยอ้างอิงสเปกเดิมไม่ได้
  • session compaction จะนำ prompt ใหม่ไปต่อไว้หน้าของ session เดิม ทำ prefill ทั้งหมดใหม่ แล้วสรุปเป็น bullet ไม่กี่ข้อ
    • หากวาง prompt สำหรับสรุปไว้ท้าย session ก็หลีกเลี่ยง prefill ทั้งหมดได้
    • วิธีให้โมเดลเขียน handoff note ลงไฟล์เองทำงานได้ดีกว่า และยังแก้ไขผลลัพธ์หรือใช้ซ้ำข้ามหลาย session ได้ด้วย
  • การบีบอัดเป็น abstraction ที่รั่ว ซึ่งทำให้หน้าต่างคอนเท็กซ์ที่มีขนาดจำกัดดูเหมือนไม่จำกัด และยิ่งแย่เมื่อใช้ร่วมกับการตัดแต่ง
  • ควรยอมรับว่าหน้าต่างคอนเท็กซ์และ prompt cache เป็นข้อจำกัดพื้นฐาน แล้วให้เครื่องมือสำหรับจัดการ โดย session tree ของ Pi ใช้ prompt cache อย่างจงใจ

system prompt และโหมด Plan

  • system prompt ค่าเริ่มต้นยาวมาก และใช้เนื้อหาส่วนใหญ่ไปกับการสั่งให้โมเดลตอบอย่างกระชับ
  • ยังรวมรสนิยมการเขียนโค้ดที่เข้มข้น เช่น สั่งให้ sub-agent ใช้ ABSOLUTELY NO COMMENTS
  • ขั้นตอนส่งต่อจาก Plan ไป Build ไม่ลื่นไหล ทำให้ถ้าวางแผนละเอียดพอ คอนเท็กซ์อาจเข้าใกล้ปลายหน้าต่างคอนเท็กซ์
    • ผู้เขียนจึงชอบวิธีเขียนและแก้ไขผลสรุปลงไฟล์ แล้วส่งต่อไปยัง session ใหม่
  • การแจ้งเตือนของโหมด Plan บอกว่าเขียนลงไดเรกทอรีใดๆ ไม่ได้ แต่จริงๆ แล้วเขียนลง .opencode/plans ได้
    • พบทั้งกรณีที่มันเขียนลงไดเรกทอรีนั้นทั้งที่ไม่ได้สั่ง และกรณีที่ปฏิเสธการเขียนทั้งที่ร้องขออย่างชัดเจน
  • ไม่สามารถแก้ไข system prompt เริ่มต้นแบบ global ได้ จึงต้อง คัดลอกแยกตามโปรเจ็กต์
  • หาก override เฉพาะ prompt ของโหมด Build เมื่อสลับไปโหมด Plan จะเกิด prompt cache miss ทั้งหมด
  • prompt รายโมเดลมีความต่างกันมากทั้งด้านเนื้อหาและคุณภาพ
    • Beast Mode สำหรับ GPT-4, o1, o3 สั่งว่าการจะเข้าใจแพ็กเกจและ dependency ของบุคคลที่สามต้องอาศัยการตรวจสอบด้วย Google เสมอ

ความล้าจากการตัดสินใจที่เกิดจากการยืนยันสิทธิ์

  • เมื่อพบความพยายามเข้าถึงไฟล์นอกโปรเจ็กต์ด้วยการวิเคราะห์สตริงแบบเฉพาะกิจ จะมีหน้าต่างสิทธิ์ Yes, No, Always โผล่ขึ้นมา และหยุดการทำงานจนกว่าจะตอบ
    • ไม่มีตัวเลือก Never สำหรับปฏิเสธงานแบบเดียวกันนี้ในอนาคต
  • เมื่อ sub-agent พยายามอ่านผลลัพธ์สคริปต์ใน /tmp แล้วเลือก No agent จะจบทันทีและคอนเท็กซ์ของงานก็หายไปด้วย
    • ถ้าต้องการเก็บความคืบหน้าไว้ จึงเกิดสถานการณ์ที่ต้องเลือก Yes แม้เป็นการเข้าถึงภายนอกที่ไม่ต้องการ
  • หากคำขออนุญาตถูกถามซ้ำๆ และตัวเลือกเดียวที่รักษาผลิตภาพได้คือ Yes ผู้ใช้ก็อาจกดอนุมัติแม้แต่คำขอที่เสี่ยง
  • กลไกความปลอดภัยพื้นฐานที่ป้องกันการเขียนนอกไดเรกทอรี ไม่ควรพึ่งพา ความใส่ใจอย่างต่อเนื่องของมนุษย์

ปฏิสัมพันธ์ระหว่างข้อความและ sub-agent

  • ข้อความที่ส่งระหว่าง SSE streaming จะเข้าไปอยู่ในคิว แต่ไม่ชัดเจนว่าถูกส่งจริงเมื่อใด
    • จากโค้ดดูเหมือนจะส่งตอนสิ้นสุด tool call turn แต่ก็พบกรณีที่เปลี่ยนจากเครื่องมือไปเป็นกระบวนการคิดโดยไม่ส่งข้อความที่ค้างไว้
    • หากผู้ใช้ขัดจังหวะ ข้อความจะหลุดจากสถานะรอและเหลืออยู่แค่ใน log โดยไม่สามารถส่งได้อีก จึงต้องมีข้อความที่สองเพื่อเริ่ม stream ใหม่
  • บางครั้งการ undo ข้อความก็ไม่สามารถลบข้อความนั้นออกจาก log ได้
  • ไม่สามารถคุยกับ sub-agent โดยตรงหรือสั่งหยุดความคืบหน้าได้
    • ถ้าไปผิดทางก็มีแต่ต้องจบมันทิ้งจนเสียคอนเท็กซ์ หรือดูมันเผาโทเค็นต่อไป
    • ดูเหมือนว่าในอดีตเคยมีฟังก์ชันนี้ แต่ตอนนี้หายไปแล้ว
    • แม้จะ @mention sub-agent ในแชตหลัก ก็ไม่ได้ช่วยมากและยังหยุดมันไม่ได้
  • หาก tool call ของ sub-agent ล้มเหลว เช่นกรณีที่ Qwen ใส่ tool call ลงในกระบวนการคิด จะเกิดข้อผิดพลาดร้ายแรงและคอนเท็กซ์จนถึงตอนนั้นจะหายไป
  • การนำ sub-agent กลับมาใช้ซ้ำขัดกับเป้าหมายของการแยกงานออกเป็นคอนเท็กซ์เล็กๆ
    • อาจนำ sub-agent เดิมกลับมาใช้กับงานที่ไม่เกี่ยวกัน
    • การสลับไปมาระหว่าง main agent ที่มีคอนเท็กซ์ใหญ่กับ sub-agent ทำให้เกิด cache miss
    • ปฏิสัมพันธ์สำหรับมนุษย์จะหลากหลายได้ แต่ควรลดตัวเลือกที่ให้กับโมเดล
  • มี GitHub issue ที่เกี่ยวกับพฤติกรรมของ sub-agent ด้วย

การออกแบบเครื่องมือของ agent

  • edit โดยพื้นฐานจะทำ ค้นหา-แทนที่แบบตรงตัว กับข้อความที่ตรงกันเพียงจุดเดียว
    • เป็นวิธีที่เหมาะ เพราะโมเดลมักจำเนื้อหาไฟล์ได้แม่น แต่หลังแก้หลายครั้งอาจพลาดหมายเลขบรรทัดที่เปลี่ยนไป
    • ตัวเลือกแทนที่ทั้งไฟล์ทำให้เกิดการแก้ตามมาอีกหลายรอบ และหากเอาออกก็จะเหมือนการออกแบบ edit ของ Pi
  • เครื่องมือ question แบบหลายตัวเลือกในโหมด Plan ใช้งานลำบากกว่าการให้ถามด้วยภาษาธรรมชาติผ่าน system prompt
  • grep และ glob ใช้ bash แทนได้ และในทางปฏิบัติโมเดลก็มักรัน grep หรือ rg ผ่าน Bash
    • จุดประสงค์อาจเป็นการจำกัดไม่ให้ agent แบบอ่านอย่างเดียวอย่าง Explore ใช้ Bash
    • เรื่องนี้เชื่อมโยงกับปัญหาที่ตัดสินผลข้างเคียงได้ยากโดยไม่รันคำสั่ง Bash จริง
  • todo โดยรวมมีประโยชน์ แต่โมเดลมักลืมตรวจ TODO เอง

TUI และคุณภาพเอกสาร

  • TUI ของ OpenCode ใช้ RAM ราว 1GB สำหรับการเรนเดอร์ข้อความ
  • ในช่องป้อนข้อความ Shift+Enter สำหรับขึ้นบรรทัดใหม่ไม่ทำงาน และ issue เดิมก็ถูกปิดหลังจากมีคำตอบว่า “บนเครื่องผมใช้ได้”
  • เมื่อข้อความยาวถูกตัดบรรทัดอัตโนมัติ ช่องป้อนและเคอร์เซอร์จะเลื่อน แต่ตัวอักษรของบรรทัดใหม่อาจไม่แสดง
  • หากเลือกข้อความระหว่างการสตรีม การเลื่อนอัตโนมัติจะยกเลิกการเลือกนั้น
  • Ctrl-C ไม่ได้หยุดคำสั่งที่กำลังรัน แต่ปิด session ทันที
    • ตามธรรมเนียมของ interactive shell แล้ว Ctrl-C ควรหยุดคำสั่ง และเมื่อไม่มีคำสั่งรันอยู่ Ctrl-D ควรปิด session
  • ไม่รองรับคีย์ลัดการย้ายทีละคำที่พบได้ทั่วไป เช่น Option+ลูกศรซ้าย/ขวาบน Mac
  • เมื่อข้อความหรือกระบวนการคิดยาวขึ้น การเรนเดอร์ Markdown ใหม่ ฯลฯ อาจใช้เวลาหลายวินาที และดูเหมือนมีปัญหาด้านประสิทธิภาพแบบ ความซับซ้อนกำลังสอง
  • เพราะปัญหาการป้อนข้อความ จึงต้องเขียนข้อความใน editor ภายนอกแล้วค่อยวาง
  • เอกสารไม่สม่ำเสมอ และใกล้เคียงกับการเขียนให้โมเดลอ่านมากกว่าให้คนอ่าน

การเชื่อมต่อแบบ remote-first และการเปิดเผยข้อมูล

  • OpenCode เชื่อมต่อกับ remote model เป็นค่าเริ่มต้น
  • เอกสารไม่มีตัวอย่างง่ายๆ สำหรับการตั้งค่า local model และหากตั้งค่าผิดก็จะไปเชื่อมต่อ remote model
  • แม้จะระบุ local model ถูกต้องแล้ว หลังเริ่มโปรแกรมก็ยังต้องเลือกแบบ interactive อยู่ดี และระหว่างนั้น remote model กับ local shell ก็เชื่อมต่อกันแล้ว
  • URL ของโมเดลค่าเริ่มต้นไม่ได้ตรึงอยู่ในตัวแพ็กเกจ แต่ดาวน์โหลดจาก models.dev ที่เชื่อมโยงกับ OpenCode
    • โค้ดที่เกี่ยวข้องอยู่ที่ opencode/src/provider/provider.ts บรรทัด 1684
  • หลังติดตั้งใหม่ เพียงรัน opencode แล้วพิมพ์อักขระหนึ่งตัวกับ Enter ก็อาจทำให้ remote model เชื่อมต่อกับ local shell ได้โดยไม่ต้องตั้งค่าใดๆ
  • หากข้อความแรกว่างหรือกำกวม agent model มัก glob ไดเรกทอรีปัจจุบันและอ่านไฟล์ และข้อมูลที่อ่านจะถูกแนบไปกับคำขอ POST ถัดไป

การเข้าถึงอินเทอร์เน็ตและ system prompt

  • OpenCode มีเครื่องมือ WebFetch และ system prompt ก็สั่งอย่างชัดเจนให้ใช้งานมัน
  • prompt ค่าเริ่มต้นอนุญาตอย่างกำกวมให้ใช้ URL จากข้อความที่ผู้ใช้ให้มาหรือจากไฟล์ในเครื่อง และหากมั่นใจว่าเป็น URL สำหรับช่วยเขียนโปรแกรม ก็สามารถสร้างหรือเดา URL เองได้
  • เนื่องจาก Bash ไม่มี network sandbox ปัญหาที่ใหญ่กว่า WebFetch คือโครงสร้างที่คาดหวังว่าโมเดลจะไม่รันคำสั่งอย่าง curl | bash

วิธีเลี่ยง Bash permission filter

  • "bash": {"git *": "deny"} ใน opencode.json จะบล็อก git status หรือ echo hello && git push --force
  • การทำงานภายในใช้ไวยากรณ์ Bash·PowerShell ของ tree-sitter เพื่อ parse คำสั่งเป็น AST แล้วไล่ดู command node เพื่อนำไปเทียบกับ regex ที่สร้างจากการตั้งค่า
  • แต่การตรวจแบบอิงข้อความเปิดทางให้หลบเลี่ยงผ่านการรันทางอ้อมหลายแบบ
    • echo 'git clean -fdx .' | bash
    • env git status
    • การผูก git กับชื่อคำสั่งอื่นผ่าน alias
    • /usr/bin/git status, $(which git) status
    • GIT=git && $GIT status
    • การถอดรหัส Base64 ของ git reset --hard แล้วส่งเข้า Bash
    • git push --force ภายใน heredoc
    • รัน git checkout . ผ่าน Python subprocess.run
  • แม้โมเดลจะไม่ได้มุ่งร้ายตามปกติ แต่เพราะถูกฝึกให้พยายามหาทางอ้อมความล้มเหลวอย่างไม่ย่อท้อ จึงอาจ มีพฤติกรรมเหมือนอินพุตเชิงปฏิปักษ์ ได้โดยธรรมชาติ
  • ตัวกรองคำสั่งแบบสตริงไม่ใช่มาตรการความปลอดภัย แต่เป็นความอุ่นใจที่ผิดๆ

สิทธิ์ถาวรและข้อยกเว้น CWD

  • หากเลือก Always ให้ python3 -c 'print("hello")' prefix ทั้งหมดของ python3 จะได้รับอนุญาตถาวร
    • หลังจากนั้นคำสั่ง Python ที่อ่าน SSH private key ก็อาจถูกถือว่าได้รับอนุมัติไปแล้ว
    • สิทธิ์ถูกบันทึกลงดิสก์และคงอยู่ใน session ถัดไปด้วย
  • cd, chdir, popd, pushd, push-location, set-location อยู่ใน รายการข้อยกเว้น CWD ที่ถือว่าไม่มีผลข้างเคียง
  • คำสั่งเหล่านี้จงใจข้ามการตรวจสิทธิ์ แม้จะตั้งค่าให้ปฏิเสธคำสั่ง Bash ทั้งหมดก็ตาม

ช่องโหว่ของการตรวจการเข้าถึงไฟล์

  • การตั้งค่าเริ่มต้นพยายามป้องกันการเข้าถึงไฟล์นอกเส้นทางที่สั้นกว่าระหว่างไดเรกทอรีที่รัน OpenCode กับ Git repository
  • ในเครื่องมือ Bash จะไล่ดู tree-sitter AST แล้วตีความค่าที่ดูเหมือน path เพื่อตรวจสอบ
    • cat /tmp/logfile จะร้องขอสิทธิ์
    • python3 -c 'import shutil; shutil.rmtree("/")' ตรวจไม่พบ
  • cargo สามารถอ่าน·เขียน·รันได้อย่างอิสระใน ~/.cargo แบบ global แต่หากโมเดลพยายามอ่านซอร์สแพ็กเกจใน ~/.cargo/registry/src โดยตรงจะมีการขอสิทธิ์
  • คำสั่งที่ถือว่าสามารถเข้าถึงไฟล์ได้ถูกจำกัดอยู่ใน รายการ FILES แบบคงที่
    • มี rm, cp, mv, mkdir, touch, chmod, chown, cat และคำสั่ง PowerShell บางส่วน
    • คำสั่งที่ไม่อยู่ในรายการจะถูกถือว่าไม่แตะไฟล์ จึงไม่ตรวจ path ที่ส่งมา

การรวมการ redirect กับคำสั่งที่ได้รับอนุญาต

  • หากเลือก Always ให้ echo "hello world!" ก็จะอนุญาตการเขียนไฟล์หรืออุปกรณ์ผ่าน echo ในภายหลังด้วย
    • รวมถึงคำสั่งที่ redirect ไปยัง path อย่าง /sys/class/gpio ที่เกี่ยวกับ GPIO
  • ใน AST ของ echo foo > bar.txt นั้น redirection ไม่ได้เป็นลูกของ command แต่เป็นโหนดพี่น้อง
    • การตรวจ path ดูเฉพาะลูกของ command จึงไม่ตรวจปลายทางของการ redirect
    • และตัว echo เองก็ไม่อยู่ในรายการ FILES จึงไม่เริ่มการตรวจ path ตั้งแต่แรก

กรณี self-upgrade และ remote code execution

  • OpenCode มีเส้นทาง self-upgrade หลายแบบ และเมื่อรัน opencode upgrade จากแพ็กเกจที่ติดตั้งด้วย curl มันจะดาวน์โหลดผลลัพธ์จาก https://opencode.ai/install แล้ว รันผ่าน standard input ของ Bash
  • แม้จะไม่ต่างจากความเสี่ยงตอนใช้ตัวติดตั้งแบบ curl มากนัก แต่นี่ก็เป็นกรณีของการรันสคริปต์ระยะไกลโดยตรงใน production
  • ช่วง CVE-2026-22812 OpenCode เคยเปิดฟังก์ชันต่อไปนี้บน HTTP server ค่าเริ่มต้น
    • CORS header ที่อนุญาตทุกอย่างทั้งหมด
    • POST API สำหรับรัน shell command ตามอำเภอใจ
    • GET API สำหรับอ่านไฟล์ใดก็ได้
  • เว็บไซต์ที่ผู้ใช้เข้าเยี่ยมชมสามารถส่งคำขอไปยังพอร์ตค่าเริ่มต้นที่รู้กัน เพื่อเข้าถึงระบบในระดับสิทธิ์ของผู้ใช้ได้
  • ทีมพัฒนาตอบว่าได้ปิดการใช้งานเซิร์ฟเวอร์เป็นค่าเริ่มต้นแล้ว และจำเป็นต้องมี CORS exception เพื่อให้ opencode.ai รันโค้ดจากระยะไกลบนเครื่องได้ ก่อนจะไม่มีการตอบสนองต่อเพิ่มเติม และ issue ก็ถูก stale bot ปิด
  • อีก issue รายงานว่าคำสั่งยืนยันตัวตนดึงและรันคอนเทนต์จาก URL ตามอำเภอใจที่ผู้ใช้ส่งมา และกรณีนี้ก็จบลงด้วย stale bot เช่นกัน

ทำไม Docker อย่างเดียวถึงแก้ไม่ได้

  • ผู้เขียนไม่ต้องการแนวทางที่ทำให้การติดตั้ง dependency สำหรับพัฒนาบนเครื่องใหม่ซับซ้อนจนแทบทำไม่ได้ แล้วผลักภาระไปให้ Docker
  • ตัว Docker เองก็อาจสร้างปัญหาด้านความปลอดภัยได้
    • มันสร้าง service ทรงพลังที่รันด้วย root
    • มันเจาะช่องไว้ในไฟร์วอลล์ ufw โดยตั้งใจ
  • หากข้อมูลทั้งหมดที่ต้องปกป้องอยู่ในคอนเทนเนอร์ และ shell ภายในยังเชื่อมต่ออินเทอร์เน็ตได้ ขอบเขตการปกป้องก็จะไม่ชัดเจน
  • หากเป้าหมายคือป้องกันการลบ recursive ของ root filesystem ก็มีวิธีระดับระบบปฏิบัติการที่ตรงกว่า เช่น Landlock, Seatbelt, Restricted Tokens
  • ความปลอดภัยของ coding agent ไม่ควรเป็นเรื่องที่โยนความรับผิดชอบไปยังคอนเทนเนอร์แยก แต่ควรเป็นงานลำดับแรกของตัว harness เอง
    • การบล็อก Git ควรบล็อกตัว executable git โดยตรง ไม่ใช่สตริงคำสั่ง
    • ไดเรกทอรี .git ควรถูกทำให้เป็นแบบ read-only
    • แทนที่จะ sanitize คำสั่ง Bash เป็นข้อความ ควรใช้การแยกเชิง native ของระบบปฏิบัติการ

ประสบการณ์ใช้งาน local LLM

  • local model อย่าง Qwen3.6-27B ก็อาจทำลายเสถียรภาพและความสอดคล้องเชิงแนวคิดของ codebase ได้เหมือน frontier model แต่มีความต่างอยู่สามข้อ
    • มีความรู้สึก uncanny valley น้อยกว่าในแง่ที่ดูฉลาดแต่กลับทำอะไรโง่ๆ และเพราะขีดจำกัดชัดเจน จึงปรับวิธีโต้ตอบได้ง่ายกว่า
    • จำนวน weight มีน้อยเกินกว่าจะถ่ายทอดข้อมูลฝึกออกมาตรงๆ ได้ จึงทำให้การตัดสินใจเรื่องการปนเปื้อนของผลลัพธ์ต่างออกไป
    • ไม่จำเป็นต้องสนับสนุนหรือพึ่งพา cloud provider
  • ในงานค้นหาแบบอิงอินพุต ที่ให้โค้ด อาการ และสาเหตุที่คาดไว้ พร้อมให้อ่านโค้ดที่เกี่ยวข้อง แล้ว บังคับให้ส่งเส้นทางการเรียกและการอ้างอิงโค้ด ผู้เขียนได้ผลลัพธ์ที่มีประโยชน์
    • การจำกัดขอบเขตเป็นปัญหาการค้นหาช่วยลดแนวโน้มที่โมเดลจะกุเรื่องขึ้นมา
  • การสร้างโค้ดกลับทำลายแผนสถาปัตยกรรมซ้ำๆ
    • มันเลือกทางลัด เช่น ย้าย mutable state กลางทางของการออกแบบที่ตั้งใจให้หลายองค์ประกอบใช้ร่วมกัน
    • ปัญหาไม่ได้มีแค่ว่าไม่ได้เขียนเอง แต่ยังบั่นทอนความสามารถในการเข้าใจโค้ดด้วย
  • วิธีดึงคำตอบตรงจากความรู้ในน้ำหนักโมเดลนั้นก่อให้เกิด hallucination แม้ในโมเดลระดับหลายล้านล้านพารามิเตอร์
  • หาก LLM จะกลายเป็นเครื่องมือทั่วไปได้ ซอฟต์แวร์รอบข้างต้องได้รับ system engineering จริงจังเพื่อลบช่องโหว่ด้านความปลอดภัย และงานนั้นต้องเป็นหน้าที่ของมนุษย์

1 ความคิดเห็น

 
ความเห็นจาก Hacker News
  • ชื่อที่ดีกว่าสำหรับบทความนี้น่าจะเป็นประมาณว่า “ความขัดข้องเล็กน้อยที่ถ้าแก้ได้ OpenCode จะดีขึ้น”
    การที่ต้องอ่าน AGENTS.md ใหม่ทุกครั้ง หรือเกิด prompt cache miss เพราะวันที่เปลี่ยน เป็นเรื่องที่พอรับได้
    ปัญหาที่ การบีบอัดและการตัดกิ่ง ทำงานไม่ถูกต้องก็เคยเห็นใน Codex และ Claude เหมือนกัน และ system prompt เริ่มต้นก็มีไว้เพื่อความสม่ำเสมอ ถ้าไม่ชอบก็เปลี่ยนได้

    • ตอนนี้โค้ดเบสบวมเกินไปอย่างหนักเพราะฟีเจอร์ที่ถูกเพิ่มเข้ามาแบบ vibe coding และแสดงปัญหาเดียวกับ Claude Code
      ทั้ง เสถียรภาพ·ประสิทธิภาพ·การใช้หน่วยความจำ แย่ลงหมด และแม้เมื่อก่อนจะชอบ OpenCode แต่ก็มองว่าเป็นซอฟต์แวร์ที่เขียนมาไม่ค่อยดีนัก
      ตอนนี้เปลี่ยนไปใช้ Pi แทนทั้งหมดแล้ว และก็มีตัวเลือกใหม่ไม่น้อยที่เรียนรู้จาก OpenCode แล้วนำการออกแบบที่ยับยั้งชั่งใจมากกว่ามาใช้ในจุดที่จำเป็น
    • ผมทำงานอยู่ที่ OpenCode
      ตอนนี้เราไม่ทำ การตัดกิ่งการเรียกใช้เครื่องมือ แล้ว แต่การบีบอัดยังเป็นความจำเป็นที่เลี่ยงไม่ได้ไปอีกสักพัก เพราะถ้าจะทำงานเดิมต่อเนื่องนาน ๆ ภายใต้ context window ที่จำกัด ก็ต้องสรุปความคืบหน้าปัจจุบันไว้
      V2 ที่กำลังอยู่ในเบต้า มีวิธีใหม่ที่ทำให้ system instruction ที่เปลี่ยนแปลงได้ เช่น AGENTS.md หรือเทคโนโลยีที่ใช้งานได้ อัปเดตเป็นปัจจุบันอยู่เสมอ พร้อมกับหลีกเลี่ยง cache miss ให้มากที่สุด
      https://x.com/kitlangton/status/2075749116760457346/video/1
    • เนื้อหาเหล่านั้นถูกจัดอยู่ในหมวด “Annoying Things” ดังนั้นควรไปอ่าน “Alarming Things” ด้วย
    • สิ่งที่พูดถึงตอนนี้คือรายการในหมวด “Annoying Things” ของบทความ
      ยังมีหมวด “Alarming Things” แยกต่างหาก ซึ่งมีหัวข้อย่อยชื่อ “It’s Fucking Full of RCEs” และมีช่องโหว่การรันโค้ดระยะไกลอีกหลายจุด นอกเหนือจากปัญหาที่เกิดจากเรื่องที่เปิดเผยไว้ในหมวดก่อนหน้า
    • งั้นนี่เองที่ทำให้ OpenCode ลบคอมเมนต์ในโค้ดของผมแบบสุ่ม
  • เป็นการสรุปความเสี่ยงของ agentic CLI ได้ดี แต่ ชื่อที่โฟกัสเฉพาะ OpenCode ดูแปลกด้วยสองเหตุผล
    อย่างแรกคือไม่ได้เสนอทางเลือกที่ชัดเจน ปัญหาหลายอย่างเป็นปัญหาเชิงรากฐานจนแทบต้องออกแบบใหม่และเขียนใหม่ตั้งแต่ต้น ดังนั้นการเสนอแค่แนวทางแก้ OpenCode อาจไม่พออยู่แล้ว แต่บทความนี้ก็ไม่มีข้อเสนอเชิงสร้างสรรค์เลย จนดูเหมือนเป็นบทความที่บอกว่า “เลิกใช้ LLM ไปซะ”
    อย่างที่สองคือประเด็นหลักใน “Alarming Things” ไม่ได้เป็นปัญหาเฉพาะของ OpenCode แต่ใช้ได้กับ Claude CLI และน่าจะรวมถึงเอเจนต์ของผู้ให้บริการโมเดลชั้นนำรายอื่นด้วย
    ถึงอย่างนั้นก็ยังมีคุณค่ามากในฐานะบันทึกที่กระตุ้นให้สร้างเครื่องมือที่ดีกว่าตั้งแต่ต้น ผมเลยตั้งใจจะบุ๊กมาร์กและแชร์ต่อกว้าง ๆ แต่ยิ่งเนื้อหาดีเท่าไร ก็ยิ่งรู้สึกว่าชื่อและจุดโฟกัสตั้งไว้ผิดมากขึ้นเท่านั้น

    • ผมสงสัยว่าเขาคิดได้อย่างไรว่าจะอนุญาตให้เข้าถึง shell แต่ยัง ป้องกันการรันคำสั่งตามอำเภอใจ อย่างปลอดภัยได้
      โดยเฉพาะคำบ่นว่า echo git | bash ยังรันได้ ดูเหลวไหลมาก
  • ประโยคที่ว่า “ถ้าคุณยังไม่รู้จัก OpenCode ให้นึกภาพรองเท้าบู๊ตที่เหยียบย่ำใบหน้ามนุษย์ไปตลอดกาล รองเท้าบู๊ตนั้นทำจาก TypeScript และใบหน้าคือทุกสิ่งที่เราเรียนรู้เกี่ยวกับความปลอดภัยและซอฟต์แวร์ระบบนับตั้งแต่การประดิษฐ์คอมพิวเตอร์อิเล็กทรอนิกส์ในทศวรรษ 1940” น่าจะเข้าชิงรางวัล Bulwer-Lytton สาขา อุปมาอุปไมยที่ยัดเยียดเกินไป

    • อุปมานี้หยิบมาจากประโยคใน 1984 ของ George Orwell ที่ว่า “หากคุณอยากเห็นภาพอนาคต ก็ให้นึกถึงรองเท้าบู๊ตที่เหยียบย่ำใบหน้ามนุษย์ไปตลอดกาล”
  • สำนวนการเขียนของบทความเต็มไปด้วยความโกรธและความใจร้ายเกินไป
    โดยรวมแล้วผมเห็นด้วยกับหลายประเด็น แต่พอถึงช่วงที่เรียก OpenCode ว่า “กองขยะติดเทอร์โบในรถตัวตลกที่มีแนวทางด้านความปลอดภัยแบบ ‘พ่อครับ เดี๋ยวผมก้มให้’” แล้วบอกให้ทุกคนเลิกใช้ทั้งหมด ผมก็ไม่อยากอ่านต่อแล้ว
    ซอฟต์แวร์นี้ก็สร้างโดยคนธรรมดาเหมือนกัน ผมไม่รู้ว่าการ โจมตีโอเพนซอร์สแบบนี้ กลายเป็นเรื่องปกติตั้งแต่เมื่อไร และมันทำให้ผมนึกว่าถ้าซอฟต์แวร์ที่ผมสร้างโดนประเมินแบบนี้จะรู้สึกอย่างไร

    • ผมเห็นด้วยกับความรู้สึกนี้ แต่ก็ต้องบอกว่าวัฒนธรรมแบบนี้มีมาตั้งแต่ ยุค 1990 เป็นอย่างน้อย
      แม้แต่ใน comp.lang.lisp สมัยก่อน ก็มีคนที่ชอบเหยียดงานของคนที่เขียนโค้ดไม่ถึงมาตรฐานหอคอยงาช้าง บางคนก็หายไป บางคนก็หลงคิดว่าคำด่าแบบนั้นคือการฝึกฝนที่จำเป็นต่อการพัฒนาฝีมือและรับมันเหมือนเครื่องราชฯ
      กระทู้ HN เก่าที่เกี่ยวข้อง: https://news.ycombinator.com/item?id=587045
    • เดี๋ยวนี้แค่เรียกอะไรสักอย่างว่า “ถูก vibe coded มา” ก็เหมือนเป็นใบอนุญาตให้ปล่อยทั้งคำพูดเกินจริงและคำดูหมิ่น โดยตั้งสมมติฐานว่าไม่มีใครถูกโจมตี
      ดูเหมือนพวกเขาไม่เข้าใจเลยว่าถ้อยคำแบบนี้เป็นอันตรายแค่ไหน ทั้งต่อผู้พัฒนาที่โดนลูกหลง และต่อตัวผู้ใช้ถ้อยคำแบบนั้นเองที่ทำให้พฤติกรรมนี้กลายเป็นเรื่องปกติ
    • ประโยคที่ว่า “ถ้ามีใครสักคนที่รู้โครงสร้างภายในของ OpenCode ดี—ซึ่งผมจะสมมติว่าทีมพัฒนา OpenCode ไม่เข้าข่ายนี้—คงจะคัดค้านตัวอย่าง python3 ข้างบนไปแล้ว” ทำให้ผมหัวเราะ
    • ต่อให้คุณเคยมีส่วนร่วมกับ OpenCode ถ้ายังมีอารมณ์ขันอยู่ก็น่าจะขำได้ ดังนั้นไม่จำเป็นต้องจริงจังกับทุกอย่างขนาดนั้น
    • ถึงตอนนี้ก็ยังไม่ใช่ถ้อยคำที่ปกติอยู่ดี แต่ก็ไม่ใช่เรื่องใหม่ และภาษาลักษณะนี้มีมานานแล้ว
  • เพราะ tech stack ของลูกค้า ผมต้องใช้ Claude Code และใช้ OpenCode เวอร์ชันหนึ่งกับงานส่วนตัว ซึ่ง OpenCode ดีกว่ามาก เลยยิ่งรู้สึกเศร้ากับบทความนี้
    ความผิดปกติหลายอย่างที่ผมเห็นมาตลอดแต่ปล่อยผ่านไป ตอนนี้ตรงกับที่บทความเขียนไว้หมดและยังอธิบายสาเหตุได้ด้วย ถ้าตัดถ้อยคำเกินจริงและส่วนที่ผมไม่เห็นด้วยทางอารมณ์ออกไป โดยรวมแล้วก็ค่อนข้างถูก ผมคงต้องหา execution tool ตัวอื่นแล้ว
    อยากได้คำแนะนำว่า สถาปัตยกรรมของ Pi ดีกว่าจริงไหม หรือมีทางเลือกที่ดีกว่านี้ไหม

  • ไม่ว่าข้อบกพร่องจะเป็นอย่างไร จากการลองใช้หลายเครื่องมือแล้ว OpenCode ให้ productivity สูงสุด สำหรับผม
    สิ่งที่บทความพูดถึงส่วนใหญ่เป็นแค่ความน่ารำคาญเล็กน้อยหรือความเห็นที่ต่างกัน และโดยเฉพาะเรื่องการกรองคำสั่ง ผู้เขียนเข้าใจจุดประสงค์ผิดไปอย่างพื้นฐาน มันไม่ใช่มาตรการความปลอดภัย แต่เป็นกลไกเพื่อชี้นำพฤติกรรมของโมเดล
    ดูเหมือนผู้เขียนจะไม่เคยสร้างอะไรจริง ๆ ด้วย OpenCode และถ้าเคยใช้ ก็ไม่ได้พูดถึง คุณภาพของผลลัพธ์ ซึ่งเป็นเรื่องสำคัญที่สุดเลย

    • ผมก็รู้สึกว่า OpenCode มี สมดุลที่เหมาะสม ระหว่างการไม่เข้ามาขัดขวางกับการไม่ทำคอมพิวเตอร์พัง
      โดยเฉพาะสามารถใช้โหมดวางแผนได้ง่าย จนทำงานเสร็จได้อย่างรวดเร็ว
  • หลังเปลี่ยนจาก OpenCode ไปใช้ Pi แล้ว ประสิทธิภาพการเรียกใช้เครื่องมือดีขึ้นมาก และรู้สึกว่าบั๊กก็น้อยลงด้วย
    ดูเหมือนว่า OpenCode จะหายไปจาก https://openrouter.ai/apps/category/coding แล้วเช่นกัน

    • ฝั่ง OpenCode ขอให้นำออกจากอันดับของ OpenRouter: https://github.com/anomalyco/opencode/issues/11926#issuecomm...
    • นี่ไม่ใช่เพราะ OpenCode แย่ แต่เป็นเพราะ Pi ดีกว่า มากกว่า แม้จะเทียบ Claude กับ Pi ก็พูดแบบเดียวกันได้
    • หนึ่งในข้อดีของ OpenCode คือ การรวม LSP เลยสงสัยว่าใน Pi จัดการเรื่องนี้อย่างไร
    • ช่วงหลังได้ลองใช้ทั้ง OpenCode และ Pi แล้ว ในฐานะคนที่ย้ายมาจาก Claude Code ก็แปลกใจที่ทั้งคู่ดูเหมือนจะอนุญาตให้แก้ไขได้ตามค่าเริ่มต้นโดยไม่มีหน้าต่างยืนยัน
      เท่าที่จำได้ ตัวหนึ่งเปิดการยืนยันได้ในตั้งค่า และอีกตัวต้องใช้ปลั๊กอิน
    • พอเห็นว่ามัน ดาวน์โหลดแพ็กเกจ npm อยู่เบื้องหลังโดยไม่ถามผู้ใช้ ก็ลบ OpenCode ออกไปเลย
      พฤติกรรมนี้ยิ่งเพิ่มความเสี่ยงจากการโจมตีแบบ supply chain
  • มันไร้สาระที่ แอปเดสก์ท็อปแบบ TUI ซึ่งแค่แสดงข้อความ กลับหนักกว่าแอปเนทีฟและแม้กระทั่งแอปเดสก์ท็อปบนเบราว์เซอร์ส่วนใหญ่ แถมยังเปลือง RAM, CPU, พลังงาน และแบตเตอรี่
    ตอนนี้กำลังพัฒนาเครื่องมือรัน AI พร้อมแอปแชตของตัวเองด้วย C++ Qt6 ซึ่งมีทั้งเอเจนต์ย่อย, ความต่างของโค้ด, เทอร์มินัลอีมูเลเตอร์, เอดิเตอร์แบบง่าย, พรีวิว Markdown, พื้นหลังโปร่งแสง, ธีมผู้ใช้, สิทธิ์, MCP, การรวม Git, ระบบ dock และแท็บโปรเจ็กต์ แต่ก็ยังเบากว่าเครื่องมืออื่น
    ยังไม่ได้เปิดเผยเพราะกำลังเก็บบั๊กบางส่วนและทำ UI ให้เรียบง่ายขึ้นพร้อมขัดเกลาอยู่: https://zeteo.krysoph.com/preview.html

  • เพิ่งรู้ตอนนี้ว่าเหตุผลที่ OpenCode ลบคอมเมนต์ออก เป็นเพราะ system prompt เริ่มต้นมีคำว่า “Use ABSOLUTELY NO COMMENTS” ซึ่งน่าหงุดหงิดมาก
    อย่างไรก็ตาม ความเสี่ยงด้านความปลอดภัยไม่ใช่แค่ความไม่สะดวกเล็กน้อย แต่ใช้ได้กับเครื่องมือรันตัวอื่นด้วย เครื่องมือเหล่านี้เข้าถึงข้อมูลจำนวนมหาศาล อัปเดตแทบทุกวัน และด้วยธรรมชาติแบบ vibe coding ก็น่าจะไม่มีใครตรวจสอบ dependency ของ npm จำนวนมาก ที่ถูกดึงเข้ามาอย่างจริงจัง
    แค่เกิดเหตุแบบ left-pad ขึ้นเพียงครั้งเดียว ก็อาจกลายเป็นหายนะต่อ supply chain ทั้งหมดได้

  • การใส่วันที่ไว้ใน system prompt จนทำให้แคชถูกทำให้ใช้ไม่ได้ตอนเที่ยงคืนเป็นการตัดสินใจที่ สมเหตุสมผล และเครื่องมือรันตัวอื่นส่วนใหญ่ก็ใช้วิธีเดียวกัน
    ถ้าใส่ทั้งวันที่และเวลาครบถ้วนก็คงจะไร้ความรับผิดชอบ แต่ OpenCode ไม่ได้ทำแบบนั้น

    • แต่ตอนที่ใช้งานตอนเที่ยงคืนแล้วต้องรอ 10 นาทีเพื่อเติม KV cache ของ GPU ในเครื่องใหม่ มันไม่ได้รู้สึกว่าสมเหตุสมผลเลย
      แก้ได้ง่าย ๆ โดยประเมินวันที่แค่ครั้งเดียวต่อเซสชัน หรืออย่างมากก็ครั้งเดียวทุกครั้งที่รันไบนารี opencode เพื่อไม่ให้เซสชันที่เปิดนานค้างอยู่กับวันที่เก่า