# स्थानीय AI agents और CI jobs को अलग access models की जरूरत क्यों है

डेवलपर का workstation और build runner दोनों shell commands चला सकते हैं, APIs को call कर सकते हैं और code push कर सकते हैं। उन्हें एक जैसा security environment मानना ही वह गलती है जिसके कारण teams deployment credential ऐसी जगह रख देती हैं जहां न तो कोई व्यक्ति और न ही कोई service उसका सही हिसाब दे सकती है।

स्थानीय AI agents एक attended environment में चलते हैं। कोई व्यक्ति prompt देख सकता है, diff की जांच कर सकता है, असामान्य अनुरोध को अस्वीकार कर सकता है और गलत व्यवहार करने लगे किसी process को रोक सकता है। CI jobs किसी घटना के कारण चलते हैं: push, pull request, tag, scheduled run या manual dispatch। जॉब को उस घटना से जुड़ा machine-verifiable authority चाहिए। वह हर call के लिए developer के अनुमोदन का इंतजार नहीं कर सकता और केवल workflow चलने के कारण उसे developer की स्थायी access भी नहीं मिलनी चाहिए।

यह अंतर केवल सैद्धांतिक नहीं है। इसी से तय होता है कि agent को secret मिलेगा या नहीं, token कुछ मिनट रहेगा या महीनों तक, audit entry में क्या लिखा जाना चाहिए और compromised dependency production incident में बदल सकती है या नहीं।

## इंसान की मौजूदगी से approval का अर्थ बदल जाता है

Workstation पर approval एक सार्थक security control हो सकता है, क्योंकि कोई व्यक्ति तुरंत होने वाली कार्रवाई का आकलन करने के लिए मौजूद होता है। Approval में caller की पहचान इतनी स्पष्ट होनी चाहिए कि वह आकलन उपयोगी बन सके। «एक agent HTTP request करना चाहता है» बहुत कमजोर जानकारी है। «इस authority से signed, इस session में शुरू हुआ process production deploy credential इस्तेमाल करना चाहता है» operator को स्वीकार या अस्वीकार करने के लिए ठोस आधार देता है।

इस model की एक स्पष्ट सीमा है: approval का मतलब है कि कोई इंसान चल रहे process की जिम्मेदारी ले रहा है। यह identity का विकल्प नहीं है। अगर कोई malicious process trusted caller का रूप ले सकता है, destination छिपा सकता है या task बदलने के बाद approval फिर इस्तेमाल कर सकता है, तो prompt केवल दिखावा बन जाता है।

Developer machine पर मुझे तीन अलग-अलग तथ्य चाहिए:

- protected store तब तक locked रहे जब तक local user उसे unlock न करे;
- नए process के पहले request पर session decision जरूरी हो;
- sensitive credentials के हर उपयोग पर decision लिया जा सके।

इन controls के जवाब अलग सवालों से जुड़े हैं। Lock बताता है कि कोई action हो भी सकता है या नहीं। Session authorization बताता है कि यह process इस run के दौरान काम कर सकता है या नहीं। Per-call approval बताता है कि कोई खास credential इतना महत्वपूर्ण है या नहीं कि उसे बिना नए निर्णय के फिर इस्तेमाल न किया जाए। Teams अक्सर इन तीनों को एक ही «allow agent access» button में समेट देती हैं और बाद में पता चलता है कि button ने developer की मंशा से कहीं अधिक access मंजूर कर दी थी।

स्थानीय agent को credential material नहीं, परिणाम मिलने चाहिए। अगर agent को किसी API से जानकारी लेनी है, तो agent के बाहर का component credential जोड़ सकता है, request कर सकता है और response लौटा सकता है। इससे agent में हुआ prompt injection API key को terminal, patch या chat transcript में सीधे print नहीं कर पाता। Secret agent context में पहुंच जाने के बाद उसे mask करना बराबर सुरक्षा नहीं है। Agent उसे encode कर सकता है, किसी दूसरे host को भेज सकता है या masker के देखने से पहले ही request में इस्तेमाल कर सकता है।

Sallyport macOS पर इसी attended model का उपयोग करता है: उसका vault एक absolute gate के पीछे रहता है और किसी process session के लिए या चुने गए credential के हर उपयोग के लिए authorization मांगी जा सकती है। Developer के मौजूद होने पर यह सही तरीका है। Unattended runner के लिए यह गलत primitive होगा।

## CI जॉब को ऐसी identity चाहिए जिसकी जांच की जा सके

