MCP Fetch 2026.10.10: URL แรกผ่านแล้ว ทำไมต้องตรวจทุก Redirect?

วิศวกรกับผู้ช่วย AI ตรวจเส้นทาง URL สาธารณะที่ redirect ไปยังปลายทางภายใน โดยเส้นทางหยุดก่อนส่งคำขอ
วิศวกรกับผู้ช่วย AI ตรวจเส้นทาง URL สาธารณะที่ redirect ไปยังปลายทางภายใน โดยเส้นทางหยุดก่อนส่งคำขอ
ภาพอธิบายแนวคิดที่สร้างด้วย AI: URL แรกเป็น public ไม่ได้ยืนยันปลายทางถัดไป ต้องตรวจปลายทางก่อนส่งคำขอแต่ละครั้ง ข้อเท็จจริงอ้างอิงโค้ด MCP Fetch รุ่น 2026.10.10 ภาพเป็น simulation ไม่ใช่ผลทดสอบความปลอดภัย ต้นทาง · ภาพเต็ม

AGENT ENGINEERING · MCP / API SECURITY · ตรวจต้นทาง 14 ตุลาคม 2026

Agent อ่าน URL สาธารณะที่ดูปกติ แต่เว็บตอบว่า “เอกสารย้ายไปที่นี่” เครื่องมือเดินตามต่อ คำถามคือ ใครตรวจที่อยู่ใหม่ก่อนเครื่องที่รัน Agent ส่งคำขอ? การตรวจเฉพาะ URL แรกยังตอบไม่ได้

Quick Answer: ตรวจปลายทางก่อนทุกคำขอ รวมทุก Redirect Hop

mcp-server-fetch 2026.10.10 เพิ่มการปฏิเสธปลายทางที่ไม่เป็นที่อยู่สาธารณะโดยค่าเริ่มต้น กลไกตรวจชื่อโฮสต์ก่อนส่งแต่ละคำขอ ครอบคลุมการเปลี่ยนเส้นทางด้วย ทักษะของบทเรียนนี้คือออกแบบลำดับ “ตรวจ → ตัดสิน → จึงอนุญาตให้ส่ง” และตรวจหลักฐานว่าปลายทางที่ถูกปฏิเสธไม่เข้าสู่รายการคำขอที่อนุญาต ไม่ใช่เพียงเห็นข้อความ error แล้วสรุปว่าไม่มีการเชื่อมต่อเกิดขึ้น PR 5033

การแก้รุ่นนี้ยังมีขอบเขต: การเปลี่ยนคำตอบ DNS ระหว่างตรวจและเชื่อมต่อ รวมถึงชื่อที่เครื่องเซิร์ฟเวอร์แก้ที่อยู่ไม่ได้แต่ proxy แก้ได้ ยังต้องพิจารณาแยกกัน บทความมีตัวอย่าง MOCK ที่ไม่ใช้เครือข่าย และชุดข้อทดสอบที่เขียนไว้แต่ NOT RUN จึงไม่ใช่ผลรับรองความปลอดภัยของระบบจริง

ข่าวใหม่อยู่ตรงไหน และวันที่ใดหมายถึงอะไร

หมายเลข 2026.10.10 คือรุ่นแพ็กเกจ ส่วนไฟล์ wheel ถูกอัปโหลดจริงวันที่ 11 ตุลาคม 2026 เวลา 02:41:50 UTC ตาม metadata ของ PyPI การแก้เรื่องปลายทางรวมเข้า repository เมื่อ 5 ตุลาคม จึงควรแยกวันที่แก้โค้ด วันที่ปล่อยไฟล์ และวันที่เราอ่านหลักฐาน ไม่เรียกทุกอย่างว่า “เปิดตัววันที่ 10” ตามเลขรุ่น PyPI release metadata

ปัญหา: สิทธิ์ของเครื่องมือเกิดที่เครื่องเซิร์ฟเวอร์

SSRF หรือ Server-Side Request Forgery คือการทำให้ระบบฝั่งเซิร์ฟเวอร์ส่งคำขอไปยังปลายทางที่ผู้สร้างระบบไม่ได้ตั้งใจเปิดให้เข้าถึง ในบริบท Agent ผู้ใช้หรือข้อความที่โมเดลอ่านอาจเสนอ URL แต่ผู้ส่งคำขอจริงคือ process ที่รัน Fetch Server ถ้า process อยู่ในเครือข่ายที่มองเห็นบริการภายในได้ การอ่าน URL ก็มีผลด้านสิทธิ์ แม้เครื่องมือไม่ได้มีปุ่มลบข้อมูล

Redirect คือคำตอบจากปลายทางที่บอกให้ไปอ่านอีก URL หนึ่ง ส่วน hop คือหนึ่งช่วงของการเดินทาง ตัวอย่างสมมติ A → B → C มีสามปลายทางที่อาจถูกขอข้อมูล A ดูถูกต้องไม่ได้ทำให้ B และ C ถูกต้องตามไปด้วย เราจึงสนใจเส้นทางทั้งหมดและจุดที่คำขอจะถูกส่ง มากกว่าตรวจว่าตัวอักษรของ URL แรกมีชื่อแบรนด์ที่คุ้นตาหรือไม่

เทียบกับ LLM chat ที่คุณวางเอกสารให้สรุป เมื่อเพิ่มเครื่องมือ Agent จะเลือก tool สร้าง arguments รับข้อมูลและตัดสินใจต่อ การสั่งใน prompt ว่า “อย่าเข้าระบบภายใน” ไม่ได้แทนการตรวจของผู้ส่งคำขอ

ผลการเรียนรู้ที่ตรวจได้หลังอ่านคือ คุณอธิบายได้ว่า URL ใดต้องถูกตรวจซ้ำ วางเงื่อนไขหยุดเมื่อคำตอบที่อยู่มีรายการที่ไม่อนุญาต และเขียน acceptance criterion ที่ตรวจรายการคำขอ ไม่พึ่งเพียงคำรายงานของ Agent

แผนภาพตรวจทุกปลายทางก่อนส่งคำขอ ตั้งแต่ URL แรก การเปลี่ยนเส้นทาง และหยุดก่อนปลายทาง non-public
อินโฟกราฟฟิกที่สร้างด้วย AI จากโค้ดต้นทาง: guard ตรวจ URL ก่อนคำขอ robots.txt และแต่ละ redirect hop; ตัวอย่างปลายทางภายในถูกปฏิเสธก่อนเชื่อมต่อ เป็นแผนภาพจำลอง ไม่ได้ส่งคำขอหรือทดสอบเครือข่ายจริง ต้นทาง · ภาพเต็ม

