SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-23

كيف تمنع وكلاء الذكاء الاصطناعي من تسريب الأسرار

قد يسرّب الوكيل مفاتيح API في استدعاء أداة واحد. تعرّف إلى الرموز قصيرة العمر ومحدودة النطاق، وضعها خلف بوابة بيانات اعتماد بدلاً من المفاتيح الحقيقية.

ما يعنيه إبقاء الأسرار خارج وكلاء الذكاء الاصطناعي

وكيل الذكاء الاصطناعي هو عملية Linux عادية تنفّذ الأوامر. ويمكن للكود الذي تنفّذه العملية قراءة كل متغير بيئة تحتفظ به. لذلك فإن وجود API key في بيئة الوكيل يعني أن الوكيل يستطيع إرساله إلى أي مضيف يمكنه الوصول إليه. يعني إبقاء الأسرار خارج الوكيل منحه وسيلة وصول بدلاً من المفتاح نفسه: رمزاً مقيّد النطاق وقصير العمر، أو قيمة نائبة يستبدل بها مكوّن آخر القيمة الحقيقية عند حدود الشبكة.

لا يتعلق الأمر هنا بتحول نموذج إلى جهة معادية. الآلية أبسط من ذلك. يقرأ الوكيل صفحة ويب أو ملف README أو تعليقاً في issue يتضمن تعليمات، ثم يتبعها، لأن النموذج اللغوي لا يميّز بين النص الذي كتبته والنص الذي جلبه. هذا هو prompt injection. وعند حدوثه، يتحدد الضرر بالكامل بعامل واحد: ما تستطيع العملية قراءته. إذا لم تضع حدوداً بعد، يشرح تشغيل وكيل برمجي بأمان على خادم مستويات العزل التي يعتمد عليها هذا الدليل.

نموذج التهديد بعبارات واضحة

شغّل هذا بصلاحيات المستخدم الذي يعمل به وكيلك.

tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'

كل سطر يطبعه يمثّل طلب HTTP واحداً يفصل بين خادمك وخادم شخص غريب. انظر الآن إلى ما هو موجود على القرص بالقرب من الوكيل.

grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'

لا يحتاج وكيل يملك shell إلى استغلال معقد لإخراج تلك البيانات. تكفي أربع طرق عادية، وتبدو الطرق الأربع كلها كعمل طبيعي في السجل:

  • curl أو fetch صادر إلى أي مضيف، مع وضع القيمة في سلسلة استعلام.
  • git commit وgit push إلى مستودع يستطيع الوكيل الكتابة فيه.
  • برنامج تثبيت حزمة يشغّل تعليماً برمجياً عشوائياً بصلاحيات مستخدم الوكيل.
  • استعلام DNS عن اسم مضيف يحتوي على القيمة، ويؤدي الغرض حتى عند حظر الاتصالات الصادرة عبر HTTP.

لا يمكنك معالجة هذا بالمراجعة وحدها. الحل هو التأكد من عدم وجود أي بيانات قيّمة يمكن للوكيل الوصول إليها.

السر الموجود في شجرة العمل يصبح سراً ضمن نافذة السياق

يقرأ الوكيل الملفات. سيُقرأ ملف .env الموجود في المستودع الذي يعمل فيه، وبمجرد قراءته يصبح ضمن نافذة السياق. وهذا يعني أنه يظهر في السجل، وفي أي سجل تحتفظ به، وفي كل ما يكتبه الوكيل لاحقاً.

في السابق، عندما كان المفتاح موجوداً في شجرة العمل التي يستخدمها الوكيل:

cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billing

بعد ذلك، عند نقل الملف خارج نطاق الوصول:

sudo install -d -m 750 -o root -g agent-review /etc/agent-review
sudo install -m 640 -o root -g agent-review ~/projects/billing/.env /etc/agent-review/billing.env
rm ~/projects/billing/.env

