پرش به محتوای اصلی
پرش به محتوای مقاله

«کدی که اجرا می‌شود لزوماً امن نیست»؛ چالش جدید مهندسان ارشد

·۲۵ شهریور ۱۴۰۵۸ دقیقه مطالعه
جلسه جفت‌برنامه‌نویسی که حتی یک وصله هم در پنجره چت ثبت نکرد
جلسه جفت‌برنامه‌نویسی که حتی یک وصله هم در پنجره چت ثبت نکرد
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

معرفی متدولوژی Shape Gate برای تبدیل استانداردهای امنیتی ذهنی مهندسان ارشد به فیلترهای متنی سخت‌گیرانه پیش از ادغام کد.

تصور کنید یک توسعه‌دهنده میان‌رده با اطمینان کامل، تکه کدی را که توسط هوش مصنوعی تولید شده به محیط عملیاتی می‌فرستد، اما یک مهندس ارشد در لحظه آخر متوجه می‌شود که این کد در واقع یک «سند جرم» برای نشت داده‌هاست، نه یک راهکار. در ۱۶ سپتامبر ۲۰۲۶، دقیقاً همین اتفاق افتاد؛ یک مهندس ارشد مانع از آن شد که یک توسعه‌دهنده میان‌رده یک وصله ۴۰ خطی تولید شده توسط AI را اعمال کند، زیرا این کد به جای حل مشکل، گواهی بر یک شکست امنیتی بود. در حالی که کد تولید شده توسط عامل (Agent) در محیط IDE بدون خطا کامپایل می‌شد، اما سعی داشت از کلیدهای محیطی استفاده کند که هندلر مربوطه مالک آن‌ها نبود و داده‌های خصوصی مشتریان را در لاگ‌ها افشا می‌کرد.

این حادثه تنشی قدیمی را در مهندسی نرم‌افزار مدرن برجسته می‌کند. بسیاری از برنامه‌نویسان اکنون با عامل‌های هوش مصنوعی (AI Agents) — شبیه دستیارهای دیجیتالی که می‌توانند به‌جای شما ابزارها را اجرا کنند و کد بنویسند — به عنوان یک «نظر دوم» یا راهی برای سریع‌تر رسیدن به تست‌های سبز (Pass) برخورد می‌کنند. اما همان‌طور که در تحلیل قبلی ما درباره‌ی امنیت مدل‌های بازمتن اشاره کردیم، مدلی که در مقالات عمومی «بهتر از اکثر برنامه‌نویسان کد می‌زند»، هنوز نمی‌تواند استانداردهای امنیتی (Security Invariants) را ابداع کند که خودِ مجموعه تست‌ها فراموش کرده‌اند نام ببرند.

کالبدشکافی یک وصله شکست‌خورده

طبق گزارش این مورد، جلسه جفت‌برنامه‌نویسی با یک وب‌هوک (Webhook) معیوب از سوی یک ارائه‌دهنده پرداخت شروع شد. ارائه‌دهنده یک درخواست POST را مجدداً ارسال کرده بود، در حالی که سرویس قبلاً آن را تأیید کرده بود. این نوع تکرار درخواست‌ها در سیستم‌های توزیع‌شده، اهمیت استفاده از کلیدهای Idempotency را برای جلوگیری از اجرای مکرر عملیات دوچندان می‌کند. عامل هوش مصنوعی در محیط IDE، یک تابع کمکی ۴۰ خطی پیشنهاد داد که عملیات fetch را در یک مکانیزم عقب‌نشینی نمایی (Exponential Backoff) قرار می‌داد. مهندس میان‌رده از ساختار و شکل ظاهری این تابع خوشش آمد، اما مهندس ارشد ابتدا به محیط اطراف نگاه کرد: لپ‌تاپی که فایل‌های .env عملیاتی در یک پوشه بالاتر داشت، یک رشته گفتگو در Slack حاوی شناسه‌های مشتری و تب باز یک مدل عمومی که حاوی گزارش خطاهای (Stack Trace) دیروز بود.

عامل چیزی تولید کرده بود که در ویرایشگر کامپایل می‌شد، اما جفت‌برنامه‌نویسان قبل از اینکه کسی دکمه Apply را فشار دهد، تغییرات (Diff) را در یک فایل موقت متوقف کردند. این فایل دیگر یک کاندید برای ادغام (Merge) نبود؛ بلکه یک مدرک بود. پیش‌نویس فایل proposed-retry.js سه شکست بحرانی را افشا کرد:

  • تورم وابستگی‌ها: عامل کتابخانه async-retry را وارد کرده بود، بسته‌ای که در فایل package-lock.json پروژه لیست نشده بود.
  • مدیریت نادرست اسرار: کد سعی داشت به process.env.WEBHOOK_SIGNING_KEY دسترسی پیدا کند؛ یک کلید محیطی جدید که هندلر وب‌هوک هرگز مالک آن نبود.
  • نشت اطلاعات شناسایی شخصی (PII): عامل دستور console.log('webhook payload', payload) را اضافه کرده بود که منجر به افشای داده‌های حساس مشتریان در لاگ‌های جفت‌برنامه‌نویسی می‌شد.