สถาปัตยกรรม: แยกการอนุญาตงานกับการตรวจปลายทาง

กรอบที่เราออกแบบสำหรับบทเรียนมีสี่ส่วน เริ่มจาก Task Policy กำหนดงานและโฮสต์ที่ผู้ใช้อนุญาต ต่อด้วย Destination Guard ตรวจ URL และคำตอบที่อยู่ ส่วน Transport เป็นผู้เชื่อมต่อจริง และ Evidence Ledger เก็บการตัดสินใจและคำขอที่ส่ง หรือคำขอที่แบบจำลองจะอนุญาต บทบาทเหล่านี้อาจอยู่ใน process เดียว แต่ไม่ควรปะปนความรับผิดชอบ

คำสั่ง → ตรวจขอบเขตงาน → URL / host → ตรวจที่อยู่ทุกคำตอบ
                                  ├─ ไม่อนุญาต → STOP + เหตุผล
                                  └─ อนุญาต → ส่งคำขอ → ผลตอบกลับ
                                                     ├─ จบ → ส่งข้อมูล
                                                     └─ redirect → วนตรวจปลายทางใหม่

ที่อยู่สาธารณะไม่เท่ากับได้รับสิทธิ์ตามงาน หากผู้ใช้ขออ่านคู่มือจากสองโฮสต์ เครื่องมือไม่ควรถือว่าบริการสาธารณะอีกแห่งอยู่ในขอบเขตเพียงเพราะ IP ผ่านตัวตรวจ การตรวจชนิดที่อยู่ตอบว่า “เครือข่ายนี้อยู่ในกลุ่มที่ต้องปิดกั้นหรือไม่” ส่วนการตรวจสิทธิ์ตอบว่า “งานนี้อนุญาตไปที่นั่นหรือไม่” นี่เป็นการแยกหน้าที่ที่เสนอในบทความ ไม่ใช่การกล่าวว่า Fetch รุ่นนี้สร้าง allowlist ขององค์กรให้เอง

สิ่งที่ Source Code รุ่นนี้ทำจริง

Asynchronous request hook ของ HTTPX ตรวจ addresses ก่อนหน้าเว็บและ robots.txt รวม tool/prompt เมื่อรายการใดไม่สาธารณะจะปฏิเสธทั้งคำขอ มีการคลี่ IPv4-mapped IPv6 และช่วง special-purpose พร้อมข้อยกเว้น server.py ที่ tag v1.0.0

ชื่อที่ resolve ได้ทั้ง public และ private ต้องพิจารณาทุกคำตอบที่ connector อาจเลือก ไม่เลือกเฉพาะรายการที่ดูปลอดภัยมาเป็นหลักฐาน

Worked Example: เอกสารสาธารณะที่ชี้ต่อไปยัง Metadata

สมมติทีมมี Agent อ่านคู่มือจาก docs.example โดยอนุญาตปลายทางประกอบที่ cdn.example ผู้ใช้สั่ง “อ่านคู่มือและสรุปวิธีตั้งค่าหนึ่งหน้า ห้ามอ่านบริการภายใน” แผนควรเริ่มจากตรวจขอบเขต เลือก Fetch รับเนื้อหาเป็นข้อมูล แล้วส่งคำสรุปพร้อมแหล่งที่มา การเปลี่ยนเส้นทางที่เกิดขณะอ่านต้องผ่านตัวตรวจเดิมทุกครั้ง

กรณีจำลอง A → B ที่ทุก address ผ่านจะมี WOULD_REQUEST สองรายการ ส่วน A → metadata.example ซึ่ง fixture กำหนด IP 169.254.169.254 ต้องหยุดก่อนเพิ่มปลายทางลง ledger เราอนุญาตชื่อ metadata ใน fixture เพียงเพื่อแสดงว่าชั้นตรวจ address ยังปฏิเสธ ไม่ได้แนะนำอนุญาตบริการจริง

ชื่อ .example และการจับคู่ IP ทั้งหมดเป็นข้อมูลสมมติในหน่วยความจำ ไม่มี DNS lookup ไม่มี HTTP ไม่มีการอ่าน metadata จริง คำว่า WOULD_REQUEST แปลว่า “แบบจำลองจะอนุญาตให้ส่ง” ไม่ใช่ log ว่าได้ส่งแล้ว การตรวจรับจึงต้องอ่านทั้ง decision ของปลายทางที่ถูกปฏิเสธและ ledger ของคำขอที่อนุญาต

กรณีสมมติการตัดสินที่คาดหมายหลักฐานที่ต้องตรวจ
Public → Public และอยู่ในขอบเขตCOMPLETEledger มีสอง URL ตามลำดับ
Public → Link-localBLOCKEDledger ไม่มี URL ที่ถูกปฏิเสธ
ชื่อเดียวมี Public + PrivateBLOCKEDไม่มีรายการขอข้อมูลของชื่อนั้น
Public แต่ไม่อยู่ในสิทธิ์งานHOST_NOT_AUTHORIZEDหยุดก่อนตรวจ fixture และก่อนอนุญาตคำขอ
Redirect วนจนถึงเพดานREDIRECT_LIMITจำนวนการเดินต่อไม่เกินค่าที่ตั้ง
เปรียบเทียบผล DNS ที่เซิร์ฟเวอร์ resolve ได้เป็น public ทั้งชุด กับชุดผสมที่มี non-public ซึ่ง guard ปฏิเสธคำขอ
อินโฟกราฟฟิกที่สร้างด้วย AI จากโค้ด MCP Fetch: ทุก address ที่เซิร์ฟเวอร์ resolve ได้ต้องเป็น public; พบ non-public แม้หนึ่งรายการก็ปฏิเสธ ส่วน –allow-private-ips เป็นการตั้งค่าที่โฮสต์ซึ่งปิด guard นี้ ไม่ใช่อาร์กิวเมนต์ให้โมเดลเลือก ภาพเป็น simulation ไม่ใช่ผลทดสอบความปลอดภัย ต้นทาง · ภาพเต็ม

Python Example: ทำให้หลักฐานอยู่หลังตัวตรวจ

ไฟล์ประกอบใช้ Python 3.12+ และ Standard Library เท่านั้น ไม่มี dependency ที่ต้องติดตั้ง ไม่ต้องมี environment variable หรือ credential Input คือ URL เริ่มต้น ตาราง fixture รายชื่อโฮสต์ที่อนุญาต และจำนวน redirect สูงสุด ตัวอย่างหลักกำหนดเพดานสามครั้งเป็นค่าของบทเรียน ไม่ใช่ค่า default ที่เรารับรองของ Fetch Server

