8 मिनट पढ़ें

अप्रूवल कार्ड का रिडैक्शन निर्णय को सुरक्षित रखे

अप्रूवल कार्ड को क्रेडेंशियल और निजी डेटा छिपाते हुए destination, target, effect और जोखिम वाले parameters इतने स्पष्ट रखने चाहिए कि कार्रवाई को सुरक्षित रूप से अप्रूव किया जा सके।

अप्रूवल कार्ड का रिडैक्शन निर्णय को सुरक्षित रखे

अप्रूवल कार्ड का एक ही काम है: किसी व्यक्ति को यह तय करने में मदद करना कि कोई खास कार्रवाई उसकी मशीन से बाहर जाने दी जाए या नहीं। अगर कार्ड क्रेडेंशियल बचाने के लिए पर्याप्त जानकारी छिपा देता है, लेकिन यह भी छिपा देता है कि अनुरोध करेगा क्या, तो वह अपने काम में विफल है।

आम गलती रिडैक्शन को केवल स्ट्रिंग बदलने की प्रक्रिया समझना है। इंजीनियर Authorization को मास्क करते हैं, JSON बॉडी खाली कर देते हैं और परिणाम को सुरक्षित मान लेते हैं। ऑपरेटर को तब POST https://api.example.com/... और Approve बटन दिखाई देता है। यह सूचित सहमति नहीं है। यह एक खाली रस्म है, जो लोगों को उसी क्षण बिना सोचे क्लिक करना सिखाती है जब मानव नियंत्रण सबसे ज़्यादा मायने रखता था।

अच्छा कार्ड कार्रवाई का अर्थ बनाए रखता है और ऐसी सामग्री हटा देता है जिससे कार्ड पढ़ने, उसका स्क्रीनशॉट लेने, उसे लॉग में देखने या किसी के पीछे खड़े होकर पढ़ने वाला व्यक्ति किसी सीक्रेट का दोबारा उपयोग कर सके। इसके लिए फ़ील्ड की जानकारी के आधार पर रेंडरिंग चाहिए। हेडर, क्वेरी स्ट्रिंग, बॉडी और टार्गेट पहचानकर्ताओं के साथ अलग-अलग व्यवहार करना होगा।

अप्रूवल कार्ड को कार्रवाई समझानी चाहिए

ऑपरेटर कुछ ही सेकंड में चार सवालों का जवाब दे सके: अनुरोध कौन कर रहा है, रिक्वेस्ट कहाँ जा रही है, वह क्या करेगी और किस ऑब्जेक्ट या स्कोप पर असर डालेगी। इनमें से कोई भी जवाब न मिले, तो कार्ड अधूरा है, भले ही हर सीक्रेट पूरी तरह छिपा हो।

ऐक्शन लाइन की शुरुआत ऐसी होनी चाहिए जिसमें प्रोटोकॉल मेथड और इंसानी भाषा में क्रिया दोनों हों:

POST  api.billing.example  /v1/invoices/inv_7KD2/refund
Action: issue a refund

मेथड महत्वपूर्ण है, क्योंकि GET, POST, PATCH और DELETE से अलग-अलग अपेक्षाएँ जुड़ी होती हैं। इंसानी क्रिया भी ज़रूरी है, क्योंकि अकेला मेथड यह नहीं बताता कि POST /v1/invoices/inv_7KD2/refund ड्राफ़्ट बनाएगा, भुगतान भेजेगा या रिफंड शुरू करेगा। जब कॉल करने वाले को इच्छित ऑपरेशन पता है, तो व्यक्ति से रूट नाम देखकर एप्लिकेशन का अर्थ समझने की उम्मीद न करें।

इसके बाद डेस्टिनेशन को वास्तविक authority के रूप में दिखाएं, केवल अकाउंट निकनेम के रूप में नहीं। «Production billing» सहायक संदर्भ हो सकता है, लेकिन वह api.billing.example की जगह नहीं ले सकता। गलत जगह भेजा गया अनुरोध परिचित लेबल का उपयोग कर सकता है। होस्ट वह सीमा बताता है कि डेटा और क्रेडेंशियल किस सेवा को मिलेंगे।

RFC 3986 URI को authority, path, query और fragment जैसे हिस्सों में बाँटता है। अप्रूवल रेंडरिंग के लिए यह विभाजन उपयोगी है, क्योंकि हर हिस्सा अलग तरह का निर्णय संकेत देता है। इसे एक सुंदर URL स्ट्रिंग में बदलकर बाद में मास्क करने पर भरोसा न करें। इससे सही जानकारी बची रहेगी, यह तय नहीं है।