سه بن‌بست در ادغام هوش مصنوعی

این تیم سه روش رایج استفاده از AI را بررسی کردند و هر سه را به دلایل امنیتی رد کردند. مهندس ارشد ابتدا سه محدودیت را روی تخته نوشت: هیچ وابستگی جدیدی نباشد، هیچ کلید محیطی جدیدی اضافه نشود و هیچ محموله‌ای (Payload) در لاگ‌ها چاپ نشود.

بن‌بست اول: پنجره چت
آن‌ها بررسی کردند که آیا deliverWebhook و فیکچر و خطای عملیاتی را در یک چت مرورگر کپی کنند تا بپرسند آیا این تابع کمکی ایمن است یا خیر. مهندس ارشد مانع از این کار شد. پنجره‌های چت قرارداد مشخصی برای حفظ داده‌ها (Retention Contract) ندارند. گزارش خطا (Stack Trace) از قبل حاوی یک شناسه فروشنده بود. علاوه بر این، وارد کردن نام یک بسته در یک چت عمومی می‌توانست در صورت نشت تاریخچه، حملات کپی‌برداری از lockfile را تسهیل کند. آن‌ها قانونی وضع کردند: دیف‌های جفت‌برنامه‌نویسی که به اسرار، محموله‌های مشتری یا شکاف‌های lockfile اشاره دارند، نباید از طریق یک جعبه چت مصرف‌کننده از میز کار خارج شوند. مدلی که نمی‌تواند دیف را ببیند، فقط «ناکارآمد» است؛ اما مدلی که دیف را نگه می‌دارد، یک «حادثه امنیتی» است.

بن‌بست دوم: لپ‌تاپ جفت‌برنامه‌نویسی
آن‌ها در نظر داشتند یک مدل کدنویسی محلی را روی همان ماشینی اجرا کنند که Slack، مدیریت رمزها و کلونِ پروژه Checkout روی آن بود. این ایده شکست خورد زیرا لپ‌تاپ یک سطح برای گفتگو است، نه یک میزبان ارزیابی (Eval Host). کوکی‌های مرورگر، عامل‌های SSH و فایل‌های .env تنها یک دستور ls با یک حلقه فراخوانی ابزار (Tool-calling loop) فاصله دارند. گفتگو به تاریخچه نیاز دارد، اما ارزیابی به ماشینی نیاز دارد که جفت‌برنامه‌نویسان بتوانند آن را بدون از دست دادن ایمیل‌های بعدازظهر خاموش کنند. در اینجا مالکیت داده بر سرعت استنتاج (Inference) اولویت داشت و آن‌ها استنتاج روی لپ‌تاپ را بدون بنچ‌مارک کردن حتی یک توکن رد کردند.

بن‌بست سوم: اصلاح تا رسیدن به تست سبز
آن‌ها بررسی کردند که آیا اجازه دهند عامل در یک حلقه علیه فایل تست موجود عمل کند تا زمانی که مجموعه تست‌ها سبز شوند. اما مجموعه تست‌ها فقط کدهای وضعیت HTTP را بررسی می‌کردند. آن‌ها لاگ‌ها، تغییرات lockfile یا کلیدهای محیطی جدید را تست نمی‌کردند. تست‌های سبز، نشت داده‌ها را پنهان می‌کردند. مهندس ارشد این وضعیت را «موفقیت کاذب در جفت‌برنامه‌نویسی» نامید. این چرخه‌ی تکرار بی‌هدف برای رسیدن به تست سبز، دقیقاً مشابه همان الگویی است که در تحلیل ریشهٔ ایجاد حلقه‌های تکرار در ابزارهای AI هنگام مواجهه با خطاهای HTTP بررسی کردیم.

دروازه تخته‌سفید مهندس ارشد

قبل از اینکه هر توکن از راه دور جابجا شود، مهندس ارشد ۵ سؤال مشخص پرسید که پاسخ آن‌ها باید در یک فایل تایپ می‌شد:
۱. دقیقاً کدام شکست باید بعد از اعمال این تابع کمکی تغییر کند؟
۲. کدام فراخوان‌های موجود باید امضای تابع (Function Signature) را حفظ کنند؟
۳. مدل در کجا دیف را پردازش می‌کند و چه کسی می‌تواند آن میزبان را در ۵ دقیقه حذف کند؟
۴. مدل اجازه ذکر کدام فایل‌ها (از جمله .env و lockfile) را ندارد؟
۵. فیکچر (Fixture) را چه کسی نوشت؛ عامل یا جفت‌برنامه‌نویسان؟