checked_host() ตรวจรูปแบบ URL และข้อจำกัดของตัวอย่าง public_fixture_address() จัดกลุ่ม IP ส่วน trace_policy() เดินทีละปลายทางและคืนผลพร้อม ledger การเพิ่ม ledger อยู่หลังการตรวจ URL สิทธิ์ และทุก address หากเงื่อนไขใดไม่ผ่านจะคืนผล BLOCKED ทันที ทำให้ assertions เขียนได้ตรงคำสัญญา

# ส่วนย่อจาก MOCK: ไม่ใช่การส่ง HTTP
if host not in authorized_hosts:
    return finish("BLOCKED", "HOST_NOT_AUTHORIZED")
if fixture is None or not fixture.addresses:
    return finish("BLOCKED", "UNRESOLVED_FIXTURE")
if any(not public_fixture_address(ip) for ip in fixture.addresses):
    return finish("BLOCKED", "NONPUBLIC_OR_INVALID_ADDRESS")
ledger.append({"url": url, "action": "WOULD_REQUEST"})

โค้ดเต็มและ README อยู่ด้านล่าง ผู้อ่านเลือกใช้ python fetch_policy_trace.py และ python -m unittest -v test_fetch_policy_trace.py โดยไม่ต้อง pip install Expected Output กรณีหลักคือ BLOCKED, reason NONPUBLIC_OR_INVALID_ADDRESS และ ledger มี URL แรกเท่านั้น เราไม่ได้รัน ผลคือ NOT RUN

MOCK เข้มกว่าต้นทาง: fixture ไม่ resolve จะหยุด จำกัด host/port/URL และปิด special-purpose exceptions แบบอนุรักษนิยม รายการช่วงที่อยู่ไม่ใช่ทะเบียน IANA สมบูรณ์ ห้ามใช้แทน transport security หรือถือว่าตรง upstream ทุกกรณี

code/fetch_policy_trace.py · NOT RUN
"""MOCK policy trace. No DNS, sockets, HTTP, MCP client, LLM, or file writes.

Authored for Python 3.12+. NOT RUN by Hybrid Mind.
This intentionally conservative teaching policy is NOT the upstream guard.
"""
from __future__ import annotations

import ipaddress
import json
from dataclasses import dataclass
from urllib.parse import urljoin, urlsplit


@dataclass(frozen=True)
class Fixture:
    addresses: tuple[str, ...]
    location: str | None = None


# A deliberately conservative fixture policy: special-purpose exceptions which
# upstream permits are still blocked here. Do not use this list as a production
# address registry; use reviewed, maintained controls in the actual transport.
DENY_RANGES = tuple(ipaddress.ip_network(value) for value in (
    "0.0.0.0/8", "10.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8",
    "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.2.0/24",
    "192.88.99.0/24", "192.168.0.0/16", "198.18.0.0/15",
    "198.51.100.0/24", "203.0.113.0/24", "224.0.0.0/4", "240.0.0.0/4",
    "::/128", "::1/128", "64:ff9b:1::/48", "100::/64", "2001::/23",
    "2001:db8::/32", "2002::/16", "fc00::/7", "fe80::/10", "ff00::/8",
))


def checked_host(url: str) -> str:
    if not isinstance(url, str) or not url or len(url) > 4096:
        raise ValueError("INVALID_URL")
    if any(ord(char) <= 32 or ord(char) == 127 for char in url):
        raise ValueError("INVALID_URL")
    try:
        parts = urlsplit(url)
        host = parts.hostname
        port = parts.port  # Accessing .port also validates malformed ports.
    except ValueError as exc:
        raise ValueError("INVALID_URL") from exc
    if parts.scheme not in {"https", "http"}:
        raise ValueError("UNSUPPORTED_SCHEME")
    if parts.username is not None or parts.password is not None:
        raise ValueError("USERINFO_NOT_ALLOWED")
    if not host or "%" in host or "\\" in url or parts.fragment:
        raise ValueError("INVALID_URL")
    if not host.isascii():
        raise ValueError("ASCII_HOST_REQUIRED_IN_MOCK")
    if port is not None and port != (443 if parts.scheme == "https" else 80):
        raise ValueError("PORT_NOT_ALLOWED_IN_MOCK")
    return host.lower().rstrip(".")


def public_fixture_address(value: str) -> bool:
    try:
        address = ipaddress.ip_address(value)
    except ValueError:
        return False
    if isinstance(address, ipaddress.IPv6Address) and address.ipv4_mapped:
        address = address.ipv4_mapped
    if not address.is_global or address.is_multicast:
        return False
    return not any(address.version == net.version and address in net
                   for net in DENY_RANGES)


def trace_policy(initial_url: str, fixtures: dict[str, Fixture],
                 authorized_hosts: frozenset[str], max_redirects: int = 3) -> dict:
    """Return a synthetic trace; request_ledger means WOULD_REQUEST, not a send.

    Empty or unknown DNS fixtures fail closed here. Upstream's unresolved-host
    behavior differs: it leaves resolution to the transport/proxy.
    """
    if isinstance(max_redirects, bool) or not isinstance(max_redirects, int):
        raise ValueError("max_redirects must be an integer")
    if not 0 <= max_redirects <= 10:
        raise ValueError("max_redirects must be between 0 and 10")
    url = initial_url
    redirects = 0
    decisions: list[dict] = []
    ledger: list[dict] = []

    def finish(status: str, reason: str) -> dict:
        return {"mode": "MOCK", "status": status, "reason": reason,
                "redirects_followed": redirects,
                "request_ledger": ledger, "decisions": decisions}

    while True:
        try:
            host = checked_host(url)
        except ValueError as exc:
            decisions.append({"url": url, "decision": "BLOCK",
                              "reason": str(exc)})
            return finish("BLOCKED", str(exc))
        if host not in authorized_hosts:
            decisions.append({"url": url, "host": host,
                              "decision": "BLOCK", "reason": "HOST_NOT_AUTHORIZED"})
            return finish("BLOCKED", "HOST_NOT_AUTHORIZED")
        fixture = fixtures.get(url)
        if fixture is None or not fixture.addresses:
            decisions.append({"url": url, "host": host,
                              "decision": "BLOCK", "reason": "UNRESOLVED_FIXTURE"})
            return finish("BLOCKED", "UNRESOLVED_FIXTURE")
        refused = [address for address in fixture.addresses
                   if not public_fixture_address(address)]
        if refused:
            decisions.append({"url": url, "host": host, "decision": "BLOCK",
                              "reason": "NONPUBLIC_OR_INVALID_ADDRESS",
                              "refused_addresses": refused})
            return finish("BLOCKED", "NONPUBLIC_OR_INVALID_ADDRESS")
        decisions.append({"url": url, "host": host, "decision": "ALLOW",
                          "addresses": list(fixture.addresses)})
        # This line is deliberately after host, address, and URL validation.
        # Nothing here sends a request. It records only the modeled next action.
        ledger.append({"url": url, "action": "WOULD_REQUEST"})
        if fixture.location is None:
            return finish("COMPLETE", "END_OF_FIXTURE")
        if redirects >= max_redirects:
            return finish("BLOCKED", "REDIRECT_LIMIT")
        url = urljoin(url, fixture.location)
        redirects += 1