कार्ड में यह भी बताया जाना चाहिए कि कार्रवाई कुछ बनाएगी, बदलेगी, हटाएगी, प्रकाशित करेगी, ट्रांसफ़र करेगी या केवल पढ़ेगी। «PATCH customer record» की तुलना में «ग्राहक का payout destination बदलें» अधिक स्पष्ट है। अगर आपका रिक्वेस्ट बिल्डर यह वाक्य नहीं दे सकता, तो रिक्वेस्ट बिल्डर को ठीक करें। कोई कार्ड रेंडरर मनमाने JSON से बिज़नेस इंटेंट को भरोसेमंद ढंग से वापस नहीं निकाल सकता।

सुंदर बनाई गई रिक्वेस्ट नहीं, रिक्वेस्ट मैनिफ़ेस्ट रेंडर करें

काम की सुरक्षित इकाई typed request manifest है। यह दर्ज करता है कि क्रेडेंशियल डाले जाने और कोई अप्रूवल व्यू बनने से पहले एजेंट क्या करना चाहता है।

एक न्यूनतम मैनिफ़ेस्ट ऐसा हो सकता है:

{
  "channel": "http",
  "method": "POST",
  "destination": {
    "scheme": "https",
    "host": "api.billing.example",
    "port": 443,
    "path_template": "/v1/invoices/{invoice}/refund"
  },
  "action": "issue refund",
  "targets": [
    {"role": "invoice", "display": "inv_7KD2", "sensitivity": "internal"}
  ],
  "query": [],
  "headers": [],
  "body": {
    "media_type": "application/json",
    "fields": []
  },
  "effect": "financial"
}

यह HTTP wire representation नहीं है। यह वह ऑब्जेक्ट है जिसे अप्रूवल रेंडरर पढ़ेगा। यह अंतर महत्वपूर्ण है। वायर रिक्वेस्ट में डाले गए क्रेडेंशियल, encoded values और transport details होते हैं। मैनिफ़ेस्ट में action, target role और effect जैसे अर्थपूर्ण लेबल होते हैं, जो कच्ची रिक्वेस्ट में नहीं मिलते।

हर दिखाए जा सकने वाले मान को इस आधार पर वर्गीकृत करें कि ऑपरेटर को निर्णय लेने के लिए क्या चाहिए, न कि इस आधार पर कि वह मान संयोग से कहाँ दिखाई दिया। हेडर में bearer token सीक्रेट है। क्वेरी स्ट्रिंग में signed webhook URL भी सीक्रेट है। JSON बॉडी में ईमेल पता निजी डेटा हो सकता है। रिपॉज़िटरी का नाम टार्गेट पहचानकर्ता हो सकता है, जिसे सुरक्षित निर्णय के लिए दिखाना ज़रूरी है।

छोटी शब्दावली रखें और उसे लगातार लागू करें:

  • public: जैसा है, वैसा दिखाना सुरक्षित है।
  • internal: प्रभावित ऑब्जेक्ट की पहचान के लिए दिखाएं, लेकिन इसे व्यापक लॉग में कॉपी न करें।
  • personal: केवल उपयोगी न्यूनतम रूप दिखाएं, आमतौर पर लेबल और मान का कुछ हिस्सा।
  • secret: मान को कार्ड, लॉग, क्लिपबोर्ड या त्रुटि टेक्स्ट में कभी न दिखाएं।
  • opaque: केवल तब स्वीकृत alias या स्थिर, गैर-सीक्रेट संदर्भ दिखाएं जब उससे टार्गेट अलग पहचानने में मदद मिले।

कॉल करने वालों को बिना सीमा वाला safe_to_display: true विकल्प न दें। कोई व्यक्ति डिबगिंग आसान बनाने के लिए इसका उपयोग करेगा और फिर उसे production credentials संभालने वाले रास्ते में छोड़ देगा। एजेंट द्वारा कार्रवाई बनाए जाने की सीमा पर ठोस वर्गीकरण ज़रूरी करें।

हेडर में नाम और उद्देश्य दिखाएं, मान लगभग कभी नहीं

हेडर के नाम अक्सर ऑपरेटर को हेडर के मानों से कहीं अधिक बताते हैं। मानों में अक्सर वही सामग्री होती है जिसे इंसानी सतह पर नहीं रखना चाहिए।

हर सुरक्षा-संबंधी हेडर का नाम और छोटा उद्देश्य लेबल दिखाएं। उदाहरण के लिए:

Headers
Authorization: bearer credential from vault
Idempotency-Key: generated request identifier
X-Request-Reason: "refund requested by finance"
Content-Type: application/json

पहली लाइन बताती है कि अनुरोध प्रमाणित होगा, और क्रेडेंशियल का स्रोत यह जानने देता है कि प्रक्रिया अपेक्षित संग्रहित सीक्रेट का उपयोग कर रही है। Bearer eyJ... दिखाने से अप्रूवल में कोई लाभ नहीं होता। इससे सीक्रेट उजागर होने का रास्ता बनता है और लोग बेकार टोकन अंशों की तुलना करने लगते हैं।

OAuth के bearer-token specification में Authorization request header को पसंदीदा transmission method बताया गया है। इसकी सुरक्षा सलाह bearer tokens को ऐसे क्रेडेंशियल मानती है जिन्हें ट्रांज़िट और स्टोरेज दोनों में सुरक्षित रखना चाहिए। अप्रूवल UI के लिए भी यही सोच सही है: उपयोगकर्ता को पता होना चाहिए कि bearer credential लगाया जाएगा, क्रेडेंशियल को देखना नहीं।

हेडर के लिए ये नियम अपनाएं:

  1. व्यवहार प्रभावित करने वाले सुरक्षित प्रोटोकॉल मान, जैसे Content-Type, Accept और If-Match, दिखाएं।
  2. Authorization, Proxy-Authorization, Cookie, Set-Cookie, signature headers, API-key headers और secret के रूप में वर्गीकृत custom headers के नाम दिखाएं, मान नहीं।
  3. घोषित गैर-सीक्रेट बिज़नेस संदर्भ, जैसे X-Request-Reason, का सीमित और escaped मान तभी दिखाएं जब वह छोटा हो और उसमें निजी या सीक्रेट सामग्री न आ सके।
  4. जब किसी हेडर की अनुपस्थिति निर्णय बदलती हो, तो यह भी दिखाएं कि हेडर मौजूद नहीं है। overwrite ऑपरेशन में If-Match का न होना महत्वपूर्ण हो सकता है।
  5. डिफ़ॉल्ट रूप से सभी हेडर रेंडर न करें। रिक्वेस्ट लाइब्रेरी शोर जोड़ती हैं और शोर उस एक हेडर को छिपा देता है जो कार्रवाई बदलता है।

एक आम खराब डिज़ाइन सीक्रेट के पहले और आखिरी चार अक्षर दिखाता है: sk_live_...9a31। यह सावधान लगता है, लेकिन छोटी वैल्यू, structured values, test keys और पहले कहीं लीक हो चुके मानों के लिए असुरक्षित है। इससे लोग यह भी समझते हैं कि उन्हें सीक्रेट के टुकड़े पहचानने चाहिए। मान की जगह stored API credential या request signature जैसा प्रकार संबंधी वक्तव्य दें।

हेडर छिपे हुए टार्गेट पहचानकर्ता भी हो सकते हैं। tenant-routing header, impersonation header या X-Account-ID यह बदल सकता है कि प्रभाव किस पर पड़ेगा। केवल हेडर होने के कारण उसे न छिपाएं। उसकी भूमिका और सुरक्षित टार्गेट लेबल दिखाएं: X-Account-ID: account "Northwind production"। अगर opaque identifier को सुरक्षित लेबल से नहीं जोड़ सकते, तो बताएं कि opaque account identifier इस्तेमाल होगा और संवेदनशील कार्रवाई के लिए अधिक सोच-समझकर अप्रूवल लें।

क्वेरी स्ट्रिंग को जितना मिलता है, उससे अधिक संदेह से देखें

क्वेरी स्ट्रिंग URL में दिखाई देती है, टर्मिनल में कॉपी होती है, त्रुटि रिपोर्ट में जा सकती है और अक्सर ऐसे इंफ्रास्ट्रक्चर द्वारा लॉग की जाती है जो रिक्वेस्ट बॉडी देखता ही नहीं। यही सुविधा कारण है कि अप्रूवल कार्ड को इसके साथ सावधानी से व्यवहार करना चाहिए।

RFC 9110 चेतावनी देता है कि URI की जानकारी references, logs और अन्य माध्यमों से उजागर हो सकती है। वह भेजने वालों को HTTP target URI में संवेदनशील जानकारी रखने से बचने की सलाह देता है। यह केवल मानक की अमूर्त चिंता नहीं है। पूरा क्वेरी स्ट्रिंग रेंडर करने वाला कार्ड उस मान के लिए एक और disclosure channel बन सकता है, जिसे शुरू से URI में होना ही नहीं चाहिए था।