CI जॉब जरूरत पड़ने पर human intent नहीं दिखा सकता। उसे workload identity चाहिए, यानी ऐसी identity जो जॉब environment में copy किए गए secret से नहीं, बल्कि जॉब के बारे में सत्यापित किए जा सकने वाले तथ्यों से निकले।

Deployment workflow के लिए इन तथ्यों में आमतौर पर CI issuer, repository या project, commit या ref, workflow identity, environment और intended audience शामिल होते हैं। Target service signed assertion की जांच करती है और बदले में short-lived credential देती है। OIDC federation का उपयोगी हिस्सा यही है: runner reusable cloud key अपने secret store में रखे बिना यह साबित करता है कि जॉब कहां से आया है।

GitHub Actions इस pattern को अपने OIDC token endpoint और `id-token: write` permission के जरिए document करता है। Permission का नाम आसानी से गलत समझा जा सकता है। यह workflow को identity token मांगने की अनुमति देता है, अपने आप deployment permission नहीं देता। Cloud role या target service को अब भी ऐसे tokens अस्वीकार करने चाहिए जिनके issuer, audience, subject और अन्य claims इच्छित workflow से मेल नहीं खाते।

कई configurations इसी दूसरे हिस्से में विफल होती हैं। ऐसा role जो repository के किसी भी token को स्वीकार करता है, उस repository के हर qualifying workflow को बहुत अधिक authority दे देता है। Documentation preview, release workflow और production deployment केवल source control साझा करने के कारण एक जैसे नहीं हो जाने चाहिए।

Claims का उपयोग करके role को एक job class तक सीमित करें। Exact claim syntax CI provider और cloud पर निर्भर करता है, लेकिन policy को इन सरल सवालों का जवाब देना चाहिए:

- कौन-सा repository यह role मांग सकता है?
- कौन-सी workflow file या protected environment इसे मांग सकती है?
- कौन-सी branch, tag या release condition इसे मांग सकती है?
- Assertion में कौन-सा audience लिखा होना चाहिए?
- जारी किया गया credential कितनी देर तक उपयोगी रह सकता है?

ऐसी policy conditions न लिखें जिन्हें आपने किसी वास्तविक token में देखा ही नहीं है। Safe test environment में claims print करें, उन्हें trust policy से मिलाएं और denial cases भी test करें। लोग सफल deployments का परीक्षण करते हैं और खतरनाक रास्ते, यानी untrusted branch से आई pull request, को केवल अनुमान पर छोड़ देते हैं।

## Secrets और identities अलग समस्याएं हल करते हैं

Secret possession साबित करता है। Identity assertion उस workload के बारे में दावा करता है जिसने access मांगी है। दोनों अंत में bearer token तक पहुंच सकते हैं, लेकिन failure paths बहुत अलग होते हैं।

Stored CI secret को आमतौर पर यह पता नहीं होता कि जॉब को वह secret क्यों मिला। अगर workflow `DEPLOY_TOKEN` पढ़ सकता है, तो बदली हुई script, compromised action, malicious pull-request path या log command उस token का उपयोग वहां कर सकते हैं जहां तक उसकी permissions पहुंचती हैं। Rotation secret के उपयोगी रहने की अवधि घटाती है, लेकिन हर उपयोग के context को सीमित नहीं करती।

Short-lived federation CI को जादुई रूप से सुरक्षित नहीं बनाती। Compromised job token की lifetime के दौरान उसका सही उपयोग कर सकता है। फायदा blast radius के कम होने का है: attacker को eligible job चलाना होगा, issuer और claim rules पूरे करने होंगे और credential expire होने से पहले काम करना होगा। हर copied secret खोजे बिना accepting role को revoke या बदलना भी संभव है।

Short-lived credentials को low privilege न समझें। दस मिनट तक valid रहने वाला ऐसा token जो हर production database को delete कर सकता है, फिर भी अस्वीकार्य है। Time limits persistence घटाती हैं, authorization scope नुकसान सीमित करता है। दोनों जरूरी हैं।

Local agent access की उलटी चिंता होती है। Developer कई repositories और tasks में एक ही local tool इस्तेमाल कर सकता है, इसलिए एक broad API key compromised agent के लिए आकर्षक target बन जाती है। सबसे सुरक्षित local design में key agent के बाहर रहती है और केवल वही specific API call या SSH command चलती है जिसे user ने मंजूर किया है। External service fine-grained tokens support करती हो तो वहां भी उनका उपयोग करें। Request machine से बाहर जाने के बाद protected vault किसी overpowered token को सुरक्षित नहीं बना सकता।

