0Pricing
AI Agents · درس

سياسات الأمان لتنفيذ التعليمات البرمجية

تقييد الصلاحيات، وعزل الشبكة، وحدود نظام الملفات، والمهلات الزمنية.

سياسات الأمان لتنفيذ التعليمات البرمجية درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.

لماذا لا تكفي السياسات وحدها

إن إخبار LLM بـ «لا تصل إلى الشبكة» ليس إجراءً أمنيًا — بل هو تلميح. فقد يتجاهله LLM، أو قد يتعرض لكسر الحماية، أو قد تنتهك التعليمات البرمجية المُنشأة القاعدة بشكل غير مباشر.

يجب فرض سياسات الأمان الحقيقية في طبقة التنفيذ، وليس في المطالبة فقط.

نظرة عامة على قيود القدرات

تحد قيود القدرات ما يمكن لعملية تعمل في بيئة معزولة فعله على مستوى نظام التشغيل. وتقسم قدرات Linux امتيازات المستخدم الجذر إلى صلاحيات دقيقة يمكن إسقاطها بشكل منفصل.

يُسمى إسقاط جميع القدرات باستثناء الحد الأدنى المطلوب مبدأ أقل امتياز.

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())

حدود الموارد: وحدة المعالجة المركزية والذاكرة والوقت

ثلاثة حدود للموارد ينبغي لكل بيئة معزولة فرضها:

  • الذاكرة: mem_limit — لمنع هجمات نفاد الذاكرة
  • وحدة المعالجة المركزية: nano_cpus أو cpu_quota — لمنع استنفاد وقت المعالجة
  • الوقت: مهلة التنفيذ — لمنع الحلقات اللانهائية
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

قبل تنفيذ التعليمات البرمجية، افحص شجرة البنية المجردة بحثًا عن عبارات الاستيراد. وارفض أي استيراد غير موجود في قائمة السماح. وهذه طبقة دفاع إضافية — وليست بديلًا عن عناصر التحكم على مستوى نظام التشغيل، لكنها مفيدة لاكتشاف انتهاكات السياسة الواضحة مبكرًا.

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

حدود حجم المخرجات

قد تنتج حلقة طباعة لا نهائية عدة غيغابايت من المخرجات. حدّدوا حجم stdout/stderr بحجم معقول (مثل 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

يمنع خيار الأمان 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'

دمج جميع السياسات

تجمع بيئة sandbox المخصصة للإنتاج بين جميع الطبقات: إسقاط إمكانات نظام التشغيل، وملف تعريف 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)}

تسجيل انتهاكات السياسات

عند اكتشاف انتهاك لسياسة (مثل استيراد محظور أو استدعاء خطير أو انتهاء مهلة)، سجّلوا الحدث مع معرّف جلسة الوكيل، وتجزئة مقتطف التعليمات البرمجية، ونوع الانتهاك. تُغذّي هذه البيانات لوحة معلومات الأمان وتساعد على ضبط السياسات بمرور الوقت.

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، وتعطيل الشبكة، وفرض حدود على الذاكرة ووحدة المعالجة المركزية والوقت، والتحقق من عمليات الاستيراد على مستوى AST.

لا تكفي أي طبقة بمفردها — فالدفاع متعدد الطبقات يعني أن كل طبقة تعوّض عن التجاوزات في الطبقات الأخرى.

الأسئلة الشائعة

هل درس «سياسات الأمان لتنفيذ التعليمات البرمجية» مجاني؟

نعم — نص درس «سياسات الأمان لتنفيذ التعليمات البرمجية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.

ماذا ستتعلم في «سياسات الأمان لتنفيذ التعليمات البرمجية»؟

تقييد الصلاحيات، وعزل الشبكة، وحدود نظام الملفات، والمهلات الزمنية. تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟

لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «سياسات الأمان لتنفيذ التعليمات البرمجية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟

نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. بيئات اختبار الوكلاء المعتمدة على Docker
  2. العزل باستخدام الآلات الافتراضية لوكلاء التعليمات البرمجية عالية الأمان
  3. خدمات E2B وبيئات الاختبار السحابية
  4. سياسات الأمان لتنفيذ التعليمات البرمجية
← العودة إلى AI Agents