केवल इसलिए सभी क्वेरी मानों को सुरक्षित न मानें कि अनुरोध GET है। नाम, घोषित प्रकार और ऑपरेशन के संदर्भ का उपयोग करें।

GET  api.crm.example  /v2/contacts
Query
status = "active"
owner = "sales-west"
include = "notes"
access_token = [secret, hidden]
search = [private text, hidden]

status और include अक्सर निर्णय के लिए उपयोगी जानकारी हैं। search में नाम, ईमेल पते, चिकित्सकीय शब्द या स्थानीय फ़ाइलों से निकाली गई कोई भी सामग्री हो सकती है। access_token स्पष्ट रूप से सीक्रेट है, लेकिन डिज़ाइन केवल स्पष्ट नामों पर निर्भर नहीं रह सकता। कुछ API sig, token, key, code, state, assertion या बिना किसी चेतावनी वाले vendor-specific parameter का उपयोग करती हैं।

मैनिफ़ेस्ट ने स्पष्ट रूप से वर्गीकृत न किया हो, तो क्वेरी मानों को डिफ़ॉल्ट रूप से सीक्रेट मानें। यह कई API explorers से जानबूझकर अधिक सख्त है। अप्रूवल UI debugging console नहीं है। उसके पाठक को अनुरोध अप्रूव करने के लिए पर्याप्त जानकारी चाहिए, byte-for-byte reconstruction नहीं।

जब duplicate parameters और उनका क्रम अर्थ बदलते हों, तो दोनों सुरक्षित रखें। क्वेरी स्ट्रिंग को dictionary में बदलने वाला रेंडरर चुपचाप tag=urgent&tag=finance खो सकता है, दोहराए गए मान बदल सकता है या signing bug को अदृश्य बना सकता है। entries की सूची दिखाएं, map नहीं:

Query
label = "finance"
label = "urgent"
expand = "line_items"

अगर छिपा हुआ क्वेरी फ़ील्ड request routing या authorization बदलता है, तो यह बताएं। signature = [signed request value, hidden] खाली पंक्ति से बेहतर संकेत देता है। अगर क्वेरी में opaque share link है, तो token उजागर न करें। ज्ञात हो तो resource label दिखाएं, जैसे shared report: Q2 forecast, और अन्यथा shared-resource token present लिखें।

रिडैक्शन के बाद भी बॉडी का आकार बना रहना चाहिए

जाँचें कि एजेंट ने क्या किया
वॉल्ट कुंजी के बिना sp audit verify से एन्क्रिप्टेड ऑडिट चेन को ऑफलाइन सत्यापित करें।

जो बॉडी केवल [redacted] बन जाए, वह ऑपरेटर को लगभग कुछ नहीं बताती। जो बॉडी हर फ़ील्ड शब्दशः दिखाए, वह अंततः ऐसी सामग्री लीक कर देगी जिसे अप्रूवल सतह तक पहुँचना ही नहीं चाहिए था। सही उत्तर structural redaction है।

बॉडी को typed tree के रूप में रेंडर करें। object keys, array counts, data types, सुरक्षित enum values और चुने हुए target labels बनाए रखें। असुरक्षित leaves को समझाने वाले marker से बदलें।

{
  "invoice": "inv_7KD2",
  "amount": {"currency": "USD", "minor_units": 12500},
  "reason": "duplicate charge",
  "customer_note": "[private text, 84 characters]",
  "payment_method": {
    "id": "[opaque payment method]",
    "token": "[secret, hidden]"
  }
}

इस रूप में ऑपरेटर देख सकता है कि कार्रवाई 125.00 USD का रिफंड करेगी, उसका कारण दिया गया है और एक निजी नोट मशीन से बाहर जाएगा। यह तय करने के लिए पर्याप्त है कि अनुरोध इच्छित काम जैसा है या नहीं। कार्ड नोट या token उजागर नहीं करता।

जब संख्या ही प्रभाव हो, तो संख्या बनाए रखें। भुगतान राशि, सीटों की संख्या, retention period, rate limits, permission levels और deletion counts छिपाने से अप्रूवल अर्थहीन हो जाता है। इन मानों को incidental data नहीं, action parameters मानें। DELETE बॉडी में { "purge": true } हो, तो purge: true दिखना चाहिए, वरना कार्ड अपरिवर्तनीय हिस्से को छिपा रहा है।