لن يعود مستخدم الوكيل قادراً على فتح الملف، لأن شجرة العمل لم تعد تحتوي عليه. تُعد قواعد الرفض في إعدادات الوكيل نفسه طبقة ثانية، وليست الطبقة الأولى. يقرأ Claude Code قواعد الصلاحيات من .claude/settings.json في المشروع:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
  }
}

يمنع ذلك الوكيل من فتح ملف عن طريق الخطأ أثناء الاستكشاف. لكنه لا يمنع تعليمة محقونة من تشغيل base64 .env، لأن ذلك أمر shell وليس قراءة ملف. يعتمد طلب الإذن قبل تشغيل الأمر على وضع صلاحيات الجلسة. وبما أن الوضع التلقائي سيصبح الوضع الافتراضي في Claude Code في أغسطس 2026، فإن الخادم الذي لا تراقبه سينفذ مزيداً من هذه الأوامر دون طلب إذن.

وينطبق الحد نفسه على أي شيء يشكّل عادات الوكيل بدلاً من صلاحياته. فـالمهارة التي تلزم الوكيل بأصغر تغيير ينجح تمنع التشغيل من التوسع إلى ملفات لم يكن من المفترض أن يفتحها، لكنها تظل إرشاداً يمكن إقناع النموذج بتجاوزه. تعامل مع الإعدادات باعتبارها حاجزاً إرشادياً، ومع صلاحيات نظام الملفات باعتبارها الجدار الفعلي. وينطبق الفصل نفسه داخل الحاويات: يغطي ملفات البيئة والأسرار في Docker Compose نسخة هذه المشكلة في طبقة أدنى.

امنح كل وكيل حساب مستخدم خاصاً غير مميّز

إذا شغّلت الوكيل بحسابك، فسيرث مفاتيح SSH وبيانات اعتماد السحابة وسجل الصدفة الخاص بك. إنشاء حساب منفصل يتطلب أمراً واحداً ويزيل كل ذلك.

sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519

يجب أن يفشل السطر الأخير مع cat: /home/you/.ssh/id_ed25519: Permission denied. إذا طبع مفتاحاً بدلاً من ذلك، فهذا يعني أن الدليل المنزلي قابل للقراءة من المجموعة أو من جميع المستخدمين، ويعالج chmod 700 ~ هذه المشكلة. لا تضف مستخدم الوكيل إلى sudo، ولا تمنحه قاعدة NOPASSWD أوسع من الأمر الوحيد الذي يحتاج إليه فعلاً. يشرح المستخدمون ذوو أقل قدر من الامتيازات على VPS تفاصيل المجموعات وsudoers. حافظ على هذا الفصل عندما تشغّل أكثر من جلسة واحدة على الخادم، لأن جلسة Claude Code واحدة يمكنها إرسال نص مباشرة إلى جلسة أخرى، ويمكن لكل ما تحتفظ به الجلسة الأولى أن يعبر هذه القناة في رسالة واحدة.

يوجد حد أمني آخر يستحق الإضافة على VPS سحابي. تستجيب خدمة بيانات تعريف المثيل على عنوان link local ثابت، وغالباً ما تمنح بيانات اعتماد الدور لأي جهة تطلبها.

sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECT

اختبر ذلك من جهة الوكيل. يجب أن يطبع sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ لا شيء وأن ينتهي برمز غير صفري، لأن الحزمة تُرفض قبل أن تغادر الخادم.

حقن بيانات الاعتماد عند الحد الفاصل

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

OneCLI هو أحد التطبيقات مفتوحة المصدر لهذا النمط، ومرخّص بموجب Apache-2.0، ويعمل كحاوية بجوار الـagent. اعتباراً من July 2026، يوثّق المشروع هذا الإعداد:

git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --wait

تستمع لوحة المعلومات على المنفذ 10254، وتستمع البوابة على المنفذ 10255. تخزّن بيانات الاعتماد الحقيقية مرة واحدة، ثم تمنح كل agent قيمة نائبة بدلاً من المفتاح، إلى جانب access token مقيّد النطاق خاص به، ويرسله ضمن ترويسة Proxy-Authorization. تطابق البوابة الطلب الصادر وفق المضيف والمسار، وتفك تشفير بيانات الاعتماد المطابقة، ثم تستبدلها. لا تحتوي بيئة الـagent على أي شيء يستحق السرقة.