## दोनों दुनिया के लिए एक ही token सबसे खतरनाक सुविधा है

CI में developer का personal token इस्तेमाल करना लोकप्रिय है, क्योंकि इससे blocked deployment जल्दी चल पड़ता है। Accountability मिटाने के लिए यह सबसे खराब तरीकों में से एक है।

Personal token अक्सर pipeline की जरूरत से कहीं अधिक access रखता है। वह ऐसे employee का हो सकता है जो team बदलता है, company छोड़ता है, laptop से उसका उपयोग करता है और जिसकी access deployment duties के बजाय personal membership से तय होती है। CI में आने पर audit log बता सकता है कि token ने काम किया, लेकिन वह ईमानदारी से यह नहीं बता सकता कि कार्रवाई developer ने की या release job ने।

उलटी गलती भी होती है। Teams CI deployment secret को local agent के सामने रख देती हैं ताकि वह «वही चीज test» कर सके। इससे interactive code generation को unattended production capability मिल जाती है, अक्सर release workflow से कम checks के साथ। Incident response भी बेहद कठिन हो जाता है: credential agent ने इस्तेमाल किया, shell script ने, या copied value किसी दूसरे tool में leak हो गई?

हर environment को अपनी authorization boundary दें। Local developer के पास development endpoint के लिए interactive, revocable access हो सकती है। Release job को protected production environment तक सीमित federated role मिल सकता है। Pull-request job के पास कोई write authority न हो। ये ऐसी असुविधाएं नहीं हैं जिन्हें छिपाना चाहिए। बाद में यह समझाने के लिए यही evidence काम आता है कि कोई कार्रवाई क्यों allow हुई थी।

एक उपयोगी naming rule यह है कि credential names में actor और purpose दोनों दिखाई दें। `ci-release-prod-deploy`, `deploy-token` से reviewer को कहीं अधिक जानकारी देता है। इससे बेहतर यह है कि CI job उस नाम वाला token store ही न करे। वह identity-bound role मांगे जिसकी trust policy में वही purpose लिखा हो।

## Runner state अस्थायी access को अवशेष में बदल देता है

Job temporary credential इस्तेमाल कर सकता है और फिर भी स्थायी परेशानी छोड़ सकता है। आम leaks logs, shell tracing, cached home directories, Docker layers, workspace artifacts और third-party actions द्वारा लिखी गई files से होते हैं।

Self-hosted runners पर विशेष संदेह रखें, क्योंकि वे jobs के बीच state बचा सकते हैं। Untrusted code checkout करने वाला job modified executable रख सकता है, shared cache बदल सकता है, leftover workspace देख सकता है या privileged workflow के host को दोबारा इस्तेमाल करने का इंतजार कर सकता है। Repository name से isolation मदद नहीं करती, अगर jobs एक ही operating-system account, container socket या filesystem साझा करते हों।

Ephemeral runners बड़ी मात्रा में residue हटा देते हैं, क्योंकि job के बाद runner ही समाप्त हो जाता है। फिर भी workflow inputs को नियंत्रित करना जरूरी है। Untrusted pull request से scripts चलाने वाला privileged job fresh machine पर भी authority untrusted code को दे रहा है।

GitHub Actions चेतावनी देता है कि `pull_request_target` base repository के context में चलता है और secrets या write permissions तक पहुंच सकता है। इस event का वैध उद्देश्य है: Maintainers को fork से आई pull request पर label या comment करने की जरूरत पड़ सकती है। समस्या तब आती है जब उस event से triggered workflow pull request का head commit checkout करके उसकी scripts चला देता है। Workflow ने trusted credentials को attacker-controlled code के साथ जोड़ दिया है।

Pattern को सरल रखें:

- Untrusted pull-request code को deployment authority के बिना चलाएं।
- Protected environment access केवल reviewed refs और नियंत्रित workflow paths को दें।
- जहां आपकी प्रक्रिया अनुमति दे, third-party actions को immutable commit references पर pin करें।
- Secret material को caches, artifacts और diagnostic output से दूर रखें।
- Job के बाद sensitive runner instances नष्ट कर दें।

पहले और चौथे points वास्तविक incidents को elaborate token naming conventions से अधिक बार रोकते हैं। Perfectly scoped credential भी leak हो जाता है, अगर shell command उसे print कर दे या artifact उसकी configuration file साथ ले जाए।

## Deployment identity एक ही file में जांचने योग्य होनी चाहिए

