سرفصلهای مقاله
دادن دسترسی مستقیم اجرای کوئری SQL به یک مدل زبانی بزرگ (LLM)، کوتاهترین مسیر برای نشت اطلاعات مشتریان یا قفل شدن جداول پروداکشن است. مهندسانی که در موج اول ساخت دستیارهای هوشمند، رشتههای اتصال دیتابیس را در اختیار کدهای تولیدشده توسط هوش مصنوعی (Text-to-SQL) قرار دادند، خیلی زود با حملات Prompt Injection، کوئریهای بدون ایندکسِ کشنده و دسترسی غیرمجاز بینمستاجری (Cross-tenant Data Leakage) روبهرو شدند. پیادهسازی اتصال امن هوش مصنوعی به دیتابیس با mcp (پروتکل زمینه مدل) به ما اجازه میدهد به جای باز گذاشتن دروازه پایگاهداده، یک لایه قراردادی سختگیرانه، قابل ممیزی و کاملاً مهارشده بین عامل هوشمند و دادههای حساس سازمان ایجاد کنیم.
چرا اتصال مستقیم LLM به پایگاه داده (Text-to-SQL) یک حفره امنیتی است؟
مدلهای زبانی ذاتاً غیردترمینستیک هستند و هیچ درک ذاتی از مرزهای امنیتی سطری یا هزینه اجرای یک Execution Plan در PostgreSQL ندارند. وقتی از الگوی سنتی Text-to-SQL استفاده میکنید، سه ریسک بزرگ معماری شما را تهدید میکند:
- دور زدن منطق دسترسی برنامه (Application-level RBAC): در اکثر وباپلیکیشنها، کنترل دسترسی و جداسازی دادههای مشتریان (Tenant Isolation) در لایه ORM یا سرویسهای بکاند پیادهسازی شده است، نه در سطح کاربران دیتابیس. اگر کاربر با یک پرامپت دستکاریشده مدل را فریب دهد تا شرط
WHERE organization_id = Xرا حذف کند، کل دادههای رقبا افشا میشود. - حملات Denial of Service ناخواسته: مدل زبانی ممکن است برای پاسخ به یک سوال ساده تحلیلی، یک
CROSS JOINروی سه جدول میلیونی بدون ایندکس بنویسد که CPU سرور دیتابیس را به ۱۰۰ درصد رسانده و کل سرویس پروداکشن را از دسترس خارج کند. - نشت ساختار داخلی و دادههای حساس: قرار دادن نام جداول و ستونهای داخلی در کانتکست مدل، سطح حمله را به شدت افزایش میدهد.
معماری لایه ابزارها در سرورهای Model Context Protocol (MCP)
پروتکل MCP به جای اینکه اجازه دهد هوش مصنوعی کد دلخواه خود را روی دیتابیس اجرا کند، دسترسی به داده را به مجموعهای از «ابزارهای از پیش تعریفشده» (Deterministic Tools) با ورودیهای اعتبارسنجیشده محدود میکند. در معماری استودیو سجاد، ما تمام مجموعههای داده را در سه دسته صریح طبقهبندی میکنیم:
- AGENT_SURFACE: مجموعههایی که عامل هوشمند فقط به فیلدهای مشخصشده در لیست سفید (Allow-list) آنها دسترسی دارد و روی فیلدهای حساسشان ماسکگذاری خودکار (Redaction) اعمال میشود.
- AGENT_NEVER: جداولی که تحت هیچ شرایطی و با هیچ اسکوپی قابل دسترسی نیستند؛ از جمله کلیدهای امنیتی (
agent-keys)، نشستهای کاربری (auth-sessions)، تراکنشهای مالی مستقیم و پیامهای خصوصی رمزنگاریشده. - AGENT_DEFERRED: جداولی که تا زمان تعریف قرارداد دقیق فیلدها، به صورت پیشفرض مسدود هستند.
عامل هوشمند دیگر اسکیمای دیتابیس را نمیبیند؛ بلکه فقط کاتالوگی از توابع مجاز با قراردادهای دقیق تایپشده با Zod را دریافت میکند:
// تعریف یک ابزار امن در سرور MCP با اعتبارسنجی سختگیرانه
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { z } from 'zod'
import { db } from '@/db'
import { invoices } from '@/db/schema'
import { and, eq, gte, lte } from 'drizzle-orm'
const server = new McpServer({ name: 'finance-mcp-gateway', version: '1.0.0' })
server.tool(
'get_tenant_invoices',
'واکشی لیست فاکتورهای یک سازمان در بازه زمانی مشخص با سقف تعداد محدود',
{
status: z.enum(['paid', 'pending', 'overdue']),
fromDate: z.string().datetime(),
toDate: z.string().datetime(),
limit: z.number().int().min(1).max(50).default(20),
},
async ({ status, fromDate, toDate, limit }, { authInfo }) => {
// استخراج شناسه سازمان از توکن امنیتی، نه از ورودی قابل دستکاری LLM!
const tenantId = authInfo.tenantId
if (!tenantId) throw new Error('Unauthorized context')
const results = await db
.select({
id: invoices.id,
amount: invoices.amount,
dueDate: invoices.dueDate,
status: invoices.status,
})
.from(invoices)
.where(
and(
eq(invoices.tenantId, tenantId),
eq(invoices.status, status),
gte(invoices.createdAt, new Date(fromDate)),
lte(invoices.createdAt, new Date(toDate))
)
)
.limit(limit)
return {
content: [{ type: 'text', text: JSON.stringify(results) }],
}
}
)
نکته حیاتی در کد بالا این است که tenantId هرگز به عنوان پارامتر ورودی از LLM دریافت نمیشود، بلکه مستقیماً از Context احراز هویتِ نشست فعلی استخراج و به کوئری تزریق میگردد.
پیادهسازی کلیدهای دسترسی محدود (Scoped Keys) و کنترل مصرف توکن (Metering)
عاملهای هوش مصنوعی میتوانند در یک حلقه معیوب (Agentic Loop) گیر بیفتند و در عرض چند دقیقه هزاران بار یک ابزار MCP را فراخوانی کنند. در زیرساخت Agent API ما، هر کلید با الگوی ak_<prefix>_<secret> صادر میشود، تنها هش SHA-256 آن در دیتابیس ذخیره میگردد و در زمان احراز هویت با مقایسه زمانثابت بررسی میشود.
علاوه بر این، هر ابزار هزینه مشخصی به واحد (Unit Cost) دارد؛ برای مثال خواندن لیستها ۱ واحد، ساخت پیشنویس ۳ واحد و تایید محتوا ۵ واحد مصرف میکند. پیش از اجرای هر ابزار، مصرف ماهانه کلید از جدول agent-usage بررسی شده و در صورت عبور از سقف ماهانه (monthlyUnitLimit) با کد خطای ساختاریافته quota_exceeded متوقف میشود.
ماسکگذاری دادههای ورودی کاربران و مقابله با Prompt Injection غیرمستقیم
وقتی یک عامل هوشمند پیامهای فرم تماس یا تیکتهای ورودی را میخواند، متن نوشتهشده توسط کاربران ناشناس ممکن است حاوی دستورات مخرب برای فریب دادن مدل باشد. به همین دلیل در لایه shapeForAgent، علاوه بر ماسک کردن شماره تماس و ایمیل و کوتاه کردن متن به ۶۰۰ کاراکتر، برچسب _untrusted به خروجی الصاق میشود تا مدل بداند این فیلدها صرفاً داده هستند و هرگز نباید به عنوان دستورالعمل اجرا شوند.
در استودیو سجاد، ما سرورهای اختصاصی MCP، دروازههای امن داده و زیرساختهای هوش مصنوعی سازمانی را با بالاترین استانداردهای امنیتی طراحی و پیادهسازی میکنیم. برای بررسی نیازمندیهای فنی و ادغام امن AI در پلتفرم خود، به صفحه خدمات استودیو سجاد مراجعه کنید.