الإعدادات المكتوبة بشكل مباشر.
يقوم مساعدو الذكاء الاصطناعي بكتابة القيم الخاصة بالبيئة — مثل روابط URL، والمنافذ، والمسارات، وفترات انتهاء الصلاحية، والمفاتيح، والأرقام السحرية — مباشرة في منطق الكود بدلاً من قراءتها من ملف الإعدادات أو البيئة، وذلك لأن القيمة الحرفية هي الرمز التالي الأكثر احتمالاً للظهور، كما يفتقر النموذج إلى الوعي بوجود طبقة الإعدادات الحالية لديك.
##العلامات والأعراض
يميل مساعد الذكاء الاصطناعي إلى إصدار قيمة حرفية معقولة في المكان الذي ينبغي أن يوضع فيه مرجع لمتغير. يعمل الكود في العرض التوضيحي، لذا تنجو هذه الرائحة من المراجعة ما لم تبحث عنها خصيصاً.
العلامات المميزة:
- نقاط نهاية، ومنافذ، ومسارات، وفترات مهلة مدمجة (inline) متناثرة في منطق الأعمال بدلاً من تجميعها في موديول الإعدادات: مثل
http://localhost:3000، أو/tmp/cache، أو5432، أوsetTimeout(..., 30000). - أرقام/سلاسل نصية سحرية لا تشير إلى ثابت مسمى — مثل عدد مرات إعادة المحاولة، أو أحجام الصفحات، أو حدود معدل الاستخدام، أو حدود ميزات النظام.
- تكرار نفس القيمة الحرفية عبر ملفات متعددة لأن النموذج أعاد توليدها بدلاً من استيراد ثابت موجود (وهو ما يمثل نمط GitClear المتمثل في "ارتفاع النسخ/اللصق وانخفاض إعادة الهيكلة" بشكل مصغر).
- بيانات اعتماد / مفاتيح مكتوبة بشكل مباشر — مثل رموز واجهة برمجة التطبيقات المميزة، أو مفاتيح التشفير، أو سلاسل مصادقة
Basicالمنسوخة من بيانات التدريب. - تجاهل كود جديد بالكامل لكائن إعدادات
config.ts/.env/ الإعدادات الحالي والموجود مسبقاً. - قيم مخصصة لبيئة معينة: ككتابة رابط URL لبيئة اختبار أو معرف حساب تجريبي مباشرة في مسار يُشحن لاحقاً إلى بيئة الإنتاج.
// 🚩 مولَّد بالذكاء الاصطناعي: كل إعداد قيمة حرفية، وقيم التطوير مضمّنة في الكود
export async function syncOrders() {
const res = await fetch("https://api.staging.acme.dev/v1/orders", {
headers: { Authorization: "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" },
signal: AbortSignal.timeout(30000),
});
const orders = (await res.json()).slice(0, 50); // لماذا 50؟
for (let i = 0; i < 3; i++) { /* إعادة المحاولة 3 مرات... لماذا 3؟ */ }
}
سطر Authorization يمثل انتهاكاً تكتشفه أدوات مثل gitleaks/Semgrep؛ بينما تمثل قيم مثل الرابط، و 30000، و 50، و 3 روائح للقيم السحرية؛ ورابط api.staging.acme.dev هو قيمة تطوير على وشك الوصول إلى الإنتاج.
##أسباب المشكلة
لماذا تنتجها النماذج؟
- القيمة الحرفية هي الرمز التالي الأعلى احتمالاً. بالنظر إلى استدعاء
fetch(، فإن الإكمال الأرخص الذي يلبي متطلبات التوجيه المباشر هو سلسلة نصية لرابط URL محدد، وليسconfig.apiBaseUrl. يتطلب حل المرجع معرفة أن الرمز موجود في مكان آخر؛ بينما لا يتطلب إصدار قيمة أي معرفة مسبقة. تقوم النماذج بالتحسين لإنتاج مقطع كود معقول محلياً وقابل للتشغيل. - مجموعة بيانات التدريب عبارة عن مقاطع كود برمجية قائمة بذاتها. تضع الدروس البرمجية، وأمثلة ملفات README، وإجابات Stack Overflow قيمها بشكل مدمج (inline) حتى تعمل بشكل مستقل ومستقر. لقد تعلم النموذج أن "كود الأمثلة الجيد" يحتوي على قيم مباشرة — وهو عكس النظافة والتنظيم المطلوب في كود الإنتاج.
- غياب سياق المستودع / نافذة سياق محدودة. لا يكون النموذج عادة قد قرأ مجلد
config/أو مخطط متغيرات البيئة أو ملف الثوابت لديك، لذا لا يستطيع إعادة استخدامها. ويربط ملخص DevClass لبحث GitClear ذلك بارتفاع التكرار: فالمساعدات أقل ميلاً إلى اقتراح إعادة استخدام دالة مشابهة، ويعود ذلك جزئياً إلى محدودية حجم السياق. وتُظهر بيانات GitClear نفسها أن الكتل التي تضم خمسة أسطر مكررة أو أكثر نمت نحو ثمانية أضعاف خلال 2024، بينما انخفضت الأسطر المرتبطة بإعادة الهيكلة ("المنقولة") من 25% من الأسطر المعدلة في 2021 إلى أقل من 10% في 2024. - التملق / الانحياز للإجابة على الأمر الموجه. عندما يُطلب من النموذج "إضافة مزامنة للطلبات"، فإنه يقدم شيئاً يعمل الآن؛ أما فصل الإعدادات وتصديرها فهو عمل إضافي لن يتطوع للقيام به ما لم يُطلب منه ذلك بوضوح.
- التقادم بسبب تاريخ انتهاء بيانات التدريب. كثيراً ما تكون القيم الحرفية المكتوبة مباشرة قيماً قديمة — نقاط نهاية قديمة، أو إصدارات API مهملة، أو منافذ افتراضية، أو ثوابت تشفير ضعيفة. ويرجع مقال OX Security عن أمان البرمجة بالإحساس ممارسات قديمة مثل التجزئة بـ MD5 إلى "أنماط تعلمها النموذج من قواعد كود قديمة كانت فيها هذه الممارسات معياراً صناعياً في وقت ما"، ويشير إلى أن "النموذج لا يدرك إطلاقاً أن معايير الأمان قد تطورت".
لماذا يسبب ضرراً؟
- قابلية الصيانة — الجراحة بالخردق (Shotgun Surgery). يعني تغيير مهلة زمنية واحدة أو رابط URL أساسي واحد البحث عن كل قيمة حرفية مكررة عبر قاعدة الكود بأكملها؛ وفي حال إغفال واحدة، ينحرف السلوك بصمت في مواقع الاستدعاء.
- الصحة عبر بيئات التشغيل المختلفة. قد يتم شحن رابط URL لبيئة اختبار (staging) أو معرف حساب تطوير مكتوب مباشرة في المنطق إلى بيئة الإنتاج الفعلي؛ وتنحرف الحدود الرقمية السحرية التي لا تحمل اسماً عن القيم التي يجب أن تعكسها وتتزامن معها.
- الأمان. الرموز والمفاتيح المكتوبة مباشرة في الكود هي تسريب لبيانات الاعتماد — فبمجرد إيداعها تبقى في سجل git إلى الأبد. ووجدت دراسة تجريبية لكود البناء المولد بالذكاء الاصطناعي (arXiv 2601.16839) 364 رائحة في كود البناء ضمن طلبات دمج كتبها وكلاء، منها 25 مساراً/رابطاً مكتوباً مباشرة و5 بيانات اعتماد مكتوبة مباشرة صُنفت عالية الخطورة؛ وقد دُمج أكثر من 61% من طلبات الدمج تلك.
- عبء المراجعة والدين التقني. يجب على المراجعين التحقق من مصدر كل قيمة حرفية، والقيم التي تتحكم في السلوك عبر الدوال المساعدة والعتبات هي بالضبط الأصعب في التدقيق اليدوي. وفي مقابلة Stack Overflow مع إينو رييس من Factory يلاحظ رييس أنه "كلما ارتفعت جودة قاعدة الكود، زاد تسريع الذكاء الاصطناعي للمؤسسة" — وانتشار القيم المكتوبة مباشرة يقوض هذا الأساس تحديداً.
##المعالجة
تكتيكات المراجعة وصياغة الأوامر
- وجه النموذج إلى طبقة الإعدادات الخاصة بك: "اقرأ ملف
src/config.tsوملف.env.example؛ استخدمconfig.*/process.envلكل رابط URL، ومنفذ، ومهلة، وبيانات اعتماد. لا تقدم قيماً حرفية مباشرة". تكتب النماذج القيم مباشرة لأنها لا تعرف بوجود الثابت المسمى — لذا قم بتسميته وإرشاده إليه. - احظر القيم السحرية صراحة: "لا تستخدم أرقاماً أو سلاسل نصية سحرية — استخرج ثوابت مسماة". ثم اطلب منه تشغيل الأمر
eslint --rule no-magic-numbersوماسح الأسرار (gitleaks/Semgrep) وإصلاح ما يتم تمييزه من أخطاء. وفقاً لتوجيهات Factory، اربط أدوات الفحص/المسح في الحلقة التكرارية حتى يصحح الوكيل البرمجي نفسه بدلاً من الاعتماد على المراجعة البشرية. - وفر مخططاً لمتغيرات البيئة (مثل zod/envalid/
.env.example) بحيث يجد النموذج مكاناً يضع فيه القيم بدلاً من تخمينها. - ابحث في الفروقات (diffs) الجديدة عن كلمات مثل
http، وlocalhost، وقيم IP، وBearer، والأرقام المجردة في معاملات الاستدعاء قبل الدمج.
إعادة الهيكلة — تقنيات الكتالوج، إضافة إلى ممارسة واحدة للإعدادات:
- استبدال الرقم السحري بثابت رمزي للعتبات والأعداد والأحجام.
- استخراج الفئة لجمع الإعدادات في وحدة إعدادات واحدة ذات أنواع محددة ويتم التحقق من صحتها.
- انقل القيم التي تختلف بين البيئات والأسرار إلى متغيرات البيئة (إعدادات وفق منهجية 12-factor) واقرأها فقط عبر تلك الوحدة؛ ولا تودع الأسرار في المستودع أبداً.
// config.ts — مصدر واحد للحقيقة، تُتحقّق صحة قيمه
import { z } from "zod";
const env = z.object({
ORDERS_API_BASE_URL: z.string().url(),
ORDERS_API_TOKEN: z.string().min(1),
ORDERS_TIMEOUT_MS: z.coerce.number().default(30_000),
ORDERS_PAGE_SIZE: z.coerce.number().default(50),
ORDERS_MAX_RETRIES: z.coerce.number().default(3),
}).parse(process.env);
export const config = env;
// ✅ بعد: مراجع بدلاً من القيم الحرفية — موضع واحد للتغيير، والسر خارج الكود المصدري
import { config } from "./config";
export async function syncOrders() {
const res = await fetch(`${config.ORDERS_API_BASE_URL}/v1/orders`, {
headers: { Authorization: `Bearer ${config.ORDERS_API_TOKEN}` },
signal: AbortSignal.timeout(config.ORDERS_TIMEOUT_MS),
});
const orders = (await res.json()).slice(0, config.ORDERS_PAGE_SIZE);
for (let i = 0; i < config.ORDERS_MAX_RETRIES; i++) { /* ... */ }
}
إذا تم تسريب سر بالفعل في التزام كود سابق، فقم بتغييره واستبداله فوراً — فحذف السطر لا يطهر تاريخ سجلات git.
##أدوات الكشف
- ESLint no-magic-numbers — منع الأرقام السحرية (Disallow magic numbers)
- SonarSource typescript:S109 / java:S109 — الأرقام السحرية
- SonarSource java:S1075 — عناوين URI المكتوبة بشكل مباشر
- SonarSource java:S2068 — بيانات الاعتماد المكتوبة بشكل مباشر
- Checkstyle MagicNumber — فحص الأرقام السحرية
- PMD AvoidUsingHardCodedIP — تجنب عناوين IP المكتوبة بشكل مباشر
- Bandit B105 hardcoded_password_string / B108 hardcoded_tmp_directory — كلمات المرور/المسارات المؤقتة المكتوبة بشكل مباشر (بايثون)
- gitleaks generic-api-key — ماسح الأسرار المكتوبة بشكل مباشر
- Semgrep generic.secrets / hardcoded-credentials — قواعد الأسرار/الإعدادات المكتوبة بشكل مباشر
- eslint-plugin-no-secrets no-secrets/no-secrets — كشف السلاسل النصية ذات العشوائية العالية (الأسرار)