टेक्स्ट के लिए अलग नियम चाहिए। free-form text में source code, customer data, pasted secrets या कार्रवाई बदलने वाले निर्देश हो सकते हैं। मनमाना preview दिखाना आकर्षक है, क्योंकि इससे ऑपरेटर बेतुकी सामग्री पकड़ सकता है। लेकिन इससे अप्रूवल विंडो data exfiltration surface बन जाती है। unclassified free text के लिए उसका फ़ील्ड नाम, character count और destination role दिखाएं। bounded excerpt तभी दिखाएं जब caller ने फ़ील्ड को public या internal चिह्नित किया हो और रेंडरर control characters को escape करता हो।

Arrays में counts और summaries चाहिए। यह खराब है:

recipients: [redacted]

यह बेहतर है:

recipients: 37 email addresses [personal values hidden]

destructive operation में संख्या निर्णय बदलती है। access change में role और count दिखाएं: add 4 members to role: billing-admin। अगर members internal identifiers हैं और अप्रूवर को अलग-अलग पहचानना ज़रूरी है, तो raw IDs के बजाय स्वीकृत display names या aliases दिखाएं।

केवल फ़ील्ड नाम से sensitivity का अनुमान कभी न लगाएं। password, token और secret के लिए hard deny list ज़रूरी है, लेकिन content, message, value, data और metadata में भी वही सामग्री हो सकती है। वर्गीकरण schema, action builder या स्पष्ट field annotation से आना चाहिए। नाम-आधारित फ़िल्टर अंतिम सुरक्षा पंक्ति है, मुख्य डिज़ाइन नहीं।

टार्गेट पहचानकर्ता स्पष्ट हों, पूरी तरह उजागर नहीं

टार्गेट वह object है जो अनुरोध को उसका प्रभाव देता है। वह path segment, header, query parameter, JSON field या SSH command argument में हो सकता है। कच्चा identifier सुरक्षित रूप से न दिखाया जा सके, तब भी कार्ड में टार्गेट दिखाई देना चाहिए।

टार्गेट के machine reference और human display form को अलग रखें:

{
  "role": "repository",
  "raw_reference": "repo_01HZX8M9...",
  "display": "payments-service",
  "scope": "production",
  "sensitivity": "internal"
}

raw reference execution के लिए ज़रूरी हो सकता है, लेकिन कार्ड में display form होना चाहिए। अगर कार्रवाई permissions बदलती है, तो संबंध को स्पष्ट करने वाला वाक्य लिखें: Grant deploy permission on payments-service production to the release automation account. कार्ड को अप्रूवर से opaque IDs याद रखने की उम्मीद नहीं करनी चाहिए।

कभी-कभी raw value ही एकमात्र उपलब्ध पहचान होती है। इसे हल करने के लिए पूरा मान न दिखाएं। protected value से बनाया गया local alias या छोटा approval reference जैसे स्थिर, non-reversible reference चुनें। truncated identifier को hash न कहें, जब तक वह वास्तविक cryptographic digest न हो और आपको collision तथा correlation के परिणाम समझ न आते हों। कई मामलों में customer record [opaque reference 4F8C], cus_Qa8J7kW2m9 को एक नज़र में सत्यापित कर पाने का झूठा आभास देने से अधिक ईमानदार है।

blast radius तय करने वाले identifiers को ज़रूरत से ज़्यादा न छिपाएं। DELETE /projects/{project}/members में project छिपा हो, तो हर व्यक्तिगत member identifier mask होने के बावजूद कार्ड ख़तरनाक है। project display name, environment और प्रभावित members की संख्या दिखाएं। संवेदनशील व्यक्तिगत मान छिपे रहने दें।

यहाँ स्पष्ट अंतर है: सीक्रेट छिपाने से confidentiality सुरक्षित होती है; टार्गेट छिपाने से authorization कमज़ोर होता है। टीमें अक्सर दोनों को «redaction» कह देती हैं। ये अलग काम हैं और कार्ड को इनके लिए अलग नियम चाहिए।

अप्रूवल का दायरा कार्ड की जानकारी से मेल खाना चाहिए

आउटबाउंड कार्रवाइयों से पहले गेट लगाएं
MCP-सक्षम एजेंट और बाहरी HTTP या SSH लक्ष्यों के बीच एक्शन गेटवे रखें।

पूरा कार्ड जितना बताता है, उससे अधिक को authorize नहीं करना चाहिए। अगर किसी व्यक्ति ने एक repository पढ़ने का अनुरोध अप्रूव किया है, तो वही अप्रूवल बाद में repository settings बदलने वाले अनुरोध पर चुपचाप लागू नहीं हो सकता, भले दोनों एक ही agent process से आए हों।

