SSD Nodes Learn 8GB RAM — $66/বছর
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-01

AI agent থেকে API key নিরাপদে দূরে রাখুন

একটি tool call-এই API key ফাঁস হতে পারে। আসল key না দিয়ে credential gateway-এর মাধ্যমে সীমিত, স্বল্পমেয়াদি token ব্যবহার করে ঝুঁকি কমান।

AI agent থেকে গোপন তথ্য দূরে রাখার অর্থ

একটি AI agent হলো একটি সাধারণ Linux process, যা command চালায়। ওই process-এর কাছে থাকা প্রতিটি environment variable তার চালানো code পড়তে পারে। তাই agent-এর environment-এ থাকা API key এমন একটি key, যা agent তার নাগালের যেকোনো host-এ পাঠাতে পারে। Agent থেকে গোপন তথ্য দূরে রাখার অর্থ হলো তাকে key না দিয়ে একটি handle দেওয়া: স্বল্পমেয়াদি সীমাবদ্ধ token, অথবা এমন একটি placeholder, যা network boundary-তে অন্য কোনো ব্যবস্থা আসল মান দিয়ে প্রতিস্থাপন করে।

এটি কোনো model শত্রুভাবাপন্ন হয়ে ওঠার কাহিনি নয়। প্রক্রিয়াটি আরও সরল। একটি agent এমন একটি web page, README, অথবা issue comment পড়ে যাতে নির্দেশনা থাকে, এবং সে নির্দেশনা অনুসরণ করে। কারণ language model-এর কাছে আপনার লেখা text এবং তার fetch করা text-এর মধ্যে কোনো পার্থক্য নেই। এটিই prompt injection। এটি ঘটলে ক্ষতির পরিমাণ ঠিক একটি বিষয়ের ওপর নির্ভর করে: process কী পড়তে পারে। আপনি যদি এখনও কোনো boundary নির্ধারণ না করে থাকেন, তাহলে server-এ coding agent নিরাপদে চালানো এই guide যে isolation স্তরগুলোর ওপর ভিত্তি করে তৈরি, সেগুলো ব্যাখ্যা করে।

সহজ ভাষায় হুমকির মডেল

আপনার agent যে user হিসেবে চলে, সেই user হিসেবে এটি চালান।

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

এটি যে লাইন প্রিন্ট করে, তার প্রতিটি লাইন অপরিচিত ব্যক্তির server-এ একটি HTTP request পাঠানোর সমতুল্য। এখন agent-এর কাছাকাছি disk-এ কী আছে, তা দেখুন।

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

shell-সহ একটি agent-এর ওই data বাইরে পাঠানোর জন্য কোনো চতুর exploit-এর প্রয়োজন হয় না। চারটি সাধারণ পদ্ধতিই যথেষ্ট। Log-এ চারটিকেই স্বাভাবিক কাজের মতো দেখায়:

  • যেকোনো host-এ একটি outbound curl বা fetch, যেখানে value-টি query string-এ থাকে।
  • একটি git commit এবং git push, এমন repository-তে যেখানে agent লিখতে পারে।
  • একটি package install script, যা agent-এর user হিসেবে ইচ্ছামতো code চালায়।
  • এমন একটি hostname-এর DNS lookup, যার মধ্যে value-টি থাকে। HTTP egress block করা থাকলেও এটি বাইরে চলে যায়।

শুধু review করে এই ঝুঁকি দূর করা যায় না। সমাধান হলো নিশ্চিত করা যে agent-এর নাগালের মধ্যে কোনো মূল্যবান data নেই।

working tree-এ একটি গোপন তথ্য context window-এও গোপন থাকে

একজন agent ফাইল পড়ে। যে repository-তে এটি কাজ করছে, সেখানে থাকা একটি .env ফাইল পড়া হবে। পড়ার পর সেটি context window-এ থাকে। অর্থাৎ সেটি transcript-এ, আপনার সংরক্ষিত যেকোনো log-এ এবং agent পরবর্তী সময়ে যা লিখবে তাতেও থাকবে।

