0Pricing
AI Agents · บทเรียน

นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด

การจำกัดความสามารถ การแยกเครือข่าย ข้อจำกัดระบบไฟล์ และระยะหมดเวลา

นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดนโยบายจึงไม่เพียงพอด้วยตัวเอง

การบอก LLM ว่า «อย่าเข้าถึงเครือข่าย» ไม่ใช่การควบคุมความปลอดภัย แต่เป็นเพียงคำแนะนำ LLM อาจเพิกเฉย ถูกเจลเบรก หรือโค้ดที่สร้างขึ้นอาจละเมิดกฎทางอ้อม

นโยบายความปลอดภัยที่แท้จริงต้องบังคับใช้ที่ ชั้นการทำงาน ไม่ใช่บังคับใช้เฉพาะในพรอมต์เท่านั้น

ภาพรวมข้อจำกัดด้านความสามารถ

ข้อจำกัดด้านความสามารถจะจำกัดสิ่งที่กระบวนการในแซนด์บ็อกซ์ทำได้ในระดับ OS ความสามารถของลินุกซ์จะแบ่งสิทธิ์ของผู้ดูแลระบบออกเป็นความสามารถย่อย ๆ ซึ่งสามารถยกเลิกได้ทีละรายการ

การยกเลิกความสามารถทั้งหมด ยกเว้นความสามารถขั้นต่ำที่จำเป็น เรียกว่า หลักสิทธิ์น้อยที่สุด

import docker
client = docker.from_env()

# Drop all Linux capabilities
output = client.containers.run(
    'python:3.12-slim',
    'python -c "print(\"safe run\")"',
    cap_drop=['ALL'],
    network_disabled=True,
    mem_limit='256m',
    auto_remove=True
)
print(output.decode())

การบล็อกการเขียนดิสก์นอก /tmp

ใช้ระบบไฟล์รากแบบอ่านอย่างเดียว และเมานต์เฉพาะ /tmp ให้เขียนได้ วิธีนี้จะป้องกันไม่ให้โค้ดแก้ไขไฟล์ระบบหรือเก็บข้อมูลไว้นอกพื้นที่ชั่วคราวที่กำหนด

import tempfile, docker
client = docker.from_env()

with tempfile.TemporaryDirectory() as tmpdir:
    output = client.containers.run(
        'python:3.12-slim',
        'python -c "open(\"/tmp/ok.txt\",\"w\").write(\"ok\"); print(open(\"/tmp/ok.txt\").read())"',
        read_only=True,
        tmpfs={'/tmp': 'size=64m,mode=1777'},
        network_disabled=True,
        mem_limit='128m',
        auto_remove=True
    )
    print(output.decode())  # 'ok' — /tmp write allowed
    # Writing anywhere else raises ReadOnlyFileSystem

โปรไฟล์ซีคอมป์: การกรองการเรียกระบบ

ซีคอมป์ (โหมดการประมวลผลที่ปลอดภัย) ช่วยให้คุณระบุรายการอนุญาตของการเรียกระบบที่ยอมรับได้ การเรียกระบบใดก็ตามที่ไม่อยู่ในรายการจะทำให้กระบวนการถูกยุติด้วย SIGSYS

ด็อกเกอร์มีโปรไฟล์ซีคอมป์เริ่มต้นให้ คุณสามารถระบุโปรไฟล์เจสันที่กำหนดเองเพื่อเพิ่มความเข้มงวดได้

import json, docker
client = docker.from_env()

# Minimal seccomp profile: only allow read, write, open, close, exit
seccomp_profile = json.dumps({
    'defaultAction': 'SCMP_ACT_ERRNO',
    'architectures': ['SCMP_ARCH_X86_64'],
    'syscalls': [
        {'names': ['read', 'write', 'open', 'openat', 'close',
                   'fstat', 'mmap', 'mprotect', 'munmap', 'brk',
                   'exit', 'exit_group', 'rt_sigaction',
                   'rt_sigprocmask', 'futex'],
         'action': 'SCMP_ACT_ALLOW'}
    ]
})

output = client.containers.run(
    'python:3.12-slim',
    'python -c "print(1+1)"',
    security_opt=[f'seccomp={seccomp_profile}'],
    auto_remove=True
)
print(output.decode())

ขีดจำกัดทรัพยากร: CPU หน่วยความจำ และเวลา