per-session approval और per-call approval अलग सवालों के जवाब देते हैं। per-session approval पूछता है कि क्या यह signed process इस रन के दौरान gateway के ज़रिए कार्रवाई कर सकता है। per-call approval पूछता है कि क्या यह खास outbound action, इस target और effect के साथ, किया जा सकता है। दोनों को एक बड़ी permission में मिलाने से पहले कार्ड पर असंभव बोझ पड़ता है।

परिणामों पर आधारित escalation rule अपनाएं। ज्ञात सेवा से पढ़ने की कार्रवाई session grant में आ सकती है। protected credential का उपयोग करने, access बदलने, message भेजने, financial commitment बनाने या data delete करने वाली कॉल के लिए concrete request manifest से जुड़ा कार्ड चाहिए।

अप्रूवल परिणाम को visible card text से नहीं, canonical action digest से बाँधें। digest में method, normalized destination, target references, classified non-secret parameters और protected fields का representation होना चाहिए। उसमें इतना metadata भी हो कि rendering के बाद बदली गई रिक्वेस्ट पकड़ी जा सके। निर्णय को केवल screenshot-friendly summary से न बाँधें।

उदाहरण के लिए, इन दोनों कॉल के लिए अलग अप्रूवल चाहिए, भले लापरवाह रेंडरर उन्हें एक जैसा दिखा दे:

POST /v1/roles/grant
body: role = "viewer", subject = "build-bot"

POST /v1/roles/grant
body: role = "owner", subject = "build-bot"

role कोई ऐसा विवरण नहीं है जिसे collapsed JSON view में छिपा दिया जाए। वही कार्रवाई है। अगर इंजीनियर कहे कि कार्ड बहुत व्यस्त हो गया है, तो पहले सजावटी protocol data हटाएं। उस फ़ील्ड को न हटाएं जो तय करती है कि एजेंट अकाउंट अपने कब्ज़े में ले सकता है या नहीं।

Sallyport इसी कारण session authorization को per-call keys से अलग रखता है। session decision नए agent process की पहचान और प्रवेश तय कर सकता है, जबकि हर-use approval के लिए चिह्नित credential व्यक्तिगत कार्रवाई से पहले फिर पूछता है।

रिडैक्शन की विफलता अक्सर रेंडरिंग से पहले शुरू होती है

संवेदनशील कुंजियों को हर कॉल पर अप्रूव करें
जब हर आउटबाउंड कार्रवाई के लिए मानव निर्णय ज़रूरी हो, तब किसी कुंजी को हर बार अप्रूवल के लिए चिह्नित करें।

मान लें कि किसी एजेंट से signature के लिए contract भेजने को कहा गया। वह यह अनुरोध बनाता है:

POST /v1/envelopes?template=msa&signature=QmFzZTY0U2lnbmVkVmFsdWU HTTP/1.1
Host: api.signing.example
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json

{
  "recipients": [
    {"name": "Maya Chen", "email": "[email protected]"}
  ],
  "subject": "MSA for Northwind",
  "message": "Please sign the attached agreement.",
  "document": "JVBERi0xLjQK..."
}

सतही implementation raw request को format करता है, Authorization value बदलता है और लंबी lines को काट देता है। कार्ड अब query string में signature, recipient का email और शायद text के रूप में encoded document का शुरुआती हिस्सा उजागर करता है। truncation redaction नहीं है। इससे leak कम अनुमानित होता है, समाप्त नहीं।

सही manifest पहले हिस्सों को अलग करता है:

POST api.signing.example /v1/envelopes
Action: send contract for signature
Target: template "msa"
Recipients: 1 email address [personal value hidden]
Subject: "MSA for Northwind"
Message: public text, 39 characters
Document: 1 PDF attachment [content hidden]
Credential: bearer credential from vault
Request signature: present, hidden

यह कार्ड ऑपरेटर को गलत host, गलत template, अनपेक्षित recipient count या गलती से भेजे जाने वाली रिक्वेस्ट पकड़ने देता है। यह credential, signature, email address या document bytes उजागर नहीं करता।

ख़तरनाक संस्करण इसलिए विफल नहीं हुआ कि उसके masking pattern में signature छूट गया। वह इसलिए विफल हुआ क्योंकि सिस्टम ने HTTP request को display-ready text मान लिया। रेंडरर को secret-bearing blob मिला, जिसमें field types, target roles और कार्रवाई का अर्थ बताने वाले मानों की कोई जानकारी नहीं थी।

ऐसा रेंडरर बनाएं जो सुरक्षित रूप से असफल हो