আগে, agent যে tree-তে কাজ করে সেখানে key থাকা অবস্থায়:

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

ব্যবহারকারী আর ফাইলটি খুলতে পারবেন না, কারণ working tree-তে সেটি আর নেই। agent-এর নিজস্ব config-এর deny rule দ্বিতীয় স্তরের সুরক্ষা, প্রথম স্তরের নয়। Claude Code project-এর .claude/settings.json থেকে permission rule পড়ে:

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

এটি exploration করার সময় agent-এর ভুল করে কোনো ফাইল খোলার ঘটনা প্রতিরোধ করে। কিন্তু injected instruction-কে base64 .env চালানো থেকে এটি থামাতে পারে না, কারণ সেটি একটি shell command, file read নয়। config-কে guardrail এবং filesystem permission-কে প্রতিরোধী দেয়াল হিসেবে বিবেচনা করুন। একই বিভাজন container-এর ভেতরেও প্রযোজ্য: Docker Compose-এ env file এবং secret এই সমস্যার এক স্তর নিচের সংস্করণটি ব্যাখ্যা করে।

প্রত্যেক agent-এর জন্য আলাদা unprivileged user দিন

agent আপনার user হিসেবে চললে, এটি আপনার SSH keys, cloud credentials এবং shell history পেয়ে যায়। একটি আলাদা user তৈরি করতে মাত্র একটি command লাগে এবং এসব কিছু থেকে agent-কে আলাদা রাখা যায়।

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

শেষের line-টি cat: /home/you/.ssh/id_ed25519: Permission denied সহ ব্যর্থ হওয়া উচিত। এর পরিবর্তে যদি একটি key প্রিন্ট হয়, তাহলে আপনার home directory group বা world-এর জন্য readable। chmod 700 ~ এটি ঠিক করে। agent user-কে sudo-এ যোগ করবেন না এবং তার প্রয়োজনীয় একটি command-এর চেয়ে বিস্তৃত NOPASSWD rule দেবেন না। VPS-এ least privilege 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/-এর কোনো output থাকা উচিত নয় এবং এটি non-zero exit status-এ শেষ হওয়া উচিত, কারণ packet-টি box ছাড়ার আগেই rejected হয়।

সীমানায় শংসাপত্র প্রবেশ করান

এই সমস্যার কার্যকর সমাধান হলো শংসাপত্র প্রবেশ করানো। এজেন্টের কাছে কখনও আসল cryptographic key থাকে না। এটি একটি স্থানীয় gateway-এর মাধ্যমে অনুরোধ পাঠায়, আর gateway বাইরে পাঠানোর সময় একটি placeholder-এর পরিবর্তে আসল secret বসায়। Secret-টি gateway-এর storage-এ থাকে। এটি আলাদা process-এ এবং ভিন্ন user-এর অধীনে থাকে।

OneCLI এর একটি open source বাস্তবায়ন। এটি Apache-2.0 লাইসেন্সের অধীনে প্রকাশিত এবং agent-এর পাশে একটি container হিসেবে চলে। July 2026 অনুযায়ী, প্রকল্পটি এই configuration নথিভুক্ত করেছে:

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

Dashboard port 10254-এ এবং gateway port 10255-এ listen করে। আপনি একবার আসল credential সংরক্ষণ করেন। এরপর প্রতিটি agent-কে key-এর পরিবর্তে একটি placeholder value এবং তার নিজস্ব সীমাবদ্ধ access token দেন। Agent এটি একটি Proxy-Authorization header-এ পাঠায়। Gateway host ও path অনুযায়ী outbound request মিলিয়ে দেখে। এরপর মিলে যাওয়া credential decrypt করে এবং placeholder-এর পরিবর্তে সেটি বসায়। Agent-এর environment-এ চুরি করার মতো কোনো secret থাকে না।