FIXTURES = {
    "https://docs.example/start": Fixture(("8.8.8.8",), "https://cdn.example/page"),
    "https://cdn.example/page": Fixture(("1.1.1.1",)),
    "https://docs.example/to-internal": Fixture(("8.8.8.8",), "http://metadata.example/info"),
    "http://metadata.example/info": Fixture(("169.254.169.254",)),
    "https://docs.example/mixed": Fixture(("8.8.8.8", "10.0.0.8")),
    "https://docs.example/loop": Fixture(("8.8.8.8",), "/loop"),
    "https://docs.example/unresolved": Fixture(()),
}
AUTHORIZED_HOSTS = frozenset({"docs.example", "cdn.example", "metadata.example"})


if __name__ == "__main__":
    print(json.dumps(trace_policy("https://docs.example/to-internal", FIXTURES,
                                  AUTHORIZED_HOSTS), ensure_ascii=False, indent=2))
code/test_fetch_policy_trace.py · NOT RUN
"""Authored synthetic assertions, NOT RUN by Hybrid Mind."""
import unittest
from fetch_policy_trace import AUTHORIZED_HOSTS, FIXTURES, Fixture, trace_policy


class PolicyTraceTests(unittest.TestCase):
    def test_public_redirect_has_two_modeled_requests(self):
        result = trace_policy("https://docs.example/start", FIXTURES, AUTHORIZED_HOSTS)
        self.assertEqual(result["status"], "COMPLETE")
        self.assertEqual(len(result["request_ledger"]), 2)

    def test_private_redirect_is_not_in_request_ledger(self):
        result = trace_policy("https://docs.example/to-internal", FIXTURES, AUTHORIZED_HOSTS)
        self.assertEqual(result["status"], "BLOCKED")
        self.assertEqual(result["reason"], "NONPUBLIC_OR_INVALID_ADDRESS")
        self.assertEqual([row["url"] for row in result["request_ledger"]],
                         ["https://docs.example/to-internal"])

    def test_one_private_answer_blocks_mixed_set(self):
        result = trace_policy("https://docs.example/mixed", FIXTURES, AUTHORIZED_HOSTS)
        self.assertEqual(result["status"], "BLOCKED")
        self.assertEqual(result["request_ledger"], [])

    def test_public_host_still_needs_task_authorization(self):
        result = trace_policy("https://cdn.example/page", FIXTURES,
                              frozenset({"docs.example"}))
        self.assertEqual(result["reason"], "HOST_NOT_AUTHORIZED")
        self.assertEqual(result["request_ledger"], [])

    def test_unresolved_mock_fails_closed(self):
        result = trace_policy("https://docs.example/unresolved", FIXTURES, AUTHORIZED_HOSTS)
        self.assertEqual(result["reason"], "UNRESOLVED_FIXTURE")
        self.assertEqual(result["request_ledger"], [])

    def test_redirect_limit_bounds_the_trace(self):
        result = trace_policy("https://docs.example/loop", FIXTURES,
                              AUTHORIZED_HOSTS, max_redirects=2)
        self.assertEqual(result["reason"], "REDIRECT_LIMIT")
        self.assertEqual(result["redirects_followed"], 2)
        self.assertEqual(len(result["request_ledger"]), 3)

    def test_invalid_url_classes_never_reach_ledger(self):
        for value in ("file:///etc/passwd", "https://user:password@docs.example/a",
                      "https://docs.example:bad/a", "https://docs.example/a\n",
                      "https://docs.example:8443/a"):
            with self.subTest(value=value):
                result = trace_policy(value, FIXTURES, AUTHORIZED_HOSTS)
                self.assertEqual(result["status"], "BLOCKED")
                self.assertEqual(result["request_ledger"], [])

    def test_ipv4_mapped_loopback_is_blocked(self):
        url = "https://docs.example/mapped"
        result = trace_policy(url, {url: Fixture(("::ffff:127.0.0.1",))}, AUTHORIZED_HOSTS)
        self.assertEqual(result["request_ledger"], [])
        self.assertEqual(result["status"], "BLOCKED")


if __name__ == "__main__":
    unittest.main()
code/README.md · NOT RUN
# MCP Fetch redirect policy trace — MOCK

Testing status: **NOT RUN**. Hybrid Mind has authored and read the code as text; no Python process, imports, compile step, tests, DNS, HTTP, MCP tool call, or upstream package installation was executed.

## Runtime / dependencies / configuration

Python **3.12+**. Standard library only: `ipaddress`, `json`, `dataclasses`, `urllib.parse`, `unittest`. No requirements installation, external SDK, environment variables, credentials, model provider, GPU, paid API, or network access is required. The companion `requirements.txt` is intentionally comment-only.

## Installation and running (instructions for the reader)

Save the two Python files in the same directory. No `pip install` step is needed. With a separately installed Python 3.12+ runtime, the reader can choose to run:

```text
python fetch_policy_trace.py
python -m unittest -v test_fetch_policy_trace.py
```

Those commands are supplied as instructions, not a claim that the publisher ran them.

## Input / expected output

Input is `initial_url`, an in-memory dictionary of `Fixture(addresses, location)` values, an explicit set of authorized hosts, and `max_redirects` (default 3; bounded 0–10). `.example` hostnames and the fixture IPs are synthetic associations: they are not resolved and do not describe the current DNS of any real site.

The default demonstration models a public fixture redirecting to a link-local metadata fixture. Expected output is `mode=MOCK`, `status=BLOCKED`, `reason=NONPUBLIC_OR_INVALID_ADDRESS`, `redirects_followed=1`; `request_ledger` contains only `https://docs.example/to-internal` with `action=WOULD_REQUEST`. The metadata URL appears only in the blocked decision. No actual request occurred, including to the first URL.

The eight authored synthetic test methods cover public-to-public, private redirect absent from ledger, mixed public/private answers, unauthorized public host, unresolved fixture, redirect budget, malformed URL classes, and mapped IPv6 loopback. They are **NOT RUN**, so there is no actual pass count or coverage measurement.

## Permission / cost