القيمة هنا ليست في التشفير. بل في أن السؤال «ما الذي استخدمه هذا الـagent، ومتى؟» يتحول إلى استعلام في السجل. تقرأ مسار تدقيق واحداً بدلاً من التخمين لمعرفة أي من البيئات الست احتوت على نسخة من المفتاح.

سلِّم السر إلى العملية، لا إلى البيئة

إذا شغّلت الوكيل باستخدام systemd، فلست بحاجة إلى متغيرات البيئة إطلاقاً. يضع LoadCredential= السر في دليل خاص لا يمكن لهذه الخدمة وحدها قراءته، ويظهر باسم %d في ملف الوحدة وباسم $CREDENTIALS_DIRECTORY داخل العملية. لا تظهر القيمة مطلقاً في /proc/<pid>/environ، لذلك لا يستطيع ps eww عرضها، ويختفي الدليل عند توقف الخدمة.

شفّر بيانات الاعتماد للمضيف أولاً. تأتي هذه الأوامر من وثائق systemd، وتعمل على systemd 250 أو أحدث، وهو ما يشمل Ubuntu 24.04 وDebian 13:

echo -n 'sk-example-value' > /tmp/plain.txt
sudo systemd-creds encrypt --name=api_key /tmp/plain.txt /etc/credstore/api_key.cred
shred -u /tmp/plain.txt
sudo systemd-run -P --wait -p LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred \
  systemd-creds cat api_key

يطبع الأمر الأخير sk-example-value. وهذا يثبت أن الملف المشفّر يمكن فك تشفيره على هذا المضيف. ثم أشِر إليه من الوحدة:

[Service]
User=agent-review
LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred
Environment=AGENT_KEY_FILE=%d/api_key
ExecStart=/usr/local/bin/agent-worker

يفتح رمز الوكيل الملف في $AGENT_KEY_FILE عندما يحتاج إلى القيمة. تستغرق قراءة الملف لحظة واحدة. أما متغير البيئة فيظل موجوداً طوال مدة تشغيل العملية، وفي كل عملية فرعية تنشئها.

فضّل الرموز المميّزة قصيرة العمر على المفاتيح طويلة العمر

يبقى المفتاح الذي لا تنتهي صلاحيته صالحاً كلما ظهر لاحقاً، بعد أشهر، في سجل أو نص مُفرَّغ. عندما تتيح الخدمة رمزاً مميّزاً للجلسة، استخدم رمز الجلسة وحدّد أقصر مدة تسمح بها المهمة.

aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/agent-readonly \
  --role-session-name agent-review \
  --duration-seconds 900

تقبل AWS STS (خدمة رموز الأمان) مدة لا تقل عن 15 دقيقة، ويكون ذلك كافياً عادةً لمهمة وكيل واحدة. بالنسبة إلى GitHub، امنح مستخدم الوكيل حساب تسجيل دخول خاصاً به عبر gh، مع رمز مميّز دقيق النطاق ومقيد بالمستودع الواحد الذي يعمل عليه، بحيث يعيد gh auth token داخل تلك الجلسة قيمة لا يمكنها الوصول إلى أي شيء آخر. حدّد النطاق حسب المورد أولاً، ثم حسب المدة.

تحقّق، ثم واصل التحقّق

ينبغي إجراء 3 عمليات تحقق بعد أي تغيير في إعداد وكيل. نفّذها باستخدام حساب مستخدم الوكيل، لا حسابك أنت.

sudo -u agent-review env | grep -iE 'key|token|secret'
sudo -u agent-review ls -la /home/you/ 2>&1 | head -3
sudo -u agent-review curl -s -o /dev/null -w '%{http_code}\n' --max-time 5 https://api.github.com/user