এখানে মূল বিষয় encryption নয়। মূল বিষয় হলো, “এই agent কী ব্যবহার করেছে এবং কখন ব্যবহার করেছে”—এই প্রশ্নের উত্তর একটি log query-তে পাওয়া যায়। ছয়টি environment-এর কোনটিতে key-এর কপি ছিল তা অনুমান করার বদলে আপনি একটি audit trail পড়েন।

গোপন তথ্যটি প্রসেসের কাছে দিন, environment-এর কাছে নয়

আপনি যদি agent-টি systemd-এর অধীনে চালান, তাহলে environment variables-এর কোনো প্রয়োজন নেই। LoadCredential= গোপন তথ্যটি একটি private directory-তে রাখে, যা শুধু ওই service পড়তে পারে। Unit file-এ এটি %d হিসেবে এবং process-এর ভিতরে $CREDENTIALS_DIRECTORY হিসেবে প্রকাশিত হয়। মানটি কখনো /proc/<pid>/environ-এ দেখা যায় না। তাই ps eww এটি দেখাতে পারে না। Service বন্ধ হলে directory-টিও মুছে যায়।

প্রথমে credential-টি machine-এর জন্য encrypt করুন। এই command-গুলো systemd documentation থেকে নেওয়া এবং 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

শেষ command-টি sk-example-value প্রিন্ট করে। এতে প্রমাণ হয় যে encrypted file-টি এই host-এ decrypt করা যায়। এরপর unit থেকে এটিকে reference করুন:

[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-এ থাকা file-টি open করে। File read অল্প সময়ের জন্য থাকে। Environment variable process-এর পুরো lifetime জুড়ে থাকে এবং process যেসব child তৈরি করে, সেগুলোর প্রতিটিতেও থাকে।

দীর্ঘমেয়াদি কী-এর বদলে স্বল্পমেয়াদি টোকেন ব্যবহার করুন

যে কী-এর কখনো মেয়াদ শেষ হয় না, সেটি কয়েক মাস পরে কোনো লগ বা ট্রান্সক্রিপ্টে দেখা গেলেও তখনও বৈধ থাকে। পরিষেবা যদি সেশন টোকেন দেয়, তাহলে সেশন টোকেন ব্যবহার করুন এবং কাজের জন্য যত কম সময় যথেষ্ট, তত কম মেয়াদ নির্ধারণ করুন।

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

AWS STS (security token service) সর্বনিম্ন 15 মিনিট গ্রহণ করে। একটি এজেন্টের কাজের জন্য সাধারণত এই সময় যথেষ্ট। GitHub-এর ক্ষেত্রে, এজেন্ট ব্যবহারকারীর জন্য আলাদা gh লগইন তৈরি করুন এবং যে একক repository-তে সে কাজ করবে, সেটির মধ্যেই সীমাবদ্ধ fine grained token দিন। এতে ওই সেশনের মধ্যে gh auth token এমন কিছু ফেরত দেবে, যা অন্য কোনো কিছুর ওপর কাজ করতে পারবে না। প্রথমে resource অনুযায়ী সীমা নির্ধারণ করুন, তারপর সময় অনুযায়ী।

যাচাই করুন, তারপর নিয়মিত যাচাই করতে থাকুন

কোনো agent-এর সেটআপে পরিবর্তন করার পর তিনটি পরীক্ষা চালানো উচিত। এগুলো নিজের user হিসেবে নয়, 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 কোন identity উপস্থাপন করছে। gateway pattern-এর উদ্দেশ্যও এই প্রশ্নের উত্তর দেওয়া: 401 বোঝায় agent নিজের কোনো GitHub credential বহন করছে না, আর 200 বোঝায় এটি একটি credential বহন করছে; তাই কোন token সেটি, তা আপনার জানা উচিত। আপনি যদি agents unattended অবস্থায় চালান, VPS-এ AI agent-এর খরচ নিয়ন্ত্রণ করা এই access limit-এর সঙ্গে সম্পর্কিত budget limit সম্পর্কে ব্যাখ্যা করে।

FAQ

মডেল আমার key ফাঁস করবে না—এটি কি আমি শুধু বিশ্বাস করতে পারি?

না, কারণ এই threat model-এ আক্রমণকারী মডেল নয়। agent web page, repository এবং issue tracker থেকে text পড়ে, এবং সেই text-এ instruction থাকতে পারে। agent যে text সংগ্রহ করেছে, সেটিকে আপনার instruction থেকে নির্ভরযোগ্যভাবে আলাদা করার কোনো উপায় মডেলের নেই। মডেল সঠিক সিদ্ধান্ত নেবে—এমন নিয়ন্ত্রণ ব্যবস্থা injected instruction বিশ্বাসযোগ্য হলেই প্রথমবার ব্যর্থ হবে। তাই নিয়ন্ত্রণটি operating system বা network স্তরে থাকতে হবে।

agent-এর secret-এর জন্য environment variable কি সত্যিই এতটা ঝুঁকিপূর্ণ?

একটি নির্দিষ্ট কারণে এগুলো ঝুঁকিপূর্ণ: এগুলো উত্তরাধিকার সূত্রে পাওয়া যায়। agent যে প্রতিটি child process চালু করে, সেটি এর একটি copy পায়। এর মধ্যে build script, test runner এবং যেকোনো package install hook-ও রয়েছে। একই user /proc/<pid>/environ-এর মাধ্যমে variable-গুলো পড়তে পারে। তাই agent যেকোনো process চালালে, agent নিজে variable পাঠানো ছাড়াই সেই process সেগুলো পড়তে পারে। ব্যবহারের সময় LoadCredential= বা gateway দিয়ে file পড়ালে exposure শুধু ওই সময়ের মধ্যে সীমাবদ্ধ থাকে।

vault-এ secret রাখলে কি একাই এই সমস্যা সমাধান হয়?

আংশিকভাবে। vault storage-এর সমস্যা সমাধান করে। কিন্তু পরবর্তী ধাপের সমস্যা সমাধান করে না। ওই ধাপে কোনো কিছু vault থেকে secret নিয়ে agent-কে environment variable হিসেবে দেয়, ফলে আপনি আগের অবস্থায় ফিরে যান। গুরুত্বপূর্ণ বিষয় হলো substitution কে সম্পাদন করছে। agent secret সংগ্রহ করলে secret agent-এর কাছে থাকে। gateway বা init system agent-এর process-এর বাইরে substitution সম্পাদন করলে agent কখনো secret ধারণ করে না।

agent ইতিমধ্যে কিছু ফাঁস করেছে কি না, তা কীভাবে জানব?

সাধারণত ঘটনার পরে তা জানা যায় না। এটাই gateway ব্যবহারের পক্ষে যুক্তি। gateway ছাড়া আপনার প্রমাণ shell history, agent-এর transcript এবং outbound connection log-এ ছড়িয়ে থাকে, আর সম্ভবত আপনি ওই log সংরক্ষণই করছেন না। credential gateway থাকলে credential ব্যবহারের প্রতিটি ঘটনা agent identity এবং timestamp-সহ একটি line-এ থাকে। ফাঁসের সন্দেহ হলে আগে key rotate করুন, পরে তদন্ত করুন। Rotation সস্তা, কিন্তু নিশ্চিততা সস্তা নয়।

আজ আমার ন্যূনতম কী করা উচিত?

আপনার agent-গুলো যে directory-তে কাজ করে, সেখান থেকে প্রতিটি .env file সরিয়ে নিন এবং প্রতি agent-এর জন্য একটি করে unprivileged user তৈরি করুন। এই দুই পরিবর্তনে প্রায় 10 মিনিট লাগে এবং সবচেয়ে সাধারণ পথটি বন্ধ হয়। সেই পথে agent code-এর পাশে অপ্রয়োজনীয়ভাবে থাকা credential file পড়ে। Gateway এবং short-lived token পরবর্তী ধাপ, প্রথম ধাপ নয়। একই starting point যেকোনো agent runtime-এর ক্ষেত্রেই প্রযোজ্য, যার মধ্যে রয়েছে VPS-এ autonomous agent নিরাপদে চালানো