रेंडरर केवल structured input स्वीकार करे, allowlisted display rules लागू करे और unclassified outbound fields वाली कार्रवाई को रेंडर करने से मना कर दे। यह सख्त लगता है, क्योंकि यह सख्त है। unclassified field उस निर्णय का नाम है जिसे किसी ने टाल दिया, और अप्रूवल के समय अनुमान लगाना बहुत देर हो चुकी होती है।

एक व्यावहारिक rendering contract के तीन चरण हैं:

  1. credential injection और transport encoding से पहले planned action को manifest में normalize करें।
  2. सत्यापित करें कि हर फ़ील्ड में type, sensitivity label और display rule है। unknown headers, query values और body leaves को अस्वीकार करें, जब तक caller उन्हें स्पष्ट रूप से सुरक्षित hidden representation में न भेजे।
  3. fixed card layout रेंडर करें, जिसमें destination, action, targets, effect और protected-field notices के लिए प्रमुख स्थान हो।

visible values में HTML, terminal control characters, markdown या arbitrary Unicode direction controls की अनुमति न दें। layout से पहले उन्हें escape करें। कोई malicious value recipient: [email protected] को भ्रामक लाइन में बदलने, fake buttons बनाने या target identifier का दृश्य क्रम बदलने में सक्षम नहीं होनी चाहिए।

display budgets भी तय करें। public string 50,000 characters की हो सकती है और कार्ड को अनुपयोगी बना सकती है। field type के अनुसार visible text की सीमा तय करें, उसके छोटा किए जाने की सूचना दें और केवल उसी content के लिए नियंत्रित detail view रखें जिसे manifest ने safe घोषित किया हो। «show full request» को सार्वभौमिक escape hatch न बनाएं।

रेंडरर को केवल सामान्य API calls से नहीं, hostile examples से भी जाँचें। हर संभव स्थान पर bearer token, duplicated query names, nested arrays वाला JSON, percent-encoded delimiters वाला path segment, empty secret, short secret, बहुत लंबा text field और newlines वाला मान शामिल करें। उन requests को भी जाँचें जिनका हानिकारक अर्थ boolean, count, role या destination host में छिपा हो।

अंत में, approval ने क्या कवर किया यह दर्ज करें, लेकिन plaintext secrets को evidence trail में कॉपी न करें। Sallyport के activity और session records एक ही encrypted, hash-chained audit log से बनते हैं और उसका offline verification command vault key के बिना chain जाँच सकता है। यही लक्ष्य होना चाहिए: auditability यह साबित करे कि क्या हुआ, लेकिन दूसरा ऐसा vault न बन जाए जिसमें दोबारा इस्तेमाल किए जा सकने वाले credentials भरे हों।

कार्ड को गलत कार्रवाई को गलत दिखाना चाहिए। अगर कोई व्यक्ति credential वाले अनुरोध को उसके destination, effect और target देखे बिना अप्रूव कर सकता है, तो सिस्टम ने वही तथ्य छिपा दिए हैं जिनसे उस व्यक्ति को सुरक्षा करनी थी।

सामान्य प्रश्न

API अप्रूवल प्रॉम्प्ट में कौन-सी जानकारी दिखनी चाहिए?

मेथड, डेस्टिनेशन होस्ट, पाथ का अर्थपूर्ण ढाँचा और भेजे जा रहे फ़ील्ड के नाम दिखाएं। क्रेडेंशियल, सेशन टोकन, साइन किए गए मान, निजी सामग्री और ऐसे पहचानकर्ता छिपाएं जो कार्रवाई को अप्रूव करने के लिए ज़रूरत से ज़्यादा जानकारी दें।

क्या अप्रूवल कार्ड में पूरा URL दिखाना चाहिए?

आमतौर पर नहीं। पूरा URL क्वेरी स्ट्रिंग में सीक्रेट डाल सकता है और निजी अकाउंट, दस्तावेज़ या टेनेंट पहचानकर्ता उजागर कर सकता है। होस्ट और सामान्यीकृत पाथ दिखाएं, फिर चुने हुए क्वेरी पैरामीटर के नाम और सुरक्षित मान अलग से दिखाएं।

क्या अप्रूवल प्रॉम्प्ट में API टोकन के मान दिखाने चाहिए?

मान पूरी तरह छिपाएं, जब तक कि छोटा प्रीफ़िक्स या सफ़िक्स निर्णय को प्रभावित न करता हो। बेयरर क्रेडेंशियल, साइन किए गए हेडर, कुकी और API कुंजियों के लिए फ़ील्ड का नाम आमतौर पर पर्याप्त है। ऑपरेटर को यह जानना ज़रूरी है कि क्रेडेंशियल इस्तेमाल होगा, यह नहीं कि वह क्या है।