This example has no tools that write to external systems, no network capability, no secrets, and no model selection. `request_ledger` is a returned list in memory; it is not a network trace. A reader running it uses only local CPU/RAM; there is no provider charge in the authored design. Runtime latency and memory usage were not measured.

## Intentional differences from mcp-server-fetch 2026.10.10

- This is a teaching policy, not the upstream implementation or a security library.
- It fails closed when a DNS fixture is empty or missing. Upstream leaves locally unresolvable names to its transport/proxy.
- It uses a reviewed host set and restricts ports, userinfo, fragments, and ASCII hosts for simplicity. These are application choices, not upstream defaults.
- Its conservative range list blocks special-purpose exceptions that upstream permits. It is not an authoritative replacement for current IANA classification.
- It never resolves or pins an address, so it cannot exercise DNS rebinding, proxy routing, HTTP redirects, robots.txt, parser compatibility, TLS, network egress, prompt injection, or real SSRF prevention.

For real integration, use the pinned current server, inspect `tools/list`, review network egress and transport/proxy controls, and test permitted sandbox scenarios separately. Do not infer production readiness from the authored fixture tests.
code/requirements.txt · NOT RUN
# Python 3.12+ standard library only. No third-party dependencies to install.

เชื่อม MCP จริงอย่างไร โดยแยกจาก MOCK

MCP คือข้อตกลงให้ client ค้นพบและเรียกเครื่องมือที่ server เปิดให้ใช้ ก่อนเรียกจริงให้อ่าน tools/list ของ instance นั้นและตรวจรุ่นที่ติดตั้ง ตัวอย่างข้อความต่อไปนี้เป็นรูปแบบ tools/call สำหรับ Fetch ตาม schema ที่อ่านจาก source รุ่นนี้ เป็นแนวทาง Live Integration ที่ NOT RUN ไม่มีคำขอจริงจากบทความ

{
  "jsonrpc": "2.0",
  "id": "fetch-docs-001",
  "method": "tools/call",
  "params": {
    "name": "fetch",
    "arguments": {
      "url": "https://example.com/",
      "max_length": 5000,
      "start_index": 0,
      "raw": false
    }
  }
}

Schema มี URL ที่จำเป็น และตัวเลือกความยาว จุดเริ่ม กับ raw โดย max_length ใช้หน่วยอักขระในผลส่งกลับ ไม่ใช่จำนวน token หรือข้อรับรองขนาดข้อมูลที่ดาวน์โหลด การกำหนด 5,000 จึงไม่ใช่เพดานเครือข่าย ใน source กำหนดช่วงจำนวนเต็ม 1–999999 และ start_index ไม่ติดลบ ให้แยก policy จำกัด response/เวลา/จำนวนคำขอของระบบคุณออกจากตัวเลือกตัดข้อความนี้

README ระบุการพึ่ง MCP Python SDK 1.x และเตือนการเปลี่ยน API ใน SDK 2.0 ผู้ใช้ระบบจริงควรตรึงรุ่น ตรวจ transport ที่ client รองรับ และทบทวน proxy configuration ก่อนเชื่อมต่อ ข้อความประกอบเครื่องมือแบบ read-only เป็นคำบอกลักษณะการทำงาน ไม่ใช่การพิสูจน์ว่าทุกเว็บที่อ่านไม่มีความเสี่ยง Fetch README

ข้อจำกัดที่ยังต้องออกแบบต่อ

DNS คือระบบแปลงชื่อเป็นที่อยู่ ส่วน DNS rebinding ในประเด็นนี้คือคำตอบเปลี่ยนระหว่างเวลาที่ guard ตรวจและเวลาที่ transport เชื่อมต่อ เอกสาร PR ระบุว่า hook กับการเชื่อมต่อ resolve แยกกัน จึงยังมีหน้าต่าง TOCTOU หรือช่องว่างระหว่างตรวจเงื่อนไขกับใช้จริง การตรวจทุก redirect เป็นชั้นหนึ่ง แต่ไม่ปิดช่องว่างนี้เอง ขอบเขตที่ PR ระบุ

ข้อวิเคราะห์สำหรับระบบจริงคือพิจารณา connector/resolver หรือ network egress ที่ควบคุมปลายทาง ณ จุดเชื่อมต่อ พร้อมตรวจ TLS และ proxy ใน sandbox ที่ได้รับอนุญาต เราไม่ได้ติดตั้งหรือพิสูจน์มาตรการเหล่านี้

ชื่อที่เซิร์ฟเวอร์ resolve ไม่ได้จะถูกส่งต่อให้ transport/proxy จัดการ การไม่พบ IP ที่ห้ามจึงไม่เท่ากับตรวจผ่าน องค์กรต้องกำหนดว่าจะหยุดเมื่อไม่ทราบ หรือให้ proxy ที่ควบคุมตรวจปลายทาง พร้อมหลักฐานของจุดตรวจ

Flag --allow-private-ips เป็นการตั้งค่าฝั่งผู้รัน server ที่ปิด guard นี้ ไม่ใช่ argument ที่โมเดลส่งมาเปิดได้ การมี intranet ที่จำเป็นควรใช้ server หรือเครือข่ายที่จำกัดขอบเขตเฉพาะ พร้อมผู้รับผิดชอบ การเปิด flag กว้างเพื่อแก้ error ของงานอ่านเว็บทั่วไปทำให้คุณข้ามการควบคุมที่กำลังศึกษา

ช่องว่างเวลาระหว่างตรวจ DNS กับเชื่อมต่อที่ยังมีความเสี่ยง DNS rebinding พร้อมข้อจำกัดกรณี proxy และข้อเสนอ network policy
อินโฟกราฟฟิกที่สร้างด้วย AI อธิบายข้อจำกัดจากโค้ดและเอกสาร: คำตอบ DNS อาจเปลี่ยนระหว่างการตรวจกับการเชื่อมต่อ และกรณี resolve เฉพาะ proxy ยังต้องตรวจตามสภาพแวดล้อมจริง การเพิ่ม network policy เป็นข้อเสนอทางวิศวกรรม ภาพเป็น simulation ไม่ใช่ผลวัดหรือคำรับรองความปลอดภัย ต้นทาง · ภาพเต็ม

Failure Modes, Logs และวิธีตรวจรับ

แยกความล้มเหลวอย่างน้อยสามกลุ่ม: Policy Denial คือระบบห้ามปลายทาง Transport Failure คือเชื่อมต่อไม่ได้ และ Content Failure คือได้ข้อมูลแล้วแต่แยกหรือแปลความไม่ได้ อย่า retry การปฏิเสธสิทธิ์เหมือน timeout อย่าให้ Agent แก้ host หรือเปลี่ยน proxy เองเพื่อทำให้สถานะเขียว เพราะนั่นเปลี่ยนขอบเขตงาน