ขีดจำกัดทรัพยากรสามรายการที่แซนด์บ็อกซ์ทุกแห่งควรบังคับใช้:

  • หน่วยความจำ: mem_limit — ป้องกันการโจมตีแบบ OOM
  • CPU: nano_cpus หรือ cpu_quota — ป้องกันการใช้ CPU จนหมด
  • เวลา: การหมดเวลาการทำงาน — ป้องกันลูปไม่สิ้นสุด
output = client.containers.run(
    'python:3.12-slim',
    'python -c "import time; time.sleep(100)"',
    mem_limit='128m',
    nano_cpus=500_000_000,   # 0.5 CPU
    network_disabled=True,
    auto_remove=True,
    timeout=10               # kill after 10 seconds
)
# Raises ReadTimeout after 10 seconds

การอนุญาตการนำเข้าไพธอนตามรายการ

ก่อนเรียกใช้โค้ด ให้สแกน AST เพื่อค้นหาคำสั่งนำเข้า ปฏิเสธการนำเข้าทุกรายการที่ไม่อยู่ในรายการอนุญาต วิธีนี้เป็นชั้นการป้องกันเพิ่มเติม ไม่ใช่สิ่งทดแทนการควบคุมระดับ OS แต่มีประโยชน์สำหรับตรวจจับการละเมิดนโยบายที่เห็นได้ชัดตั้งแต่เนิ่น ๆ

import ast

ALLOWED_IMPORTS = {'math', 'statistics', 'json', 'csv', 'datetime', 'collections', 're'}

def check_imports(code: str) -> list[str]:
    tree = ast.parse(code)
    blocked = []
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name.split('.')[0] not in ALLOWED_IMPORTS:
                    blocked.append(alias.name)
        elif isinstance(node, ast.ImportFrom):
            if node.module and node.module.split('.')[0] not in ALLOWED_IMPORTS:
                blocked.append(node.module)
    return blocked

print(check_imports('import socket; print(1)'))   # ['socket']
print(check_imports('import math; print(math.pi)'))  # []

การตรวจหารูปแบบโค้ดอันตราย

นอกเหนือจากการนำเข้า ให้ตรวจสอบรูปแบบที่หลีกเลี่ยงข้อจำกัดการนำเข้า เช่น __import__, exec(), eval(), compile() และ open() ที่ใช้เส้นทางนอก /tmp

import ast

DANGEROUS_CALLS = {'exec', 'eval', 'compile', '__import__', 'breakpoint'}

def check_dangerous_calls(code: str) -> list[str]:
    tree = ast.parse(code)
    found = []
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name):
                if node.func.id in DANGEROUS_CALLS:
                    found.append(node.func.id)
            elif isinstance(node.func, ast.Attribute):
                if node.func.attr in DANGEROUS_CALLS:
                    found.append(node.func.attr)
    return found

print(check_dangerous_calls('exec("import os")'))  # ['exec']

ขีดจำกัดขนาดผลลัพธ์

ลูปการพิมพ์ที่ทำงานไม่หยุดอาจสร้างผลลัพธ์ได้หลายกิกะไบต์ ให้จำกัดเอาต์พุตมาตรฐานและเอาต์พุตข้อผิดพลาดมาตรฐานให้อยู่ในขนาดที่เหมาะสม เช่น 1MB และตัดทอนหรือหยุดคอนเทนเนอร์หากเกินขนาดที่กำหนด

MAX_OUTPUT_BYTES = 1 * 1024 * 1024  # 1 MB

def run_with_output_limit(client, code: str) -> dict:
    container = client.containers.run(
        'python:3.12-slim',
        f'python -c "{code}"',
        mem_limit='256m',
        network_disabled=True,
        detach=True
    )
    try:
        container.wait(timeout=30)
        logs = container.logs(stdout=True, stderr=True)
        if len(logs) > MAX_OUTPUT_BYTES:
            return {'success': False, 'error': 'Output too large'}
        return {'success': True, 'output': logs.decode(errors='replace')}
    finally:
        container.remove(force=True)

if __name__ == '__main__':
    class FakeContainer:
        def wait(self, timeout=30): pass
        def logs(self, stdout=True, stderr=True): return b'Analysis complete: 42 rows processed.'
        def remove(self, force=True): pass
    class FakeContainers:
        def run(self, *args, **kwargs): return FakeContainer()
    class FakeClient:
        containers = FakeContainers()

    result = run_with_output_limit(FakeClient(), 'print(42)')
    print('Success:', result['success'])
    print('Output :', result['output'])

แฟล็กป้องกันการเพิ่มสิทธิ์

ออปชันความปลอดภัย no-new-privileges ป้องกันไม่ให้กระบวนการได้รับสิทธิ์เพิ่มเติมผ่านไบนารี setuid หรือ sudo แม้โค้ดจะเปิดเชลล์ ก็ไม่สามารถยกระดับสิทธิ์ได้

