SSD Nodes Learn 8GB RAM — $66/साल
गाइड Matt Connorलेखक: Matt Connor · अपडेट किया गया: 2026-08-01

AI एजेंट को API keys दिए बिना secrets कैसे सुरक्षित रखें

AI agent एक tool call में API keys लीक कर सकता है। असली keys के बजाय credential gateway के पीछे scoped, short-lived tokens दें और पहुँच सीमित रखें।

AI एजेंट से सीक्रेट बाहर रखने का अर्थ

AI एजेंट एक सामान्य 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 हो जाने की कहानी नहीं है। इसका mechanism अधिक साधारण है। Agent किसी web page, README या issue comment को पढ़ता है, जिसमें instructions होती हैं, और उनका पालन करता है। इसका कारण यह है कि language model के लिए आपके द्वारा लिखे गए text और उसके द्वारा fetch किए गए text में कोई अंतर नहीं होता। इसे prompt injection कहते हैं। ऐसा होने के बाद नुकसान की सीमा ठीक एक चीज़ से तय होती है: process क्या पढ़ सकता है। यदि आपने अभी तक boundary निर्धारित नहीं की है, तो server पर coding agent को सुरक्षित रूप से चलाना उस isolation के स्तरों को समझाता है, जिन पर यह guide आधारित है।

खतरे का मॉडल सरल शब्दों में

इसे उसी user के रूप में चलाएँ, जिसके रूप में आपका agent चलता है।

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

इसमें दिखाई देने वाली हर line किसी अनजान server के लिए एक HTTP request है। अब agent के पास disk पर मौजूद data को देखें।

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 में हो।
  • ऐसे repository को git commit और git push, जिसमें agent लिख सकता हो।
  • package install script, जो agent के user के रूप में arbitrary code चलाती है।
  • ऐसे hostname का DNS lookup, जिसमें value शामिल हो। HTTP egress blocked होने पर भी यह value बाहर भेज देता है।

आप केवल review करके इस समस्या से नहीं बच सकते। समाधान यह सुनिश्चित करना है कि agent की पहुँच में कोई मूल्यवान data न हो।

working tree में secret, context window में भी secret

Agent files को पढ़ता है। जिस repository में वह काम कर रहा है, उसमें मौजूद .env file पढ़ी जाएगी। पढ़े जाने के बाद वह 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

बाद में, file को पहुंच से बाहर ले जाने पर:

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 का user अब file को नहीं खोल सकता, क्योंकि working tree में वह file मौजूद नहीं है। Agent के अपने config में मौजूद deny rules दूसरी सुरक्षा परत हैं, पहली नहीं। Claude Code project में .claude/settings.json से permission rules पढ़ता है:

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

इससे exploration के दौरान Agent द्वारा गलती से file खोलने की समस्या रुकती है। यह किसी injected instruction को base64 .env चलाने से नहीं रोकता, क्योंकि वह shell command है, file read नहीं। Config को guardrail मानें और filesystem permission को दीवार मानें। यही विभाजन containers के भीतर भी लागू होता है: Docker Compose में env files और secrets इस समस्या के एक स्तर नीचे वाले रूप को कवर करता है।

प्रत्येक agent को अपना unprivileged 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 के साथ fail होना चाहिए। यदि इसके बजाय यह कोई key प्रिंट करती है, तो आपकी home directory group या world readable है और chmod 700 ~ इसे ठीक करता है। agent user को sudo में न जोड़ें और उसे NOPASSWD का ऐसा rule न दें जो उस एक command से अधिक व्यापक हो जिसकी उसे वास्तव में आवश्यकता है। VPS पर न्यूनतम विशेषाधिकार वाले users में group और sudoers का विवरण दिया गया है।

cloud VPS पर एक और सीमा जोड़ना उपयोगी है। instance metadata service एक fixed 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/ को कुछ भी प्रिंट नहीं करना चाहिए और non zero exit करना चाहिए, क्योंकि packet box से बाहर जाने से पहले ही reject हो जाता है।

सीमा पर क्रेडेंशियल इंजेक्ट करें

इस समस्या का वास्तविक समाधान क्रेडेंशियल इंजेक्शन है। एजेंट के पास कभी वास्तविक key नहीं होती। वह अपना अनुरोध एक स्थानीय gateway के माध्यम से भेजता है। gateway बाहर भेजते समय placeholder को वास्तविक secret से बदल देता है। secret gateway के storage में रहता है। यह अलग process में और अलग user के स्वामित्व में होता है।

OneCLI इसका एक open source implementation है। यह Apache-2.0 licensed है और agent के पास एक container के रूप में चलता है। July 2026 तक project इस setup को document करता है:

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 को एक बार store करते हैं। इसके बाद प्रत्येक agent को key के स्थान पर एक placeholder value और अपना scoped access token देते हैं। agent यह token Proxy-Authorization header में भेजता है। gateway host और path के आधार पर outbound request का मिलान करता है। फिर यह matching credential को decrypt करके उसका स्थान ले लेता है। agent के environment में चोरी करने योग्य कोई credential नहीं रहता।

यहां encryption मुख्य लाभ नहीं है। मुख्य लाभ यह है कि प्रश्न "इस agent ने क्या इस्तेमाल किया और कब" अब एक log query बन जाता है। आप छह environments में key की copy कहां थी, इसका अनुमान लगाने के बजाय एक audit trail पढ़ते हैं।