Workflow में outside authority के लिए request साफ दिखाई देनी चाहिए। यह GitHub Actions example केवल deployment job में OIDC identity मांगता है और production environment घोषित करता है। इसमें जानबूझकर कोई stored cloud credential नहीं है।

```yaml
name: deploy

on:
  push:
    tags:
      - "v*"

permissions:
  contents: read
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@<full-commit-sha>
      - name: Request deployment identity
        run: |
          token=$(curl -sS \
            -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=deploy.example.internal")
          test -n "$token"
      - name: Deploy
        run: ./scripts/deploy.sh
```

वास्तविक exchange में आमतौर पर response को shell variable में save करने के बजाय action या cloud CLI का उपयोग होता है। यहां महत्वपूर्ण request का ढांचा है: GitHub one-time request token और URL देता है, workflow specific audience मांगता है और target फिर तय करता है कि यह identity role assume कर सकती है या नहीं। Runner को मिले identity token को कभी general API credential नहीं मानना चाहिए।

Cloud-side trust policy को ऐसे token को अस्वीकार करना चाहिए जिसके claims इस release context की पहचान न करते हों। किसी provider example को copy करके वहीं न रुकें। Provider examples अक्सर broad रखे जाते हैं, क्योंकि उन्हें बहुत से users के लिए काम करना होता है। Role के production बदलने से पहले repository, environment, branch या tag और audience की constraints कड़ी करें।

अगर target OIDC की सीधे पुष्टि नहीं कर सकता, तो उसके सामने एक छोटा credential broker रखें। Broker CI assertion की पुष्टि करता है, claims को सीमित actions से map करता है, temporary target credential जारी करता है और mapping log करता है। इस सीमा को हल करने के लिए हर उस workflow में permanent target secret न रखें जिसे service की जरूरत है।

## SSH इस अंतर को खास तौर पर स्पष्ट करता है

SSH keys साझा CI सुविधा के लिए खराब विकल्प हैं। CI secret में copy की गई private key उस key को पढ़ सकने वाले किसी भी job से authentication करा सकती है और उसका public half आमतौर पर target को यह नहीं बताता कि connection के लिए कौन-सा repository revision responsible था। Forced commands, source restrictions और अलग accounts नुकसान सीमित कर सकते हैं, लेकिन मूल identity फिर भी reusable private key ही रहती है।

Local work में SSH को interactive gate की जरूरत हो सकती है, क्योंकि developer देख सकता है कि agent किसी खास host से connect करना चाहता है। Private key protected storage में रहनी चाहिए और agent को key की raw access देने के बजाय specific command मांगनी चाहिए। Host को अपनी account permissions और command restrictions भी लागू करनी होंगी। Local approval launch point को नियंत्रित करता है, खतरनाक remote command को सुरक्षित नहीं बनाता।

CI के लिए, जब आपका SSH certificate authority और target fleet support करें, तो short-lived SSH certificates को प्राथमिकता दें। Job workload federation से short validity period, restricted principal और संभव हो तो forced command वाला certificate मांगता है। Target हमेशा के लिए copied private key स्वीकार करने के बजाय certificate authority की पुष्टि करता है।

अगर certificates उपलब्ध नहीं हैं, तो हर deployment class के लिए अलग deploy account और dedicated private key इस्तेमाल करें। उस account को `authorized_keys` और server दोनों स्तरों पर सीमित करें। एक न्यूनतम restriction इस तरह दिखती है:

```text
command="/usr/local/bin/receive-release",no-port-forwarding,no-agent-forwarding,no-X11-forwarding ssh-ed25519 AAAA... ci-release
```

यह line key को arbitrary interactive shell खोलने से रोकती है और server को एक receiver program चलाने के लिए बाध्य करती है। यह अपने आप source repository की पहचान नहीं करती। अगर release decision repository context पर निर्भर है, तो इसे brokered, short-lived key या किसी अन्य verified workload signal के साथ जोड़ें।

CI script में SSH को चलाने के लिए `StrictHostKeyChecking=no` सेट न करें। इससे server identity check उसी जगह बंद हो जाता है जहां runners traffic redirect करने के लिए आसान target होते हैं। Known host keys को controlled mechanism से दें, उन्हें सोच-समझकर rotate करें और host verification अचानक बदलने पर job fail करें।

## Audit records को अलग-अलग सवालों के जवाब देने चाहिए

केवल «deployment succeeded» कहने वाला action log operational output है, पर्याप्त security evidence नहीं। आपको यह पता लगाना चाहिए कि authority किसे या किस चीज को मिली, उसने कौन-सा request किया और क्या record बाद में बदला गया।