output = client.containers.run(
    'python:3.12-slim',
    'python -c "import os; print(os.getuid())"',
    user='nobody',                              # run as non-root
    security_opt=['no-new-privileges:true'],    # no privilege escalation
    cap_drop=['ALL'],                           # no capabilities
    network_disabled=True,
    mem_limit='128m',
    auto_remove=True
)
print(output.decode())  # numeric UID of 'nobody'

การรวมทุกนโยบาย

แซนด์บ็อกซ์ระดับใช้งานจริงจะรวมการป้องกันทุกชั้นเข้าด้วยกัน ได้แก่ การถอดความสามารถของระบบปฏิบัติการ โพรไฟล์ seccomp ระบบไฟล์แบบอ่านอย่างเดียว no-new-privileges การปิดเครือข่าย การจำกัดทรัพยากร และการกำหนดเวลาหมดอายุ การป้องกันหลายชั้นช่วยให้การหลีกเลี่ยงชั้นหนึ่งถูกหยุดไว้ด้วยอีกชั้นหนึ่ง

import tempfile, json, docker
client = docker.from_env()

def maximum_security_run(code: str) -> dict:
    with tempfile.TemporaryDirectory() as tmpdir:
        try:
            out = client.containers.run(
                'python:3.12-slim',
                f'python -c "{code}"',
                user='nobody',
                security_opt=['no-new-privileges:true'],
                cap_drop=['ALL'],
                network_disabled=True,
                read_only=True,
                tmpfs={'/tmp': 'size=32m,mode=1777'},
                mem_limit='128m',
                nano_cpus=500_000_000,
                auto_remove=True,
                timeout=15
            )
            return {'success': True, 'output': out.decode()}
        except Exception as e:
            return {'success': False, 'error': str(e)}

การบันทึกการละเมิดนโยบาย

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

import hashlib, logging, time

logging.basicConfig(level=logging.INFO)
security_logger = logging.getLogger('sandbox.security')

def policy_check_and_run(code: str, session_id: str) -> dict:
    violations = check_imports(code) + check_dangerous_calls(code)
    code_hash = hashlib.sha256(code.encode()).hexdigest()[:16]

    if violations:
        security_logger.warning(
            'POLICY_VIOLATION session=%s hash=%s violations=%s',
            session_id, code_hash, violations
        )
        return {'success': False, 'error': f'Blocked: {violations}'}

    result = maximum_security_run(code)
    security_logger.info(
        'EXEC session=%s hash=%s success=%s',
        session_id, code_hash, result['success']
    )
    return result

การตั้งค่า 'defaultAction: SCMP_ACT_ERRNO' ในโพรไฟล์ seccomp ทำหน้าที่อะไร

โพรไฟล์ seccomp ควบคุมว่ากระบวนการจะเรียกใช้การเรียกระบบใดได้บ้าง ฟิลด์ defaultAction จะกำหนดว่าจะเกิดอะไรขึ้นกับการเรียกระบบที่ไม่ได้ระบุไว้อย่างชัดเจนในโพรไฟล์

สรุปนโยบายความปลอดภัย

การรักษาความปลอดภัยในการเรียกใช้โค้ดที่มีประสิทธิผลจำเป็นต้องมี หลายชั้น: การถอดความสามารถของ Linux การกรองการเรียกระบบด้วย seccomp ระบบไฟล์แบบอ่านอย่างเดียวพร้อมพื้นที่ชั่วคราวแบบ tmpfs no-new-privileges การปิดเครือข่าย การจำกัดหน่วยความจำ/CPU/เวลา และการตรวจสอบการนำเข้าระดับ AST

ไม่มีชั้นใดเพียงชั้นเดียวที่เพียงพอ — การป้องกันหลายชั้นหมายความว่าแต่ละชั้นจะช่วยชดเชยจุดที่ชั้นอื่นอาจถูกหลีกเลี่ยงได้

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

บทเรียน “นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด”

การจำกัดความสามารถ การแยกเครือข่าย ข้อจำกัดระบบไฟล์ และระยะหมดเวลา คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม

ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. แซนด์บ็อกซ์เอเจนต์บน Docker
  2. การแยก VM สำหรับเอเจนต์รันโค้ดความปลอดภัยสูง
  3. บริการแซนด์บ็อกซ์ E2B และระบบคลาวด์
  4. นโยบายความปลอดภัยสำหรับการเรียกใช้โค้ด
← กลับไปที่ AI Agents