ينبغي أن يطبع الأمر الأول أي شيء على الإطلاق. وينبغي أن يطبع الأمر الثاني ls: cannot open directory '/home/you/': Permission denied. يوضّح الأمر الثالث الهوية التي يقدّمها مسار شبكة الوكيل، وهو السؤال الذي يجيب عنه نمط البوابة: تعني 401 أن الوكيل لا يحمل بيانات اعتماد GitHub خاصة به، بينما تعني 200 أنه يحمل بيانات اعتماد، ولذلك يجب أن تعرف الرمز المميز المستخدم. إذا كنت تشغّل الوكلاء دون مراقبة، يوضّح التحكم في تكاليف وكلاء الذكاء الاصطناعي على VPS حدود الميزانية التي تتوافق مع حدود الوصول هذه.

FAQ

هل يمكنني الوثوق بالنموذج ببساطة كي لا يسرّب مفاتيحي؟

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

هل متغيرات البيئة سيئة فعلاً بالنسبة إلى أسرار الوكلاء؟

هي سيئة بطريقة محددة: إذ ترثها العمليات. تحصل كل عملية فرعية ينشئها الوكيل على نسخة منها، بما في ذلك script البناء وtest runner وأي hook لتثبيت الحزم. ويمكن للمستخدم نفسه أيضاً قراءة هذه المتغيرات عبر /proc/<pid>/environ، لذلك يستطيع أي شيء يشغّله الوكيل قراءتها من دون أن يمررها الوكيل إليه. أما قراءة ملف عند لحظة الاستخدام، باستخدام LoadCredential= أو gateway، فتحدّ من التعرض إلى تلك اللحظة.

هل يحل وضع الأسرار في vault هذه المشكلة بمفرده؟

يحلها جزئياً فقط. يعالج vault مشكلة التخزين. وإذا استضفت هذا الـvault بنفسك، فإنه يحتاج إلى تشديد أمني خاص به، لأن اختراق خادم Vaultwarden يحدث عادةً عبر admin token أو ملف النسخ الاحتياطي، وليس عبر العناصر المشفّرة التي يحتفظ بها. ولا يعالج ذلك الخطوة الأخيرة، حين يسحب شيء ما السر من الـvault ويسلّمه إلى الوكيل باعتباره متغير بيئة، فتعود إلى الوضع نفسه. المهم هو الجهة التي تنفذ الاستبدال. إذا جلب الوكيل السر، فالسر بحوزته. وإذا نفّذ gateway أو نظام init الاستبدال خارج عملية الوكيل، فلن يحتفظ الوكيل بالسر.

كيف أعرف ما إذا كان وكيل قد سرّب شيئاً من قبل؟

لا يمكنك عادةً معرفة ذلك بعد وقوعه، وهذا هو سبب استخدام gateway. من دونه، تكون الأدلة موزعة بين سجل shell history، وسجل محادثة الوكيل، وسجلات الاتصالات الصادرة التي من المحتمل أنك لا تحتفظ بها. مع credential gateway، يكون كل استخدام لبيانات اعتماد في سطر واحد يتضمن هوية الوكيل وطابعاً زمنياً. إذا اشتبهت في حدوث تسريب، فقم بتدوير المفتاح أولاً ثم ابدأ التحقيق. تدوير المفتاح رخيص، أما اليقين فليس كذلك.

ما الحد الأدنى الذي ينبغي أن أفعله اليوم؟

انقل كل ملف .env خارج الأدلة التي تعمل فيها وكلاؤك، وأنشئ مستخدماً واحداً غير مميّز لكل وكيل. يستغرق هذان التغييران نحو عشر دقائق، ويغلقان المسار الأكثر شيوعاً، وهو قراءة الوكيل لملف بيانات اعتماد لم يكن هناك سبب لوجوده بجانب الشيفرة. أما gateway والرموز قصيرة العمر فهما الخطوة التالية، وليسا الخطوة الأولى. تنطبق نقطة البداية نفسها على أي runtime للوكيل، بما في ذلك تشغيل وكيل مستقل بأمان على VPS.