0Pricing
AI Agents · 课时

代码执行的安全策略

能力限制、网络隔离、文件系统限制和超时设置

代码执行的安全策略 是 CoddyKit 上的免费 AI Agents 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。

为什么仅靠策略还不够

告诉 LLM“不要访问网络”并不是一种安全控制,而只是一种提示。LLM 可能忽略它、被越狱,或者生成的代码可能间接违反该规则。

真正的安全策略必须在执行层强制实施,而不能只写在提示中。

能力限制概述

能力限制会在 OS 层面限制沙盒进程可以执行的操作。Linux 能力将 root 权限拆分为细粒度的能力,可以单独移除。

只保留最低限度的必要能力,移除其他所有能力,这称为最小权限原则。

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

seccomp 配置文件:过滤系统调用

seccomp(安全计算模式)允许您指定获准系统调用的允许列表。任何不在列表中的系统调用都会导致进程收到 SIGSYS 并被终止。

Docker 自带默认的 seccomp 配置文件。您可以提供自定义 JSON 配置文件,使限制更加严格。

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

将 Python 导入列入允许列表

执行代码之前,扫描 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(),以及使用位于 /tmp 之外路径的 open()。

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']

输出大小限制

失控的打印循环可能生成数 GB 的输出。请将标准输出和标准错误限制在合理大小(例如 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 获取额外权限。即使代码进入 shell,也无法提升权限。

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

seccomp 配置文件中的“defaultAction: SCMP_ACT_ERRNO”设置有什么作用?

seccomp 配置文件控制进程可以进行哪些系统调用。defaultAction 字段决定对于配置文件中未明确列出的系统调用将采取什么措施。

安全策略回顾

有效的代码执行安全机制需要多层防护:移除 Linux 权限能力、使用 seccomp 过滤系统调用、使用带有 tmpfs 临时空间的只读文件系统、启用 no-new-privileges、禁用网络、限制内存、CPU 和时间,以及在 AST 层面检查导入。

单独任何一层都不够充分——深度防御意味着每一层都能弥补其他层可能被绕过的漏洞。

常见问题解答

「代码执行的安全策略」课时是免费的吗?

是的 — 「代码执行的安全策略」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。

「代码执行的安全策略」这节课中我会学到什么?

能力限制、网络隔离、文件系统限制和超时设置 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 AI Agents 需要有经验吗?

无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「代码执行的安全策略」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 AI Agents 课中编写并运行代码吗?

能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 基于 Docker 的智能体沙箱
  2. 高安全性代码智能体的 VM 隔离
  3. E2B 与云沙箱服务
  4. 代码执行的安全策略
← 返回 AI Agents