مهندس میان‌رده به دو سؤال اول از روی تیکت باگ پاسخ داد. پاسخ سؤال سوم خالی بود، برای چهارم شانه بالا انداخت و پاسخ پنجم «عامل» بود. مهندس ارشد پاسخ پنجم را به عنوان یک شکست در دروازه ورود در نظر گرفت، نه یک نکته استایلی. آن‌ها خودشان فیکچر را بازنویسی کردند تا مدل یک ساختار سانسورشده ببیند، نه هندلر عملیاتی.

پیاده‌سازی Shape Gate

برای حل این مشکل، آن‌ها Shape Gate را توسعه دادند؛ یک کیت ارزیابی سبک که اگر پاسخ مدل قوانین انسانی (Human Invariants) را نقض کند، خروجی را رد می‌کند. این رویکرد ساختاریافته برای جلوگیری از خطاهای رایج، یادآور استفاده از SOPهای مستند در ویکی برای کاهش نرخ شکست وصله‌های تولید شده توسط AI است. آن‌ها فایلی به نام pairing-fixture.json برای تعریف مرزها ساختند:

  • هویت تابع: functionName روی deliverWebhook تنظیم شد.
  • حفظ امضا: mustKeepSignature شامل url و payload و secret شد.
  • واردات ممنوعه: بسته‌های async-retry و p-retry و got برای جلوگیری از تغییر در lockfile صراحتاً ممنوع شدند.
  • شناسه‌های ممنوعه: استفاده از process.env و WEBHOOK_SIGNING_KEY و console.log برای جلوگیری از نشت اسرار و لاگ کردن PII ممنوع شد.
  • رفتار الزامی: تلاش مجدد در صورت عدم دریافت کد 2xx، استفاده از آرگومان secret برای امضا (و نه یک کلید محیطی جدید) و عدم لاگ کردن محموله.
  • زمینه (Context): ذکر شد که محموله حاوی PII است و lockfile برای این اسپرینت منجمد شده است.

آن‌ها از یک میزبان ارزیابی یک‌بارمصرف توسط MonkeyCode استفاده کردند تا اسکریپت pairing-eval.mjs را اجرا کنند. دسترسی رایگان به مدل و گزینه سرور رایگان MonkeyCode به عنوان یک سطح ارزیابی دورریز استفاده شد: میزبانی که جفت‌برنامه‌نویسان می‌توانستند آن را ایمیج کنند، اسکریپت را اجرا کنند و بدون دست زدن به کلون پروژه، آن را حذف کنند. آن‌ها این کار را به عنوان یک آزمایشگاه بنچ‌مارک در نظر نگرفتند و توکن‌ها یا سخت‌افزار را در تیکت ثبت نکردند. تیکت فقط قوانین تخته‌سفید و مسیر فایل pairing-fixture.json را ثبت کرد.

اسکریپت، فیکچر و پیش‌نویس منجمد را می‌خواند و تکمیل کد را به عنوان متن امتیازدهی می‌کند. این اسکریپت از هیچ حلقه ابزاری (Tool loop) استفاده نمی‌کند و هیچ نوشتی در مخزن انجام نمی‌دهد. برای اجرای آن، جفت‌برنامه‌نویسان از متغیرهای محیطی خاصی استفاده کردند تا کلیدها خارج از مخزن بمانند:

export MODEL_BASE_URL="http://127.0.0.1:8080/v1"
export MODEL_API_KEY="$MODEL_API_KEY"
export MODEL_NAME="$MODEL_NAME"
node pairing-eval.mjs proposed-retry.js

نتیجه نهایی تحت هدایت انسان

اولین اجرای Shape Gate در هر سه قانون تخته‌سفید شکست خورد. این شکست، مفیدترین خروجی بود. پیش‌نویس عامل از جفت‌برنامه‌نویسی جان سالم به در نبرد. کد نهایی که ادغام شد، کوتاه‌تر از پیش‌نهاد AI بود: یک حلقه for ساده برای تلاش مجدد با سقف سخت ۳ بار، حفظ امضای اصلی تابع و لاگ کردنِ صرفاً کدهای وضعیت.