Evidence ระบบจริงควรมี execution ID, hop, ผลตัดสิน, เหตุผล, รุ่น policy และคำขอจริง ลดข้อมูล URL ที่อาจมี secret และไม่บันทึก token การสรุปหน้าเว็บสำเร็จไม่ได้พิสูจน์ว่าทุก hop ผ่านกติกาเครือข่าย

ข้อทดสอบสมมติแปดข้อครอบคลุมเส้นทางปกติ private redirect, mixed addresses, สิทธิ์, ชื่อไม่ทราบ, วนซ้ำ, URL ผิด และ mapped loopback ตรวจ URL ที่ห้ามไม่อยู่ใน ledger และไม่เกินเพดาน ตอนนี้ NOT RUN ไม่มี pass count, coverage หรือผล Live Integration

การพิสูจน์จริงต้องใช้ sandbox และสังเกต transport/ปลายทางที่ควบคุมได้ ไม่ใช้บริการ metadata จริงเพื่อเดโม ผล upstream แยกจากผลของเรา และ fixture ไม่พิสูจน์ DNS rebinding หรือ proxy path

ต้นทุนและ Production: กำหนดขอบเขตให้วัดได้

การตรวจ DNS และการเดิน redirect เพิ่มงานตามเส้นทาง ตัวอย่างนี้กำหนดเพดานสาม redirect จึงมีคำขอหน้าเริ่มต้นและปลายทางต่อได้สูงสุดสี่ครั้งในแบบจำลอง ส่วนการอ่าน robots การ retry หรือการอ่านส่วนถัดไปอาจเพิ่มงานในระบบจริง อย่าใช้เพดานของแบบจำลองเป็นจำนวน HTTP requests ของ Fetch ทั้งวงจร

Budget ที่ควรกำหนดคือ tool calls, hops, เวลาสิ้นสุดรวม, response bytes และขนาดผลส่งให้โมเดล เราไม่ได้วัดราคา เวลา หรือเงินประหยัด ตัวอย่าง Python ใช้ CPU/RAM ในเครื่อง ไม่มี provider charge ตามโครงสร้างที่เขียน แต่ไม่ได้วัดทรัพยากรจริง

ก่อนใช้งาน ตรวจ lockfile, proxy, สิทธิ์ process และ outbound network แยกเครื่องมือสาธารณะจากเครื่องมือภายใน กำหนดผู้รับผิดชอบ incident และคืน UNKNOWN เมื่อหลักฐานยังตอบไม่ได้

Brief หกส่วน: มอบหมายการตรวจนโยบายปลายทาง

Brief นี้อนุญาตเฉพาะการวิเคราะห์ fixture การรันเครื่องมือจริงต้องมีสิทธิ์จากเจ้าของระบบแยก

1. เป้าหมาย: อธิบายและตรวจลำดับ validate-before-request ของเส้นทางอ่านเอกสาร
2. ข้อมูล/เครื่องมือ: ใช้ fixture URL, addresses และ redirect location ที่ให้; ไม่ใช้ DNS/HTTP จริง
3. สิทธิ์: อ่านและวิเคราะห์ fixture เท่านั้น; ห้าม metadata, intranet, secrets และเปลี่ยน server flags
4. สิ่งส่งมอบ: decision ทุก hop, ledger WOULD_REQUEST, terminal status และเหตุผล
5. ตรวจรับ: any nonpublic answer ต้อง BLOCK; URL ที่ห้ามไม่มีใน ledger; ไม่เกิน max_redirects
6. จุดหยุด: URLผิดรูป สิทธิ์ไม่ชัด ไม่ทราบ address หรือถึงเพดาน ให้หยุดส่งให้คนตรวจ; ห้ามเปลี่ยนปลายทางเพื่อเลี่ยงข้อห้าม

Lab: ดูเส้นทางและทดลองนโยบายจากข้อมูลสมมติ

Topic 3D ติดตาม gate ระหว่าง hop ส่วน interactive แยกทดลองชนิดคำขอ addresses สิทธิ์ และการควบคุมเครือข่าย ทั้งหมดเป็น simulation ไม่มี DNS/HTTP หรือ Agent จริง ผลอนุญาตไม่ใช่หลักฐานการเชื่อมต่อจริง

3D Lab: เส้นทางหนึ่ง URL ผ่านกี่ด่าน?

SIMULATION — DNS และการเชื่อมต่อเป็นข้อมูลสมมติทั้งหมด เลือกกรณีและนโยบาย แล้วดูว่า request ledger ได้รับปลายทางใด ไม่มีการเรียก DNS, HTTP, MCP หรือ Agent จริง ฉากสามมิติแยกจุดตรวจ DNS ออกจากจุดเชื่อมต่อ เพื่อให้เห็นช่องว่างที่ guard นี้ยังปิดไม่ได้

ผังสองมิติและคำอธิบายสำรอง: URL → DNS → Guard → Connect การผ่าน DNS ณ เวลาตรวจไม่รับรองที่อยู่ที่ transport ใช้หลังจากนั้น ฉากใช้ CSS ไม่ต้องใช้ canvas หรือ WebGL

กรณีเริ่มต้น: hop0 ผ่านและอยู่ใน ledger; hop1 ชี้เข้าภายในจึง BLOCK ก่อน request ที่สอง จำนวน request สมมติ = 1 ไม่ใช่ผลวัดระบบจริง

Visual Interactive: public IP มีสิทธิ์เรียกหรือยัง?

การทดลองแยกจากฉากสามมิติข้างบนนี้เป็นตารางตัดสินสมมติ เพิ่มนโยบายปลายทางของงานและ network egress หรือด่านออกเครือข่าย การตั้งค่าทั้งสองเป็นข้อเสนอออกแบบ ไม่ใช่ความสามารถที่ guard Fetch รับรองเอง

READY_FOR_MOCK_TRANSPORT: public และได้รับอนุญาตในงาน ยังไม่รับรองการเชื่อมต่อจริงหรือปิด DNS rebinding

อ่านข้อความสำรอง: ไม่มีสิทธิ์งาน → STOP_AUTHORIZATION; network ปฏิเสธ → BLOCK_NETWORK; guard เปิดและพบ IP non-public ใด ๆ → BLOCK_GUARD; resolve ไม่ได้ → UNKNOWN_DESTINATION; public → READY_FOR_MOCK_TRANSPORT ทั้งหมดเป็นผลของกฎจำลอง ไม่ใช่ผลทดสอบ Production

ใช้ Video Agent Lab ฝึกตรวจแหล่งข้อมูลก่อนส่ง brief