सीक्रेट environment को नहीं, process को दें

यदि आप agent को systemd के अंतर्गत चलाते हैं, तो आपको environment variables की आवश्यकता नहीं है। LoadCredential= सीक्रेट को एक private directory में रखता है, जिसे केवल वह service पढ़ सकती है। यह unit file में %d के रूप में और process के भीतर $CREDENTIALS_DIRECTORY के रूप में उपलब्ध होता है। यह मान कभी भी /proc/<pid>/environ में दिखाई नहीं देता। इसलिए ps eww इसे प्रदर्शित नहीं कर सकता। Service बंद होने पर directory भी हट जाती है।

पहले credential को machine के लिए encrypt करें। ये commands systemd documentation से ली गई हैं और systemd 250 या उसके बाद के versions पर काम करती हैं। इसमें 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 खोलता है। File read केवल क्षणिक होता है। Environment variable process के पूरे जीवनकाल तक रहता है और उसके द्वारा शुरू किए गए प्रत्येक child process में भी उपलब्ध रहता है।

लंबे समय तक मान्य keys के बजाय कम समय तक मान्य tokens को प्राथमिकता दें

जो key कभी समाप्त नहीं होती, वह महीनों बाद log या transcript में दिखाई देने पर भी मान्य रहती है। यदि service session token उपलब्ध कराती है, तो session token का उपयोग करें और कार्य के लिए अनुमत सबसे कम lifetime निर्धारित करें।

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) स्वीकार करता है। एक agent task के लिए यह आमतौर पर पर्याप्त होती है। GitHub के लिए agent user को अपना gh login दें और fine grained token को केवल उस एक repository तक सीमित करें जिस पर वह काम करता है। इस तरह उस session के अंदर gh auth token ऐसा परिणाम लौटाएगा जो किसी अन्य संसाधन को प्रभावित नहीं कर सकता। पहले resource के आधार पर scope निर्धारित करें, फिर समय के आधार पर।

सत्यापित करें, फिर लगातार सत्यापन करते रहें

किसी 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 कौन-सी identity प्रस्तुत करता है। यही वह प्रश्न है जिसका उत्तर gateway pattern देता है: 401 का अर्थ है कि agent के पास अपना कोई GitHub credential नहीं है, और 200 का अर्थ है कि उसके पास एक credential है। इसलिए आपको पता होना चाहिए कि वह कौन-सा token है। यदि आप agents को unattended चलाते हैं, तो VPS पर AI agent की लागत नियंत्रित करना इन access limits के साथ लागू होने वाली budget limits की जानकारी देता है।

FAQ

क्या मैं केवल इस बात पर भरोसा कर सकता हूँ कि model मेरी keys लीक नहीं करेगा?

नहीं, क्योंकि इस threat model में attacker model नहीं है। agent web pages, repositories और issue trackers से text पढ़ता है, और उस text में instructions हो सकती हैं। model के पास आपके instructions और उसके द्वारा fetch किए गए 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 के रूप में /proc/<pid>/environ के माध्यम से variables को पढ़ा भी जा सकता है। इसलिए agent द्वारा चलाया गया कोई भी process agent के उन्हें आगे भेजे बिना इन्हें पढ़ सकता है। उपयोग के समय पढ़ी जाने वाली file, LoadCredential= या gateway के साथ, exposure को उसी समय तक सीमित रखती है।

क्या secrets को vault में रखने से यह समस्या अपने-आप हल हो जाती है?

केवल आंशिक रूप से। vault storage की समस्या हल करता है। यह अंतिम चरण की समस्या हल नहीं करता, जिसमें कोई process vault से secret निकालकर agent को environment variable के रूप में देता है। इससे आप फिर उसी स्थिति में पहुँच जाते हैं। महत्वपूर्ण यह है कि substitution कौन करता है। यदि agent secret fetch करता है, तो secret agent के पास है। यदि gateway या init system agent की process के बाहर substitution करता है, तो agent secret को कभी hold नहीं करता।

मुझे कैसे पता चलेगा कि agent ने पहले ही कुछ लीक किया है?

आमतौर पर बाद में इसका पता नहीं लगाया जा सकता। यही gateway के पक्ष में मुख्य तर्क है। gateway के बिना आपका evidence shell history, agent के transcript और outbound connection logs में बिखरा रहता है, जिन्हें आप शायद रख ही नहीं रहे हैं। credential gateway के साथ credential का हर उपयोग agent identity और timestamp वाली एक line होता है। यदि आपको leak का संदेह हो, तो पहले key rotate करें और बाद में investigation करें। Rotation सस्ता है, certainty नहीं।

मुझे आज कम-से-कम क्या करना चाहिए?

हर .env file को उन directories से बाहर ले जाएँ जिनमें आपके agents काम करते हैं, और प्रत्येक agent के लिए एक unprivileged user बनाएँ। इन दो बदलावों में लगभग दस मिनट लगते हैं और सबसे सामान्य path बंद हो जाता है। यह path ऐसा agent है जो ऐसी credential file पढ़ता है जिसका code के पास मौजूद रहने का कोई कारण नहीं था। Gateway और short lived tokens अगला चरण हैं, पहला नहीं। यही starting point किसी भी agent runtime पर लागू होता है, जिसमें VPS पर autonomous agent को सुरक्षित रूप से चलाना भी शामिल है।