export async function deliverWebhook(url, payload, secret) {
  const body = JSON.stringify(payload);
  let lastError;
  for (let attempt = 1; attempt <= 3; attempt += 1) {
    const res = await fetch(url, {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
        'x-signature': secret,
      },
      body,
    });
    if (res.ok) return res.json();
    lastError = new Error(`webhook status ${res.status} attempt ${attempt}`);
    await new Promise((r) => setTimeout(r, 200 * attempt));
  }
  throw lastError;
}

در نهایت، Shape Gate پاس شد و تست‌های اصلی کد وضعیت همچنان موفق بودند. مهندس ارشد یک الزام نهایی اضافه کرد: یک تست جاسوسی (Spy Test) که تأیید می‌کرد console.log هرگز محموله را دریافت نمی‌کند. این تست محصول تفکر جفت‌برنامه‌نویسان بود، نه محصول مدل.

محدودیت‌ها و کاربرد

باید دانست که Shape Gate یک فیلتر متنی است. این ابزار واردات مبهم (Obfuscated)، جست‌وجوهای پویا در محیط یا لاگرهایی که در توابع کمکی پیچیده شده‌اند را تشخیص نمی‌دهد. همچنین ممکن است وصله‌ای معتبر را که در یک کامنت به یک شناسه ممنوعه اشاره کرده است، رد کند. جفت‌برنامه‌نویسان این حالت‌های شکست را پذیرفتند زیرا این دروازه در مقابل بررسی انسانی قرار دارد، نه به جای آن.

چه کسانی نباید از این گردش‌کار استفاده کنند:

  • دیف‌های عمومی: وقتی دیف از قبل عمومی است و حاوی داده‌های مشتری نیست (مثلاً غلط املایی در README)، مسیر میزبان ارزیابی را رد کنید.
  • پارسرهای تولیدشده: وقتی تغییرات شامل یک پارسر تولیدشده است که شناسه‌های ثابتی برای ممنوع کردن ندارد، Shape Gate را رد کنید.
  • بازگشت‌های اضطراری: وقتی در یک حادثه On-call نیاز به یک بازگشت (Revert) تک‌خطی سریع است، نه یک تابع کمکی برای تلاش مجدد، انجماد جفت‌برنامه‌نویسی را رد کنید.
  • پلتفرم‌های تکامل‌یافته: مهندسان ارشد (Staff Engineers) با رانرهای CI ایزوله و اسکنرهای خودکار اسرار ممکن است این کیت را زائد بدانند.

این رویکرد نشان می‌دهد ارزش واقعی AI در تیم‌های تحت هدایت مهندسان ارشد، نه در سرعت، بلکه در توانایی تست کردن یک پیشنهاد در برابر یک مرز سخت و نوشته شده توسط انسان است. ادعاهای حساس به زمان درباره رتبه‌بندی مدل‌ها یا امتیازات لیدربوردهای عمومی در تیکت ذکر نشد. این جلسه اندازه‌گیری کرد که آیا یک پیش‌نویس خاص، تخته‌سفیدی را که جفت‌برنامه‌نویسان بعد از ناهار هنوز می‌توانستند بخوانند، نقض می‌کند یا خیر. برای تیم‌هایی که نمی‌توانند در ۱۰ دقیقه یک pairing-fixture.json بنویسند، عامل‌های AI احتمالاً به تولید حلقه‌های مبهم و ریسکی ادامه خواهند داد که بدهی فنی را زیر پوششی از تست‌های «سبز» پنهان می‌کنند.

چرا این موضوع مهم است؟

این رویکرد بر اساس تجربه عملی نشان می‌دهد که تکیه بر بنچمارک‌های عمومی برای پذیرش AI در تولید، خطرناک است. اعتبار سیستم‌های عملیاتی باید بر پایه «حفاظ‌های انسانی» (Human Guardrails) باشد، نه صرفاً اجرای بدون خطای کد.

تأثیر برای ایران

برنامه‌نویسان ایرانی که در پروژه‌های حساس یا دورکاری بین‌المللی فعالیت می‌کنند، می‌توانند با پیاده‌سازی این فیلترها، ریسک نشت داده‌های مشتریان را در استفاده از مدل‌های ابری کاهش دهند.

·نگاه ما
تحریریه دات‌هوش

ارزش واقعی عامل‌های هوش مصنوعی در محیط‌های عملیاتی، نه در توانایی تولید کد، بلکه در قابلیت تبدیل شدن به «پیش‌نویس‌زن» است که باید از فیلترهای سخت انسانی عبور کند. این رویکرد پارادایم را از «اعتماد به خروجی مدل» به «اعتبارسنجی خروجی مدل در برابر ناورداهای انسانی» تغییر می‌دهد. در واقع، Shape Gate یک لایه دفاعی برای جلوگیری از تبدیل شدن سرعتِ تولید کد به سرعتِ تولید بدهی فنی و امنیتی است.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.