Attended local agent के लिए local process identity, session start, approval decision, credential label या action class, destination, request time और result record करें। Secret values या पूरे sensitive payloads record न करें। Process signature या code-signing authority किसी मनमाने process name से अधिक उपयोगी है, क्योंकि names की नकल आसानी से की जा सकती है।

CI के लिए CI provider, run ID, repository, workflow reference, commit SHA, जहां उपलब्ध हो वहां run trigger करने वाला actor, runner class, OIDC subject और audience, target role, सुरक्षित रूप से रखे जा सकने वाले action parameters और result record करें। इससे investigator tagged release, manually rerun job, trusted workflow और गलती से दिए गए broad grant में अंतर कर सकता है।

Authorization logs को application logs से अलग रखें। Application logs सामान्य operations में बदले, sample या delete किए जा सकते हैं। Authorization trail में append-only behavior और independent verification होना चाहिए। Hash chaining sequence में बदलाव पकड़ती है, जब chain को सुरक्षित रखकर expected records से verify किया जाए। यह attacker को भविष्य के records रोकने से नहीं रोकती, इसलिए जहां design अनुमति दे वहां compromised machine से records बाहर भेजें।

Sallyport session और individual action journals को write-blind encrypted, hash-chained audit log से project करता है और `sp audit verify` vault key के बिना offline chain की जांच करता है। Attended agent actions के लिए यह उपयोगी evidence है। CI को identity जारी करने और स्वीकार करने वाले systems में इसी तरह का workload-bound trail बनाना चाहिए।

## Approval fatigue स्थानीय design की विफलता है

Per-call approval high-impact local credentials की सुरक्षा कर सकता है, लेकिन हर harmless read पर prompt दिखाने से लोग prompts पढ़े बिना स्वीकार करना सीख जाते हैं। ऐसा होने पर control एक रस्म बन जाता है और attacker को केवल routine work का इंतजार करना पड़ता है।

Per-call approval उन actions के लिए रखें जिनके परिणाम पलटना कठिन हो: production writes, DNS changes, organization-wide administration, source-control force pushes या sensitive hosts पर commands। Repetitive low-risk actions के लिए session authorization इस्तेमाल करें, जिन्हें developer एक agent run के दौरान उचित रूप से delegate कर सकता है। Vault gate को अलग रखें, ताकि locked machine हर action को अस्वीकार करे, भले ही पुराना session approval मौजूद हो।

CI में fatigue का अपना रूप है: manual approval gates जो हर job पर दिखाई देते हैं और release timing प्राथमिकता बन जाने पर approve कर दिए जाते हैं। Production deployment के लिए protected environment approval सही हो सकता है, लेकिन उसे स्पष्ट रूप से पहचाने गए release artifact और target को approve करना चाहिए। वह untrusted code स्वीकार करने वाले workflow, broad claims वाले role या unknown state वाले runner की भरपाई नहीं कर सकता।

एक व्यावहारिक review यह असहज सवाल पूछता है: अगर यह approval एक महीने तक अपने आप click होता रहे, तो क्या-क्या चल सकता है? Local agents के लिए approved action surface तब तक घटाएं जब तक जवाब स्वीकार्य न लगे। CI के लिए ordinary machine actions से approval हटाएं और authority को job identity से बांधें।

## अगले credential request से पहले दोनों paths अलग करें

जब कोई agent या pipeline access मांगे, तो secret mechanism चुनने से पहले caller को classify करें। क्या कोई व्यक्ति मौजूद है और action की जांच कर सकता है? क्या caller एक repeatable workload है जिसके claims validate किए जा सकते हैं? क्या caller credential के बजाय सीमित result प्राप्त कर सकता है? क्या target permission किसी एक नामित task से मेल खाती है?

अगर caller local agent है, तो credentials को उसके context के बाहर सुरक्षित रखें, meaningful approval path बनाए रखें और हर action को ऐसे रूप में log करें जिसकी developer समीक्षा कर सके। अगर caller CI है, तो short-lived federation इस्तेमाल करें, roles को workflow claims से बांधें, runner को isolate करें और उन workload facts को record करें जिन्होंने call को authorize किया।

आज तेजी से काम पूरा करने के लिए shared token को यह boundary मिटाने न दें। अगली incident में आपको इसे फिर बनाना पड़ेगा और साथ ही यह पता लगाने की कोशिश करनी होगी कि वास्तव में कार्रवाई किसी व्यक्ति, agent या runner ने की थी।