เลือกหัวข้อวิดีโอที่ต้องค้นเอกสาร เช่น “Agent อ่านเว็บอย่างมีขอบเขต” แล้วใช้ขั้น research เป็นจุดฝึกกำหนด URL และ redirect policy วงจรวิดีโอในปลั๊กอินเป็นแบบจำลองคงที่ ไม่ได้ตรวจ DNS/SSRF ให้เรา ตรวจ prompt ที่สร้างร่วมกับ brief หกส่วนนี้ด้วยตนเอง เวลาและเงินใน Cost Lab เป็นสมมติฐานที่ผู้ใช้ตั้ง ไม่ใช่ผลวัดประสิทธิภาพของ Fetch

เป้าหมาย: วางแผนวิดีโออธิบายการตรวจปลายทางทุก request
ข้อมูล/เครื่องมือ: เอกสารต้นทางที่ระบุในบทความและ fixture redirect สมมติ
ขอบเขตสิทธิ์: อ่านแหล่งที่อนุญาตเท่านั้น ห้าม resolve/fetch ภายใน ห้ามเผยแพร่วิดีโอ
สิ่งส่งมอบ: outline พร้อม source URL และตาราง URL→DNS→decision ของทุก hop
เกณฑ์ตรวจรับ: ไม่เอาคำว่า read-only มาแทนสิทธิ์ปลายทาง; ระบุ DNS rebinding/proxy-only UNKNOWN
จุดหยุด: ปลายทางใหม่ไม่อยู่ในขอบเขต หรือยืนยันที่อยู่ไม่ได้ ให้หยุดและส่งคนตัดสิน
H✦HYBRID MINDINTERACTIVE EDITION LIVE EXPERIENCE
HYBRID MIND ORIGINAL / AI AGENT WORKFLOW / 2026

จากคลิปดิบ
สู่จักรวาลคอนเทนต์

ChatGPT ตัดต่อวิดีโอแทนคนได้จริงแค่ไหน? สำรวจระบบ AI Video Editing Agent ผ่านฉากสามมิติที่โต้ตอบได้ พร้อมแยกข้อเท็จจริง สร้างพรอมป์ต์ และจำลองต้นทุนก่อนลงมือทำจริง

06 EDITING STAGES03 CONTENT FORMATS01 INTERACTIVE LAB

ออกแบบระบบตัดต่อในมุมมอง 3D

ลากบนฉากเพื่อหมุนมุมมอง แตะโหนดเพื่อดูหน้าที่ของ AI ในแต่ละขั้นตอน

แผนภาพ 6 ขั้นตอน: Footage, Story, Edit, Captions, Graphics, Render
AGENT PIPELINE / VIEWPORT ORBIT 3D
DRAG / SWIPE TO ROTATE
SELECT NODE TO INSPECT
01 / 06นำเข้าคลิปดิบ

จัดระเบียบไฟล์ ตรวจคุณภาพภาพและเสียง และกำหนดสิทธิ์เข้าถึงให้ AI Agent

● SOURCE
จุดสำคัญ: AI Agent ทำหน้าที่วางแผนและควบคุมเครื่องมือ ส่วนการตัดต่อจริงต้องมีซอฟต์แวร์หรือระบบเรนเดอร์รองรับ ฉากนี้เป็น แบบจำลองเชิงอธิบาย ไม่ใช่ระบบอัปโหลดหรือตัดต่อวิดีโอ

แยกความสามารถจริงจากคำโฆษณา

กดแต่ละประเด็นเพื่ออ่านรายละเอียดและแหล่งข้อมูล

EVIDENCE-FIRST
✓ChatGPT Work เข้าถึงไฟล์ในเครื่องได้ตรวจสอบแล้ว / มีเงื่อนไข+
รองรับการทำงานกับโฟลเดอร์หรือแอปบนคอมพิวเตอร์เดสก์ท็อป เมื่อแผนและการตั้งค่าอนุญาตและผู้ใช้ให้สิทธิ์ ส่วน Work บนมือถือหรือเว็บไม่ได้เข้าถึงโฟลเดอร์ในคอมพิวเตอร์ของคุณโดยตรง ที่มา: OpenAI Help ↗
✓Astra ใช้โปรแกรมคอมพิวเตอร์ทำงานได้ตรวจสอบแล้ว / ไม่ใช่โปรแกรมตัดต่อในตัว+
OpenAI อธิบายความสามารถด้าน computer use ของ Astra รวมถึงงานสื่อที่ใช้เครื่องมือ แต่ต้องแยกบทบาท AI ผู้ควบคุมออกจากซอฟต์แวร์ประมวลผลวิดีโอและการเรนเดอร์ไฟล์ ที่มา: OpenAI ↗
?ตัดเสร็จใน 5–10 นาทีทุกกรณียังพิสูจน์เป็นเกณฑ์ทั่วไปไม่ได้+
เวลาขึ้นกับความยาวคลิป จำนวนทรานซิชัน คุณภาพซับ เครื่องมือ และประสิทธิภาพคอมพิวเตอร์ ควรใช้การจับเวลางานจริงแบบต้นทางเดียวกัน ไม่ใช้ตัวเลขจากโพสต์เป็นเกณฑ์อ้างอิง
?ถูกกว่าจ้างคน 10 เท่าต้องกำหนดต้นทุนให้เทียบกันได้+
ต้องรวมเวลาตรวจแก้ ลิขสิทธิ์เสียง เครื่องมือที่จ่ายเพิ่ม และต้นทุนโมเดล ยังไม่มีหลักฐานว่าประหยัด 10 เท่าสำหรับทุกงาน ทดลองสมมติฐานส่วนตัวได้ใน Cost Simulator ด้านล่าง

หนึ่งไอเดีย สามรูปแบบคอนเทนต์

ปรับรูปแบบวิดีโอ แล้วดูกรอบภาพตัวอย่างและ Prompt เปลี่ยนตามแบบเรียลไทม์

WORKING INTERACTIVE
15 SEC180 SEC
LIVE CREATIVE PREVIEW9:16 · 45 SEC
HYBRID MIND / AI
AI EDITOR / EXPLAINEDAI Agent
ช่วยตัดต่อ?
ใส่ซับตามประโยคได้อัตโนมัติ
▶◉↗
CONCEPT PREVIEW · NOT RENDERED VIDEO
VERTICAL · SHORT FORMVisual Mockup

พร้อมนำไปใช้กับ AI Agent

ตัวสร้าง Prompt นี้ไม่อัปโหลดคลิป ไม่เรียก API เสียเงิน และไม่ตัดต่อวิดีโอจริง ต้องใช้กับเครื่องมือที่ผู้ใช้อนุญาตภายหลัง

