AI agent سے API keys کیسے محفوظ رکھیں؟
API key agent کے environment میں ہو تو ایک tool call میں leak ہو سکتی ہے۔ اصل key کے بجائے credential gateway کے پیچھے محدود مدت والا scoped token دیں۔
AI agents سے راز پوشیدہ رکھنے کا مطلب
AI agent ایک عام Linux process ہے جو commands چلاتا ہے۔ اس process میں موجود ہر environment variable اس کے چلائے گئے code کے لیے قابلِ مطالعہ ہوتا ہے، اس لیے agent کے environment میں موجود API key ایسی key ہے جسے agent کسی بھی قابلِ رسائی host کو بھیج سکتا ہے۔ agent سے secrets باہر رکھنے کا مطلب اسے key کے بجائے ایک handle دینا ہے: محدود مدت والا scoped token، یا ایسا placeholder جسے network boundary پر کوئی دوسرا نظام اصل value سے تبدیل کر دے۔
یہ کسی model کے hostile ہو جانے کی کہانی نہیں ہے۔ طریقۂ کار اس سے کہیں زیادہ سادہ ہے۔ agent ایسی web page، README، یا issue comment پڑھتا ہے جس میں instructions موجود ہوتی ہیں، اور ان پر عمل کرتا ہے، کیونکہ language model کے لیے آپ کے لکھے ہوئے متن اور اس کے حاصل کردہ متن میں کوئی فرق نہیں ہوتا۔ اسے prompt injection کہتے ہیں۔ یہ واقعہ پیش آنے کے بعد نقصان کی حد صرف ایک چیز سے متعین ہوتی ہے: process کیا کچھ پڑھ سکتا ہے۔ اگر آپ نے ابھی boundary متعین نہیں کی، تو server پر coding agent کو محفوظ طریقے سے چلانا ان isolation levels کی وضاحت کرتا ہے جن پر یہ guide مبنی ہے۔
سادہ الفاظ میں خطرے کا ماڈل
اسے اسی صارف کے طور پر چلائیں جس کے طور پر آپ کا agent چلتا ہے۔
tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'اس کی پرنٹ کی جانے والی ہر سطر کسی اجنبی کے سرور کو بھیجی جانے والی ایک HTTP درخواست کے فاصلے پر ہے۔ اب دیکھیں کہ agent کے قریب ڈسک پر کیا موجود ہے۔
grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'shell رکھنے والے agent کو اس ڈیٹا کو باہر منتقل کرنے کے لیے کسی پیچیدہ exploit کی ضرورت نہیں ہوتی۔ چار عام طریقے کافی ہیں، اور لاگ میں چاروں معمول کے کام جیسے دکھائی دیتے ہیں:
- کسی بھی host کو outbound
curlیاfetch، جس میں value query string میں ہو۔ - کسی ایسے repository کو
git commitاورgit push، جس میں agent لکھ سکتا ہو۔ - package install script، جو agent کے صارف کے طور پر من مانی code چلاتی ہے۔
- ایسے hostname کا DNS lookup جس میں value شامل ہو؛ یہ اس وقت بھی باہر نکل جاتا ہے جب HTTP egress مسدود ہو۔
آپ صرف جائزہ لیتے رہ کر اس خطرے سے نہیں بچ سکتے۔ حل یہ ہے کہ agent کی رسائی میں کوئی قیمتی چیز موجود نہ ہو۔
ورکنگ ٹری میں موجود راز context window میں بھی راز ہوتا ہے
ایک agent فائلیں پڑھتا ہے۔ جس repository میں agent کام کر رہا ہو، وہاں موجود .env فائل پڑھی جائے گی۔ فائل پڑھے جانے کے بعد وہ context window میں شامل ہو جاتی ہے۔ اس کا مطلب ہے کہ وہ transcript، آپ کے محفوظ کردہ کسی بھی log، اور agent کی اگلی تحریر میں موجود ہوگی۔
پہلے، جب key اس tree میں موجود تھی جس میں agent کام کرتا ہے:
cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billingبعد میں، جب فائل کو agent کی رسائی سے باہر منتقل کر دیا گیا:
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اب agent کا صارف فائل نہیں کھول سکتا، کیونکہ working tree میں وہ فائل موجود نہیں ہے۔ agent کی اپنی config میں موجود deny rules تحفظ کی دوسری تہہ ہیں، پہلی نہیں۔ Claude Code project میں .claude/settings.json سے permission rules پڑھتا ہے:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
}
}اس سے agent کے exploration کے دوران فائل کھولنے کی ایماندارانہ غلطی رک جاتی ہے۔ لیکن یہ کسی injected instruction کو base64 .env چلانے سے نہیں روکتا، کیونکہ یہ shell command ہے، file read نہیں۔ config کو حفاظتی رکاوٹ سمجھیں، اور filesystem permission کو حقیقی حد۔ یہی تقسیم containers کے اندر بھی لاگو ہوتی ہے: Docker Compose میں env files اور secrets مسئلے کے اس ورژن کو ایک تہہ نیچے بیان کرتا ہے۔
ہر agent کے لیے اپنا غیر مراعات یافتہ user مقرر کریں
اگر agent آپ کے user کے طور پر چلتا ہے تو اسے آپ کی SSH keys، cloud credentials اور shell history بھی حاصل ہو جاتی ہے۔ الگ user بنانے کے لیے ایک command کافی ہے اور یہ تمام رسائی ختم ہو جاتی ہے۔
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 کے ساتھ ناکام ہونا چاہیے۔ اگر اس کے بجائے یہ key دکھائے تو آپ کی home directory group یا world کے لیے readable ہے، اور chmod 700 ~ اسے درست کرتا ہے۔ agent user کو sudo میں شامل نہ کریں، اور اسے NOPASSWD کا ایسا rule نہ دیں جو اس ایک command سے زیادہ وسیع ہو جس کی اسے واقعی ضرورت ہے۔ VPS پر کم سے کم مراعات والے users میں group اور sudoers کی تفصیل بیان کی گئی ہے۔
cloud VPS پر ایک اور حد مقرر کرنا بھی ضروری ہے۔ instance metadata service ایک مقررہ link local address پر جواب دیتی ہے، اور اکثر درخواست کرنے والے ہر عمل کو role credentials فراہم کر دیتی ہے۔
sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECTاسے agent کے جانب سے چیک کریں۔ sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ کو کچھ بھی print نہیں کرنا چاہیے اور non zero کے ساتھ exit ہونا چاہیے، کیونکہ packet box سے باہر جانے سے پہلے ہی رد کر دیا جاتا ہے۔
سرحد پر اسناد داخل کریں
اس مسئلے کو حقیقتاً حل کرنے والا طریقہ اسناد داخل کرنا ہے۔ ایجنٹ کے پاس کبھی اصل key نہیں ہوتی۔ وہ اپنی درخواست ایک مقامی gateway کے ذریعے بھیجتا ہے، اور gateway باہر بھیجتے وقت placeholder کو اصل secret سے بدل دیتا ہے۔ secret gateway کی storage میں، ایک مختلف process کے اندر، ایک مختلف user کی ملکیت میں محفوظ رہتا ہے۔
OneCLI اس طریقے کی ایک open source implementation ہے، جو Apache-2.0 کے تحت licensed ہے، اور agent کے ساتھ ایک container کے طور پر چلتی ہے۔ July 2026 تک project اس setup کو دستاویز کرتا ہے:
git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --waitdashboard port 10254 پر اور gateway port 10255 پر سنتے ہیں۔ آپ اصل credential ایک بار محفوظ کرتے ہیں، پھر ہر agent کو key کی جگہ ایک placeholder value اور اپنا محدود دائرۂ اختیار رکھنے والا access token دیتے ہیں۔ agent یہ token Proxy-Authorization header میں بھیجتا ہے۔ gateway host اور path کی بنیاد پر outbound request سے مطابقت رکھنے والی credential تلاش کرتا ہے، متعلقہ credential کو decrypt کرتا ہے، اور اسے placeholder کی جگہ رکھ دیتا ہے۔ agent کے environment میں چوری کے قابل کچھ بھی موجود نہیں رہتا۔
یہاں اہم چیز encryption نہیں ہے۔ اہم بات یہ ہے کہ سوال "اس agent نے کیا استعمال کیا، اور کب" ایک log query بن جاتا ہے۔ آپ یہ اندازہ لگانے کے بجائے کہ چھ میں سے کس environment میں key کی copy موجود تھی، ایک audit trail پڑھتے ہیں۔
راز ماحول کے بجائے عمل کو دیں
اگر آپ agent کو systemd کے تحت چلاتے ہیں تو آپ کو ماحول کے متغیرات کی بالکل ضرورت نہیں۔ LoadCredential= راز کو ایک نجی ڈائریکٹری میں رکھتا ہے جسے صرف وہ سروس پڑھ سکتی ہے۔ یونٹ فائل میں یہ %d کے طور پر اور عمل کے اندر $CREDENTIALS_DIRECTORY کے طور پر ظاہر ہوتا ہے۔ یہ قدر کبھی /proc/<pid>/environ میں ظاہر نہیں ہوتی، اس لیے ps eww اسے نہیں دکھا سکتا۔ سروس رکنے پر ڈائریکٹری بھی ختم ہو جاتی ہے۔
پہلے credential کو مشین کے لیے encrypt کریں۔ یہ کمانڈز 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 دکھاتی ہے۔ اس سے ثابت ہوتا ہے کہ encrypted فائل اس host پر decrypt ہو جاتی ہے۔ پھر اسے یونٹ میں refer کریں:
[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 code $AGENT_KEY_FILE پر موجود فائل کھولتا ہے۔ فائل پڑھنے کا عمل صرف ایک لمحے تک رہتا ہے۔ ماحول کا متغیر عمل کے پورے دورانیے تک موجود رہتا ہے اور اس کے شروع کیے گئے ہر child میں بھی موجود ہوتا ہے۔
مختصر مدت کے ٹوکنز کو طویل مدت کی keys پر ترجیح دیں
جو key کبھی ختم نہیں ہوتی، وہ کئی ماہ بعد log یا transcript میں ظاہر ہونے پر بھی معتبر رہتی ہے۔ اگر service session token فراہم کرتی ہے تو session token استعمال کریں اور اس کی مدت وہ کم ترین وقت مقرر کریں جو کام کے لیے کافی ہو۔
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/agent-readonly \
--role-session-name agent-review \
--duration-seconds 900AWS STS (security token service) کم از کم 15 منٹ قبول کرتا ہے، اور یہ عموماً ایک agent task کے لیے کافی ہوتا ہے۔ GitHub کے لیے agent user کو اپنا gh login دیں اور اسے fine grained token کے ساتھ صرف اسی repository تک محدود کریں جس پر وہ کام کرتا ہے، تاکہ اس session کے اندر gh auth token ایسی چیز واپس کرے جو کسی دوسری چیز تک رسائی نہ دے سکے۔ پہلے resource کے مطابق دائرہ محدود کریں، پھر وقت کے مطابق۔
تصدیق کریں، پھر مسلسل تصدیق کرتے رہیں
کسی agent کے سیٹ اپ میں تبدیلی کے بعد تین جانچیں چلانا ضروری ہے۔ انہیں اپنے طور پر نہیں، بلکہ agent کے user کے طور پر چلائیں۔
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 پرنٹ کرنا چاہیے۔ تیسری جانچ بتاتی ہے کہ agent کا network path کون سی شناخت پیش کرتا ہے۔ gateway pattern کا مقصد اسی سوال کا جواب دینا ہے: 401 کا مطلب ہے کہ agent کے پاس اپنی کوئی GitHub credential نہیں ہے، جبکہ 200 کا مطلب ہے کہ اس کے پاس ایک credential ہے؛ اس لیے آپ کو معلوم ہونا چاہیے کہ وہ کون سا token ہے۔ اگر آپ agents کو unattended چلاتے ہیں تو VPS پر AI agent کے اخراجات کو کنٹرول کرنا ان access limits کے ساتھ موزوں budget limits کا احاطہ کرتا ہے۔
FAQ
کیا میں صرف یہ اعتماد کر سکتا ہوں کہ model میری keys افشا نہیں کرے گا؟
نہیں، کیونکہ اس threat model میں حملہ آور model نہیں ہے۔ agent ویب صفحات، repositories اور issue trackers سے text پڑھتا ہے، اور اس text میں instructions شامل ہو سکتی ہیں۔ model کے پاس آپ کی instructions اور حاصل کیے گئے text میں قابلِ اعتماد فرق کرنے کا کوئی طریقہ نہیں ہے۔ model کے درست انتخاب پر منحصر ہر control پہلی بار کسی injected instruction کے قائل کن ہونے پر ناکام ہو جاتا ہے۔ اس لیے control operating system یا network میں ہونا چاہیے۔
کیا agent کے secrets کے لیے environment variables واقعی اتنے خطرناک ہیں؟
یہ ایک مخصوص وجہ سے خطرناک ہیں: یہ inherited ہوتے ہیں۔ agent جس بھی child process کو چلاتا ہے، اسے ان کی copy مل جاتی ہے۔ اس میں build script، test runner اور package install hook بھی شامل ہیں۔ اسی user کے ذریعے variables /proc/<pid>/environ سے بھی پڑھے جا سکتے ہیں۔ اس لیے agent کی چلائی ہوئی کوئی بھی چیز انہیں agent کے آگے بھیجے بغیر پڑھ سکتی ہے۔ استعمال کے وقت پڑھی جانے والی file، LoadCredential= یا gateway کے ذریعے، exposure کو اسی وقت تک محدود رکھتی ہے۔
کیا secrets کو vault میں رکھنے سے یہ مسئلہ خود حل ہو جاتا ہے؟
صرف جزوی طور پر۔ vault storage کا مسئلہ حل کرتا ہے۔ یہ آخری مرحلہ حل نہیں کرتا، جس میں کوئی چیز secret کو vault سے نکال کر agent کو environment variable کے طور پر دیتی ہے۔ اس طرح آپ دوبارہ اسی صورتِ حال میں پہنچ جاتے ہیں۔ اہم بات یہ ہے کہ substitution کون کرتا ہے۔ اگر agent secret حاصل کرتا ہے تو secret agent کے پاس ہے۔ اگر gateway یا init system agent کے process سے باہر substitution کرے تو agent کے پاس secret کبھی نہیں آتا۔
مجھے کیسے معلوم ہوگا کہ agent پہلے ہی کچھ افشا کر چکا ہے؟
عام طور پر بعد میں اس کا یقین سے پتا نہیں چل سکتا۔ یہی gateway کے حق میں دلیل ہے۔ اس کے بغیر آپ کا ثبوت shell history، agent کے transcript اور outbound connection logs میں بکھرا ہوتا ہے، اور غالباً آپ یہ logs رکھ بھی نہیں رہے ہوتے۔ credential gateway کے ساتھ credential کا ہر استعمال agent identity اور timestamp سمیت ایک line ہوتا ہے۔ اگر آپ کو leak کا شبہ ہو تو پہلے key rotate کریں اور بعد میں investigation کریں۔ Rotation سستا ہے، یقین نہیں۔
مجھے آج کم از کم کیا کرنا چاہیے؟
ہر .env file کو ان directories سے باہر منتقل کریں جہاں آپ کے agents کام کرتے ہیں، اور ہر agent کے لیے ایک unprivileged user بنائیں۔ ان دونوں تبدیلیوں میں تقریباً 10 منٹ لگتے ہیں اور یہ عام ترین راستہ بند کر دیتی ہیں۔ یہ راستہ ایسا agent ہوتا ہے جو credential file پڑھ لیتا ہے، حالانکہ اس file کو code کے ساتھ رکھنے کی کوئی وجہ نہیں تھی۔ gateway اور short lived tokens اگلا مرحلہ ہیں، پہلا نہیں۔ یہی ابتدائی طریقہ کسی بھی agent runtime پر لاگو ہوتا ہے، جس میں VPS پر autonomous agent کو محفوظ طریقے سے چلانا بھی شامل ہے۔