अप्रूवल प्रॉम्प्ट में संवेदनशील JSON फ़ील्ड को कैसे छिपाएं?

फ़ील्ड का नाम, प्रकार और सुरक्षित संरचनात्मक तथ्य दिखाएं: फ़ील्ड मौजूद है या नहीं, खाली है या नहीं, ज़रूरत होने पर उसकी लंबाई, और secret या opaque identifier जैसी अपरिवर्तनीय श्रेणी। ऐसा रिवर्सिबल मास्क न लगाएं जिससे छोटे मान को फिर से बनाया जा सके।

क्या क्वेरी स्ट्रिंग पैरामीटर दिखाना सुरक्षित है?

क्वेरी पैरामीटर को वर्गीकृत किए जाने तक अविश्वसनीय मानें। उनके नाम उपयोगी हो सकते हैं, लेकिन मानों में अक्सर क्रेडेंशियल, साइन किए गए अनुरोध, खोज शब्द, ईमेल पते, रेफ़रल कोड या एप्लिकेशन स्थिति होती है।

अप्रूवल कार्ड में टार्गेट पहचानकर्ता क्या होता है?

टार्गेट पहचानकर्ता वह बताता है कि कौन-सी वस्तु प्रभावित होगी, जैसे संगठन, रिपॉज़िटरी, एनवायरनमेंट, इनवॉइस या अकाउंट। जब वह ऑथराइज़ेशन निर्णय बदलता हो, तब उसे दिखाई देना चाहिए। लेकिन अगर वह निजी या सीक्रेट पहचानकर्ता उजागर करता है, तो उसे सामान्यीकृत या छिपा दें।

क्या रिडैक्शन किसी ख़तरनाक अनुरोध को अप्रूव करने के लिए सुरक्षित बना देता है?

नहीं। रिडैक्शन कार्ड पढ़ने वाले व्यक्ति को सीक्रेट देखने से बचाता है, अनुरोध की शक्ति कम नहीं करता। कार्ड में कार्रवाई, डेस्टिनेशन, स्कोप और अपरिवर्तनीय प्रभाव इतने स्पष्ट होने चाहिए कि अप्रूवल का वास्तविक अर्थ रहे।

क्या एक अप्रूवल एजेंट के हर अनुरोध को कवर कर सकता है?

डिफ़ॉल्ट रूप से एजेंट के हर अनुरोध को अप्रूव न करें, अगर अलग-अलग कॉल में महत्वपूर्ण अंतर हो सकता है। सेशन अप्रूवल यह तय कर सकता है कि कौन चल रहा है, जबकि पैसे खर्च करने, डेटा हटाने, एक्सेस बदलने या विशेष रूप से चिह्नित क्रेडेंशियल इस्तेमाल करने वाली कॉल के लिए अलग निर्णय होना चाहिए।

डेवलपर अप्रूवल-कार्ड रिडैक्शन कैसे लागू करें?

टाइप किए गए फ़ील्ड और संवेदनशीलता लेबल वाली आंतरिक canonical request representation रखें, फिर उससे अलग अप्रूवल व्यू बनाएं। कच्ची रिक्वेस्ट स्ट्रिंग लेकर अंत में कुछ रेगुलर एक्सप्रेशन लगाने से कार्ड कभी न बनाएं।

अप्रूवल के बाद ऑडिट लॉग में क्या दर्ज करना चाहिए?

प्लेनटेक्स्ट सीक्रेट के बजाय कार्रवाई का ढाँचा और सुरक्षित संदर्भ दर्ज करें। समीक्षक यह पता लगा सके कि किस एजेंट प्रोसेस ने कौन-सा अनुरोध किया, वह कहाँ गया, कौन-सी कार्रवाई की कोशिश हुई और किसी व्यक्ति ने उसे अप्रूव किया या नहीं। ऑडिट ट्रेल को किसी दूसरे सीक्रेट स्टोर में न बदलें।

Sallyport

Sallyport आपके AI एजेंट के लिए API कॉल और SSH कमांड चलाता है। कुंजियाँ आपके Mac पर एक लोकल वॉल्ट में रहती हैं; आप हर रन को स्वीकृत करते हैं और हर क्रिया एक सीलबंद जर्नल में दर्ज होती है।

© 2026 Sallyport · Apache-2.0 के तहत ओपन सोर्स · Oleg Sotnikov