จำลองเวลาและต้นทุนของคุณเอง

เลื่อนตัวเลขเพื่อเปรียบเทียบสถานการณ์สมมติ ไม่ใช่ผล benchmark ที่ยืนยันแล้ว

SCENARIO · NOT BENCHMARK
ESTIMATED TIME SAVED11.0 ชม./เดือน
18.0 ชม.
7.0 ชม.
ส่วนต่างต้นทุนเวลา + เครื่องมือ (สมมติ)฿3,920

ตัวเลขเป็นตัวอย่างเพื่อช่วยตัดสินใจ ไม่ใช่ผลประหยัดที่รับประกัน

AI ที่ตัดคลิปเป็น ไม่ได้ทำงานลำพัง

สิ่งที่น่าสนใจของ GPT-6 Astra และ GPT-6.1 Sol ไม่ได้อยู่ที่ว่าตัวโมเดลมีปุ่ม Render MP4 ซ่อนอยู่ แต่คือความสามารถในการจัดการงานหลายขั้นตอนร่วมกับเครื่องมืออื่น: อ่านไฟล์ วางลำดับเรื่อง ใช้แอป ตรวจผลลัพธ์ และแก้งานตามข้อเสนอแนะของมนุษย์

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

ข้อควรระวังคือระบบ Work ที่รันบนเว็บหรือมือถือไม่ได้หมายความว่า AI เข้าถึงคลิปบนคอมพิวเตอร์บ้านได้ทันที ต้องทำงานในสภาพแวดล้อมที่เปิดให้เข้าถึงไฟล์จริง มีเครื่องมือตัดต่อ และมีสิทธิ์ใช้งานอย่างชัดเจน

01จัดคลิปให้พร้อม

รวบรวมไฟล์ในโฟลเดอร์ที่เข้าถึงได้ ระบุสิทธิ์และข้อจำกัด

02ตรวจสคริปต์และไทม์ไลน์

ให้ Agent เสนอ Hook, ช่วงตัด และโครงเรื่องก่อนตัดต่อ

03สร้างซับ + กราฟิก

ตรวจชื่อเฉพาะ ตัวเลข ภาษาไทย และความถูกต้องของคำกล่าวอ้าง

04ตรวจไฟล์ MP4 จริง

ตรวจความละเอียด เสียง ระยะเวลา safe zone และคำบรรยาย

เมื่อใช้ prompt จาก Lab ให้แนบ brief ด้านบนแยก ไม่อ้างว่า generator เติมเงื่อนไขสิทธิ์/ตรวจรับครบเอง การทำงานของปุ่มและหน้าจอจริงยัง UNKNOWN ส่งเจ้าของตรวจด้วยตนเอง

แบบฝึกหนึ่งข้อ: หาเหตุผลที่ต้องหยุดให้ถูกชั้น

กำหนด A เป็นโฮสต์ที่อยู่ใน brief และ fixture ของ A เป็น public แต่ A ชี้ไป B ซึ่งมีคำตอบ public สองรายการและ private หนึ่งรายการ B อยู่ในรายชื่อที่อนุญาต ให้เขียน decision กับ ledger ที่คาดหมาย แล้วเปลี่ยน B ให้อยู่นอกสิทธิ์งานโดยไม่แก้ addresses อธิบายว่ากรณีที่สองควรหยุดที่ชั้นใด

เกณฑ์ตรวจรับ: กรณีแรกปฏิเสธ B เพราะมีคำตอบไม่สาธารณะแม้มีรายการ public; กรณีสองหยุดเพราะไม่ได้รับสิทธิ์ก่อนอนุญาตคำขอ ทั้งสองกรณี ledger ไม่มี B และมีเพียง A ที่ผ่านการตรวจในแบบจำลอง อย่าเขียนว่า “ไม่พบการโจมตีจริง” จากผล fixture ผู้เรียนส่งผลการวิเคราะห์ ไม่ต้องใช้เครือข่ายเพื่อทำแบบฝึกนี้

Engineering Checklist ก่อนส่งงาน

  • ตรวจรุ่นและวันที่จากต้นทาง
  • วาง gate ก่อนทุกคำขอและตรวจทุก address
  • แยก public จากสิทธิ์งาน พร้อม unresolved/proxy policy
  • คำขอที่ห้ามต้องไม่อยู่ใน ledger
  • แยก policy denial จาก retry และกำหนดเพดาน
  • ระบุ MOCK / Sandbox / Live และผลที่รันจริงก่อนกล่าวเรื่อง Production

FAQ

URL แรกเป็น HTTPS ทำไมยังต้องตรวจ Redirect?

HTTPS ของ URL แรกไม่ได้กำหนดปลายทางของคำขอถัดไป แต่ละ hop มี host และ address ที่ต้องผ่านนโยบายของมันเอง ให้ตรวจ ณ จุดก่อนส่งจริง

มี public IP หนึ่งรายการก็พอหรือไม่?

สำหรับกลไกที่ศึกษานี้ไม่พอ หากคำตอบใดไม่สาธารณะจะปฏิเสธคำขอ อย่าเลือกเฉพาะคำตอบที่สนับสนุนผลอนุญาต

เปิด –allow-private-ips เพื่อให้ Agent อ่าน intranet ได้เลยไหม?

ต้องเป็นการตัดสินใจของผู้รันระบบในขอบเขตที่ได้รับอนุญาต Flag นี้ปิด guard ปลายทางของ server ควรออกแบบสิทธิ์และเครือข่ายสำหรับงานภายในเฉพาะก่อนใช้

ตัวอย่าง Python นี้ทำ DNS และ Fetch จริงหรือไม่?

ไม่ทำ Input มาจาก fixture และ ledger หมายถึง WOULD_REQUEST ชุดทดสอบเขียนไว้แต่ NOT RUN ความปลอดภัยของ transport, proxy และ DNS rebinding จริงยังไม่ได้พิสูจน์

อ่านต่อ: Pagination และจุดหยุด และ Retry Budget การอ่านต่อหรือ retry ต้องไม่ข้ามข้อห้ามปลายทาง

แหล่งอ้างอิงและดัชนีโค้ด

แหล่งต้นทางตรวจ 14 ตุลาคม 2026 แยกจาก code และ Lab ที่ Hybrid Mind เขียน

Code Index: fetch_policy_trace.py, test_fetch_policy_trace.py, README.md, requirements.txt ทั้งหมด NOT RUN และไม่ใช่ Source Code ของ MCP Server

ใส่ความเห็น

Discover more from HYBRID MIND

Subscribe now to keep reading and get access to the full archive.

Continue reading