8 मिनट पढ़ें

macOS प्रोसेस पहचान के लिए केवल Team ID काफी नहीं

Team ID, signing identifier, designated requirements, paths और unsigned builds के सख्त प्रबंधन के साथ macOS प्रोसेस पहचान का व्यावहारिक मॉडल।

macOS प्रोसेस पहचान के लिए केवल Team ID काफी नहीं

किस macOS प्रोसेस को कोई सीक्रेट इस्तेमाल करने दिया जाए, यह तय करने के लिए केवल Team ID काफी नहीं है। यह Apple डेवलपर टीम की पहचान करता है, उस टीम के किसी एक executable की नहीं। अगर आप केवल Team ID को अधिकृत करते हैं, तो उस टीम के हर सही तरह से साइन किए ऐप, हेल्पर, टेस्ट यूटिलिटी और भविष्य के बाइनरी को वही एक्सेस मिल सकती है।

मजबूत ऑथराइज़ेशन पहचान में signing authority के साथ signing identifier शामिल होता है, ऐसा requirement दर्ज होता है जो वैध अपडेट के बाद भी चलता रहे और उसकी तुलना उसी प्रोसेस से होती है जो वास्तव में अनुरोध कर रहा है। approval card और audit record में executable path रखना चाहिए, लेकिन ऑथराइज़ेशन का फैसला उस पर नहीं टिका होना चाहिए। unsigned और ad hoc signed development builds के लिए कोई चुपचाप अपवाद नहीं, बल्कि अलग और स्पष्ट रूप से कमजोर रास्ता चाहिए।

सीक्रेट की सीमा पर यह फर्क सबसे अहम होता है। कोड सिग्नेचर से पता चल सकता है कि प्रोसेस को किसने साइन किया और signer ने प्रोग्राम का कौन-सा नाम बताया। इससे यह नहीं पता चलता कि उस प्रोसेस को database password मिलना चाहिए, उसका मौजूदा अनुरोध उचित है, या उसी डेवलपर के दूसरे प्रोग्राम को भी वही अनुमति मिलनी चाहिए। पहचान ऑथराइज़ेशन का एक इनपुट है, उसका विकल्प नहीं।

Team ID signer की पहचान करता है, प्रोग्राम की नहीं

Team ID एक उपयोगी लेकिन व्यापक सवाल का जवाब देता है: इस कोड में इस्तेमाल signing identity किस Apple डेवलपर टीम ने जारी की? Apple की जारी की हुई developer certificates के लिए requirement language, leaf certificate के organizational unit field के माध्यम से Team ID दिखाती है। टूल सिग्नेचर विवरण में TeamIdentifier मान भी दिखा सकते हैं।

इसे बाहरी ऐप बंडल के बजाय सटीक executable पर चलाएं:

codesign -dvvv /Applications/Example.app/Contents/MacOS/Example 2>&1

आउटपुट का उपयोगी हिस्सा इस तरह दिखता है:

Executable=/Applications/Example.app/Contents/MacOS/Example
Identifier=dev.example.agent
Authority=Developer ID Application: Example Developer (A1B2C3D4E5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=A1B2C3D4E5

वैध Team ID से आपको signer scope मिलता है। इससे दूसरी टीमों के साइन किए बाइनरी बाहर हो जाते हैं, इसलिए कोई असंबंधित डेवलपर वही signing identifier बताकर आपकी जांच पास नहीं कर सकता। Apple अपने SigningIdentifier दस्तावेज़ में यही बात कहता है: कई signer एक signing identifier का दावा कर सकते हैं, इसलिए गैर-Apple कोड की सुरक्षित जांच में TeamIdentifier constraint और उपयुक्त validation category भी चाहिए।

उलटा निष्कर्ष जाल है। एक टीम कई असंबंधित उत्पादों और एक उत्पाद के कई घटकों को साइन कर सकती है। किसी ऐप, उसके privileged helper, login item, command line tool, XPC service और आंतरिक diagnostic का Team ID समान हो सकता है। compromised signing service इसी signer scope में एक और बाइनरी बना सकती है। टीम सदस्यता इनमें से किसी को अलग नहीं करती।

इसीलिए सीक्रेट के लिए Team ID == approved team बहुत व्यापक है। यह ऐसा है जैसे किसी कंपनी के हर कर्मचारी को केवल इसलिए एक्सेस दे देना कि उसके बैज एक ही जारीकर्ता ने दिए हैं। जारीकर्ता अहम है, बैज पर नाम भी अहम है।

कुछ सीमित मामलों में सिर्फ Team ID जानबूझकर लिया जाता है। कोई developer tool उपयोगकर्ता की अपनी टीम से साइन किए हर घटक को अस्थायी local fixture तक पहुंच दे सकता है। यह team trust policy है, process identity नहीं और मंजूरी के टेक्स्ट में यह साफ लिखा होना चाहिए। इसे application नाम के फ़ील्ड में न रखें और बाद में उसका अधिकार-क्षेत्र न भूल जाएं।

Signing identifier टीम के भीतर प्रोग्राम अलग करता है

Signing identifier, Team ID में छूटा हुआ प्रोग्राम वाला आयाम देता है। codesign इसे Identifier के रूप में दिखाता है। bundled app के लिए यह अक्सर bundle identifier होता है, लेकिन Apple साफ कहता है कि यह समानता जरूरी नहीं। मान signer चुनता है और command line executables के पास ऐप बंडल हुए बिना भी identifier हो सकते हैं।

Team ID और signing identifier को साथ रखने पर न्यूनतम पहचान काफी बेहतर होती है:

team_id = A1B2C3D4E5
signing_identifier = dev.example.agent

इस जोड़े का अर्थ है "टीम A1B2C3D4E5 द्वारा साइन किया गया dev.example.agent नाम वाला प्रोग्राम।" दूसरी टीम identifier कॉपी कर सकती है, लेकिन team constraint पूरा नहीं कर सकती। स्वीकृत टीम के किसी दूसरे प्रोग्राम का identifier अलग होना चाहिए, इसलिए उसे मेल नहीं खाना चाहिए।

उस आखिरी वाक्य में "होना चाहिए" महत्वपूर्ण है। एक टीम अपने identifiers नियंत्रित करती है और किसी identifier को दोबारा इस्तेमाल कर सकती है। कोई लापरवाह build configuration मुख्य ऐप का identifier embedded helper को दे सकती है। कोई दुर्भावनापूर्ण या compromised signer स्वीकृत मान कॉपी कर सकता है। यह जोड़ा अधिकार को इस धारणा के साथ सीमित करता है कि signer अपने signing credentials और identifier namespace, दोनों की रक्षा करता है।

फिर भी macOS पर update-stable third-party identity के लिए यह सामान्य सीमा है। Code hashes अधिक विशिष्ट हैं, लेकिन हर वैध रिलीज़ में वे बदलते हैं। Certificate fingerprints भी निरंतरता के लिए असुविधाजनक हैं, क्योंकि certificates समाप्त और rotate होते हैं। Team ID और signing identifier उस निरंतरता को व्यक्त करते हैं जो अधिकतर ऐप चाहते हैं: इस signer के इस प्रोग्राम के भविष्य के संस्करण स्वीकार करें, signer की पूरी सूची नहीं।

कनेक्ट कर सकने वाले हर executable की जांच करें। containing app से helper का identifier न मान लें। Apple TN3127 ऐप और उसके embedded command line tool से यही बात समझाता है: उनका Team ID एक है, पर code signing identifiers अलग हैं और Apple इस अलगाव को best practice कहता है। अनुरोध helper शुरू करता है तो सीमा पर उसकी पहचान मायने रखती है।

Identifiers के साथ byte-for-byte व्यवहार भी जरूरी है। Apple के मौजूदा SigningIdentifier दस्तावेज़ के अनुसार तुलना में Unicode normalization नहीं होता। Code Signing Services से मिला मान opaque string या byte sequence की तरह सहेजें और तुलना करें। इसे lowercase करना, normalize करना या CFBundleIdentifier से फिर बनाना अलग नियमों वाली दूसरी identity system बना देता है।

Designated requirement update-stable identity को दर्ज करता है

Designated requirement, जिसे आम तौर पर DR कहते हैं, macOS की अपनी अभिव्यक्ति है जिससे तय होता है कि अभी दिख रहा कोड पहले देखे गए कोड जैसा ही है या नहीं। इसमें signing identifier और signing authority की शर्तें साथ होती हैं। अलग-अलग फ़ील्ड देखने की तुलना में यह आपके ऑथराइज़ेशन ऑब्जेक्ट के अधिक करीब है।

Apple TN3127 के अनुसार DR वह तरीका है जिससे कोड बताता है कि दूसरा पक्ष उसे फिर कैसे पहचान सकता है। technote की व्यावहारिक जांच अपडेट है: version 1.3 को version 1.2 के लिए दर्ज पहचान पूरी करनी चाहिए, भले उसके bytes बदल गए हों। साथ ही अलग उत्पाद को असफल होना चाहिए। टिकाऊ secret grant को ठीक इसी तनाव को सुलझाना होता है।

DR दिखाने के लिए चलाएं:

codesign -d -r- /Applications/Example.app/Contents/MacOS/Example 2>&1

Developer ID परिणाम आम तौर पर ऐसा दिखता है, हालांकि certificate विवरण signing route पर निर्भर करते हैं:

Executable=/Applications/Example.app/Contents/MacOS/Example
designated => anchor apple generic and identifier "dev.example.agent" and certificate leaf[subject.OU] = "A1B2C3D4E5"

उस display string को अपने बनाए फ़ील्ड में पार्स करके Apple के evaluator की नकल न करें। TN3125 चेतावनी देता है कि signature structures बदलती रहती हैं और validation के लिए codesign या Code Signing Services का निर्देश देता है। requirement लेने के लिए SecCodeCopyDesignatedRequirement और code जांचने के लिए SecCodeCheckValidity या मौजूदा process requirement APIs इस्तेमाल करें। प्लेटफ़ॉर्म को अपना requirement form compile और compare करने दें।

इससे एक सूक्ष्म बात निकलती है: कोड का अपना DR एक दावा है, ऑथराइज़ेशन निर्णय नहीं। signer explicit DR दे सकता है और embedded DR न होने पर Code Signing Services एक बना सकता है। आपका सिस्टम फिर भी तय करता है कि कौन-सा requirement दर्ज होगा और उसका scope grant के अनुरूप है या नहीं। DR पढ़कर "trusted" घोषित करना, पहचान सामग्री और policy को गड्डमड्ड करता है।

सामान्य Developer ID software के लिए मंजूरी के समय validated DR दर्ज करना अच्छा default है। साथ में दिखाया गया Team ID और signing identifier audit fields में रखें ताकि इंसान निर्णय समझ सके। बाद की कॉल पर नया प्रिंट किया DR string समान है या नहीं देखने के बजाय live process की stored requirement से जांच करें। Requirement objects व्यवहार व्यक्त करते हैं, बराबर expressions का formatting समान होना जरूरी नहीं।

Distribution बदलावों को सोच-समझकर संभालें। TN3127 बताता है कि Mac App Store और Developer ID variants के default DR अपने आप compatible नहीं होते, जबकि Xcode इच्छित distribution forms को जोड़ने के लिए custom requirements इस्तेमाल कर सकता है। रिलीज़ channel बदलने पर verifier को तुरंत व्यापक न करें। नए requirement को identity change मानें, उपयोगकर्ता को दिखाएं और नई मंजूरी लें, जब तक आपने साफ compatibility requirement डिज़ाइन और टेस्ट न किया हो।

Executable paths संदर्भ देते हैं, प्रमाण नहीं

Executable path ऑपरेटर को बताता है कि macOS को image कहां मिला। यह मंजूरी के लिए बेहतरीन संदर्भ है और निरंतरता का कमजोर साक्ष्य। फाइलें स्थान बदलती हैं, app translocation स्थान बदल सकती है, उपयोगकर्ता कई versions रखते हैं और package managers versioned paths में install करते हैं। दूसरी ओर, कोई हमलावर approved writable path पर फाइल बदल सके तो path-only grant पा सकता है।

परिचित path allowlist दोनों दिशाओं में विफल होती है। यह हानिरहित स्थान परिवर्तन के बाद उसी signed program को अस्वीकार करती है और hostile replacement के बाद अलग bytes को स्वीकार कर लेती है। owner और mode checks जोड़ने से replacement का कुछ जोखिम घटता है, मगर pathname cryptographic identity नहीं बन जाता।

पथ को इन तीन कामों के लिए रखें:

  • उपयोगकर्ता को दिखाएं कि किस installation ने अनुरोध शुरू किया।
  • किसी आश्चर्यजनक कॉल की जांच के लिए पर्याप्त संदर्भ दर्ज करें।
  • signature identity सफल होने के बाद वैकल्पिक location restriction लगाएं।

managed environments में आखिरी उपयोग उचित हो सकता है। आप approved DR की मांग कर सकते हैं और साथ ही executable का root-owned deployment directory के अंदर होना भी जरूरी कर सकते हैं। तब path पहले से पहचाने गए प्रोग्राम के चलने का स्थान सीमित करता है। वह गायब या अमान्य signature को कभी ठीक नहीं करता।

चल रहे प्रोसेस से वास्तव में जुड़े executable को resolve और record करें। client द्वारा दी string, जैसे argv[0], working directory, request में bundle path या environment variable पर भरोसा न करें। ये requester के कथन हैं। यदि आप पहले फाइल देखें और बाद में केवल सहेजे नाम के आधार पर प्रोसेस authorize करें, तो canonicalized path में भी race हो सकती है।

प्लेटफ़ॉर्म उपलब्ध कराए तो मैं audit data में original observed path और resolved path दोनों रखूंगा, क्योंकि symlinks और launch wrappers कई अनपेक्षित स्थितियों को समझाते हैं। इनमें से कोई भी durable identity tuple में शामिल नहीं होता। संगठन path restriction चुने तो उसे अलग location_constraint field में रखें, ताकि reviewers देख सकें कि यह identity पर चढ़ी policy है।

Pathname के बजाय live caller जांचें

हर उपयोग पर मंजूरी लें
किसी संवेदनशील कुंजी के लिए हर अनुरोध पर एक-क्लिक या Touch ID मंजूरी अनिवार्य करें।

ऑथराइज़ेशन जांच उसी प्रोसेस से जुड़नी चाहिए जो कनेक्शन बना रहा है। installation समय पर फाइल जांचना, उसका path सहेजना और बाद में वहां चलने वाली किसी भी चीज पर भरोसा करना time-of-check gap छोड़ देता है। अनुरोध आने के बाद उस path की मौजूदा फाइल जांचने पर भी आप चल रही image के बजाय replacement देख सकते हैं।

macOS Code Signing Services, disk पर मौजूद static code और चल रहे प्रोसेस से जुड़े dynamic code में अंतर करता है। Apple guest code के लिए code object लेने, अक्सर PID से, के लिए SecCodeCopyGuestWithAttributes और running process की requirement जांचने के लिए SecCodeCheckValidityWithProcessRequirement दस्तावेज़ित करता है। नया lightweight requirement API इच्छित TeamIdentifier और SigningIdentifier constraints स्पष्ट कर सकता है। production में codesign output scrape करने के बजाय अपने deployment target के लिए समर्थित API इस्तेमाल करें।

भरोसेमंद connection flow ऐसा दिखता है:

  1. IPC boundary से कर्नेल की दी process identity लें, जैसे accepted connection से जुड़ा audit token। request body में दिया PID स्वीकार न करें।
  2. उस live process को dynamic code object में resolve करें और platform API से उसका signature validate करें।
  3. उसी code object पर stored requirement या stored signer और identifier constraints जांचें।
  4. decision record में path, PID, जहां उपलब्ध हो process start identity, signature facts और validation result दर्ज करें।
  5. मंजूरी को connection या process lifetime से बांधें, फिर वह lifetime समाप्त होने पर उसे हटा दें।

सिर्फ PID टिकाऊ handle नहीं है, क्योंकि kernel process IDs दोबारा इस्तेमाल करता है। verifier PID पढ़े, इंतजार करे और फिर उसे देखे तो वह किसी दूसरे प्रोसेस की जांच कर सकता है। audit token में client की दी integer से ज्यादा process identity होती है और connection-scoped verification समय की खिड़की घटाता है। आपकी सीमा XPC हो, Unix domain socket हो या कोई और IPC mechanism, नियम स्थिर है: subject को peer के operating system वाले दृश्य से लें।

पहचान दिखाने से पहले validation करें। वरना approval card में malformed या invalid signature से निकले फ़ील्ड ऐसे दिख सकते हैं मानो macOS ने उनकी पुष्टि की हो। card को valid Developer ID signature और identifier text was present में फर्क दिखाना चाहिए। Validation विफल हो तो उसी मंजूरी के तहत path match पर वापस न जाएं।

Process trees के लिए साफ निर्णय चाहिए। signed agent /bin/sh शुरू करे और shell सीधे कनेक्ट करे तो peer shell है। ancestor तक अपने आप जाना और parent की पहचान उधार देना बदले हुए children या असंबंधित descendants को authorize कर सकता है। अगर architecture launcher को authorize करना चाहता है, तो मूल authenticated connection से capability बांधें और नियंत्रित channel से भेजें। parent PIDs चढ़कर इरादा फिर से न खोजें।

इसीलिए approved process के निकलने पर ऑथराइज़ेशन समाप्त होना चाहिए। सहेजी पहचान भविष्य की मंजूरी में मदद कर सकती है, लेकिन session grant स्वतंत्र होकर हमेशा के लिए किसी matching process से नहीं जुड़ना चाहिए। "हम इस प्रोग्राम को पहचानते हैं" और "यह रन अभी approved है" को अलग रखें।

Unsigned और ad hoc builds के लिए अलग policy चाहिए

Unsigned code का कोई designated requirement नहीं होता। ad hoc signed code का DR उसी खास code version से जुड़ा होता है, इसलिए rebuild पर पहचान बदल जाती है। Apple TN3127 के अनुसार macOS इन दोनों रूपों को versions के बीच भरोसेमंद तरीके से track नहीं कर सकता। secret broker को इस सीमा को बचाए रखना चाहिए, directory exception से ढंकना नहीं चाहिए।

Production secrets के लिए caller के पास वैध, update-stable signature न हो तो fail closed करें। यह सबसे साफ नियम और समझाने में सबसे आसान है। Developers local builds को Apple Development identity या ऐसी private signing identity से sign कर सकते हैं जिसका trust और requirements संगठन संभालता है। असुविधा आम तौर पर स्थायी unsigned exception से पैदा हुई अस्पष्टता से छोटी होती है।

Local development में कभी कमजोर mode चाहिए हो सकता है। इसे opt-in बनाएं, नाम development approval रखें और blast radius सीमित करें। अच्छा डिज़ाइन मंजूरी को मौजूदा process lifetime और exact code hash से बांधता है, unsigned या ad hoc को साफ दिखाता है, production secret sets को बाहर रखता है और हर rebuild के बाद फिर पूछता है। बार-बार prompt आना दोष नहीं है। यह दर्शाता है कि executable की ऐसी निरंतरता नहीं बची जिसे macOS प्रमाणित कर सके।

इन लोकप्रिय विकल्पों का इस्तेमाल न करें:

  • उपयोगकर्ता के home directory के नीचे का path, क्योंकि वही उपयोगकर्ता उसे बदल सकता है।
  • metadata से लिया filename या bundle identifier, क्योंकि unsigned code कोई भी मान बता सकता है।
  • parent process का signature, क्योंकि authority इस्तेमाल करने वाला peer child है।
  • blanket terminal approval, क्योंकि terminals मनमाने प्रोग्राम शुरू करते हैं।
  • permanent identity के रूप में सहेजा hash, क्योंकि हर वैध rebuild में manual migration चाहिए।

Hash किसी अस्थायी exception को सुरक्षित तरीके से सीमित कर सकता है। इसका अर्थ है "इस रन के लिए ये सटीक bytes", न कि "अपडेट के बाद भी यही प्रोग्राम है"। इस अर्थ के अंतर को storage और UI में साफ रखें।

missing Team ID को तुलना bypass करने वाले null की तरह नहीं, वर्गीकृत करने वाली state की तरह लें। Apple signed platform code, independently signed code, ad hoc code और unsigned code सभी एक ही tuple में नहीं आते। तय करें कि आपका product किन categories को स्वीकार करता है, फिर हर category test करें। permissive empty-value branch के साथ if team != expected check ने इतने authorization bugs पैदा किए हैं कि इसके लिए अलग unit test होना चाहिए।

ऐसा identity record रखें जो अपना scope खुद समझाए

एजेंट कॉल को एक गेट से भेजें
`sp mcp` शिम MCP एजेंट की HTTP और SSH कार्रवाइयों को Sallyport के जरिए भेजता है।

टिकाऊ record में machine-evaluable requirement, मानव-पठनीय signature facts, code category और अलग से स्वीकृत location condition सहेजी जानी चाहिए। इसमें grant का scope भी दर्ज होना चाहिए। छह महीने बाद database देखने वाले व्यक्ति को पता चलना चाहिए कि मंजूरी एक run, भविष्य के signed versions या टीम के हर program को मिली थी।

यह उदाहरण placeholder values और base64 के रूप में serialized requirement blob इस्तेमाल करता है। blob Code Signing Services से आना चाहिए, client की दी string compile करके नहीं:

{
  "schema": 1,
  "code_category": "developer_id",
  "team_id": "A1B2C3D4E5",
  "signing_identifier": "dev.example.agent",
  "designated_requirement": "BASE64_PLATFORM_REQUIREMENT",
  "approval_scope": "matching_identity_per_session",
  "location_constraint": null,
  "observed_path": "/Applications/Example.app/Contents/MacOS/Example"
}

Matching algorithm नीरस होना चाहिए। पहले caller को classify करें और उसके live signature को validate करें। signed identity के लिए stored requirement को उस live process पर evaluate करें। लौटे Team ID और signing identifier audit fields से मेल खाते हों, यह पक्का करें। mismatch corrupt state या bug का संकेत है, access बढ़ाने की वजह नहीं। फिर कोई location constraint लागू करें। अंत में grant scope और per-secret approval requirement देखें।

Pseudocode से failure behavior की समीक्षा आसान होती है:

caller = peer_from_kernel(connection)
code = dynamic_code(caller)
result = validate(code)

if result.category not in accepted_categories:
    deny("unsupported code category")

identity = evaluate(stored_requirement, code)
if identity != satisfied:
    deny("process identity changed")

if facts(code) != stored_audit_facts:
    deny("identity record inconsistent")

if location_constraint and not location_allowed(code, location_constraint):
    deny("approved program ran from an unapproved location")

authorize_for(connection_lifetime, requested_secret)

ध्यान दें कि algorithm क्या नहीं करता। वह सिर्फ Team ID स्वीकार नहीं करता, signature जांचने से पहले path compare नहीं करता, अधिक अनुकूल पहचान के लिए parent processes नहीं खोजता और unsigned caller को चुपचाप development grant में नहीं बदलता। हर विफलता का कारण ऐसा होता है जिसे उपयोगकर्ता और auditor समझ सकें।

Identity migration को अपवाद नहीं, operation की तरह plan करें। Team transfer, signing identifier change, distribution channel change या ad hoc से Developer ID signing में बदलाव वैध रूप से requirement बदल सकता है। पुराने और नए facts साथ-साथ दिखाएं, authorized व्यक्ति से transition मंजूर कराएं और audit history में दोनों records रखें। पुराने identity को कभी overwrite न करें और पुरानी calls को नए identity से आई हुई न दिखाएं।

Adversarial fixtures के साथ test करें। एक टीम से दो executables sign करें, identifiers अलग हों तो सिर्फ एक पास होना चाहिए। स्वीकृत identifier से दूसरे team के तहत एक और sign करें, वह fail होना चाहिए। approved executable को नए path पर कॉपी करें, identity pass होनी चाहिए जब तक location condition कुछ और न कहे। launch के बाद file बदलें और पुष्टि करें कि verifier live peer को assess करता है। ad hoc target rebuild करें और पुष्टि करें कि उसकी temporary approval बची नहीं रहती।

पहचान यह नहीं बता सकती कि कार्रवाई की अनुमति है या नहीं

हर कार्रवाई वॉल्ट पर लॉक करें
हार्डवेयर-गेटेड वॉल्ट लॉक रहने पर Sallyport प्रोसेस की पहचान चाहे जो हो, सभी कॉल अस्वीकार करता है।

सही process match केवल अनुरोध के subject की पहचान करता है। वह साबित नहीं करता कि subject हर secret इस्तेमाल कर सकता है, हर host को call कर सकता है या हमेशा के लिए access रख सकता है। process identity, session approval और action approval को अलग फैसले रखें, भले एक interface उन्हें साथ दिखाए।

यह विभाजन एक आम escalation रोकता है। उपयोगकर्ता किसी signed coding agent को एक development token पढ़ने की मंजूरी देता है, सिस्टम उसकी identity सहेजता है और बाद का implementation उस record को हर credential की मंजूरी मानने लगता है। Team ID, signing identifier या DR में मूल resource boundary नहीं होती। पहचान स्थिर रही, पर ऑथराइज़ेशन चुपचाप फैल गया।

Authorization tuple को स्पष्ट रखें: subject, action, resource, conditions और lifetime। secret gateway के लिए यह ऐसा हो सकता है:

subject: requirement R42 satisfied by this live process
action: perform an HTTP request with injected bearer credentials
resource: issue-tracker-development
conditions: vault unlocked and session approved
lifetime: this connection, with per-call approval if the secret requires it

Subject field process identity record को संदर्भित करता है। बाकी fields requested operation और उसके आसपास के controls से आते हैं। यह संरचना HTTP और SSH दोनों इस्तेमाल करने वाले agent को भी संभालती है, बिना यह मानने के कि process recognition अपने आप दोनों channels authorize करती है।

Entitlements किसी specialized policy को जानकारी दे सकते हैं, लेकिन वे कोई मनमाना reputation score नहीं बनने चाहिए। Entitlement signed claim है जिसे macOS खास system facilities के लिए समझता है। उसका होना program को सामान्य रूप से सुरक्षित नहीं बनाता और उसका न होना Team ID तथा identifier match को कमजोर नहीं करता। किसी entitlement को तभी check करें जब आपके authorization design में उसका सटीक अर्थ हो।

Notarization और Gatekeeper भी अलग सवालों के जवाब देते हैं। उनकी स्वीकृति code category validation और distribution trust में योगदान दे सकती है, लेकिन वे developer team के भीतर किसी एक program की पहचान नहीं करते और न आपके secret की पहुंच देते हैं। Diagnosis के दौरान spctl -a -vv -t exec चलाने से समझ आ सकता है कि Gatekeeper file स्वीकार करता है या नहीं। उस verdict को stored requirement check का विकल्प न बनाएं।

Revocation में भी यही सटीकता चाहिए। session revoke करने से मौजूदा connection बंद होनी चाहिए, पहचाने गए program की identity नहीं मिटनी चाहिए। identity revoke करने से matching future processes को फिर मंजूरी लेनी चाहिए। resource grant revoke करने से दूसरे grants जस के तस रहें। यदि trusted नाम का एक boolean तीनों नियंत्रित करता है, तो data model उपयोगकर्ता के वास्तविक निर्णय को व्यक्त नहीं कर सकता।

इन सीमाओं से incident review में अनुमान कम लगाना पड़ता है। Auditor तय कर सकता है कि खास signed program चला, किसी व्यक्ति ने उस run को मंजूरी दी और उस run को निर्धारित operation का अधिकार मिला। इन तीनों records के बिना, एक सटीक DR भी सबसे महत्वपूर्ण सवाल का जवाब नहीं देता: प्रोसेस को पहचानने से क्या अनुमति मिली?

Approval screens को बताना चाहिए कि क्या सिद्ध हुआ

Interruptive approval के दौरान इंसान raw requirement blob की समीक्षा नहीं कर सकता। validated facts से निकला छोटा claim दिखाएं: signer या team, signing identifier, signature category, executable path और मंजूरी process के लिए है या एक call के लिए। सबसे व्यापक तथ्य पहले तभी रखें जब डिज़ाइन जानबूझकर व्यापक authority देता हो।

Friendly app names को primary identity न बनाएं। Display names mutable metadata से आते हैं और अक्सर टकराते हैं। validated signing facts के बाद वे path की तरह उपयोगी labels हैं। Example Agent wants access जैसी मंजूरी यह छिपाती है कि requester released app है, helper है, local rebuild है या unsigned copy।

Sallyport किसी नए agent process की पहली call पर process की code signing authority से शुरू होने वाला approval card दिखाता है, फिर मंजूरी को उसके समाप्त होने तक उस run से बांध देता है। इसका vault gate और per-call approval flag अलग controls रहते हैं, इसलिए process को पहचानना कभी identity को असीमित secret access में नहीं बदलता।

Audit event में verifier ने क्या देखा और कौन-सा rule लगाया, यह सुरक्षित रहना चाहिए। validated category, Team ID, signing identifier, requirement reference, path, process और session identifiers, decision, denial reason और grant scope दर्ज करें। बाद के reviewer को call समझने के लिए पुराने path पर मौजूदा file की जरूरत नहीं होनी चाहिए।

परिणाम को trusted process न कहें। Verifier ने एक सीमित कथन सिद्ध किया है: यह live process किसी खास code requirement को पूरा करता है और उपयोगकर्ता या policy ने उसे निश्चित कार्रवाई की मंजूरी दी। यह भाषा तब authority creep रोकती है जब नए secret types और agent tools आते हैं।

उस कथन में Team ID की जगह है, मगर वह अकेले उसे संभाल नहीं सकता। signer का नाम लेने के लिए Team ID, उसी signer के भीतर program का नाम लेने के लिए signing identifier, वैध releases के बीच पहचान बचाने के लिए designated requirement और प्रमाण को requester से बांधने के लिए live process handle इस्तेमाल करें। इनमें से कोई भाग न हो तो grant को सीमित करें या फिर पूछें। Secret boundary को अनिश्चितता दिखानी चाहिए, उसे स्थायी access में नहीं बदलना चाहिए।

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

क्या दो अलग macOS ऐप का Team ID एक जैसा हो सकता है?

हां। एक ही Apple डेवलपर टीम से साइन किए गए हर ऐप और हेल्पर का Team ID एक जैसा हो सकता है। टीम के भीतर प्रोग्रामों को अलग पहचानने के लिए signing identifier या designated requirement इस्तेमाल करें।

क्या bundle identifier और signing identifier एक ही हैं?

अक्सर हां, लेकिन macOS इसकी बाध्यता नहीं रखता। signer signing identifier चुनता है और कमांड-लाइन टूल के पास ऐप बंडल के बिना भी ऐसा identifier हो सकता है, इसलिए इसे वैध कोड सिग्नेचर से पढ़ें।

क्या मुझे designated requirement सहेजना चाहिए या Team ID और identifier फ़ील्ड?

मशीन से जांचा जा सकने वाला designated requirement सहेजें और Team ID व signing identifier को पढ़े जा सकने वाले ऑडिट तथ्यों के रूप में रखें। उसके प्रिंट किए गए टेक्स्ट को पार्स और तुलना करने के बजाय Code Signing Services से requirement जांचें।

क्या designated requirement साबित करता है कि कोई प्रोसेस सुरक्षित है?

नहीं। यह साबित करता है कि कोड किसी पहचान अभिव्यक्ति को संतुष्ट करता है। फिर भी आपको अलग से तय करना होगा कि वह पहचान किन सीक्रेट और कार्रवाइयों का उपयोग कर सकती है, कितने समय तक और किस मानवीय मंजूरी के साथ।

क्या executable path प्रोसेस ऑथराइज़ेशन का हिस्सा हो सकता है?

सिग्नेचर पहचान सफल होने के बाद इसे अतिरिक्त लोकेशन प्रतिबंध के रूप में इस्तेमाल किया जा सकता है। केवल पथ असुरक्षित है, क्योंकि फाइलें स्थान बदल सकती हैं और हमलावर स्वीकृत, लिखने योग्य स्थान पर फाइल बदल सकते हैं।

IPC कनेक्शन पर सेवा को प्रोसेस की पहचान कैसे करनी चाहिए?

ऑडिट टोकन जैसे कर्नेल द्वारा दिए गए कनेक्शन डेटा से peer पहचानें, फिर उससे जुड़े लाइव कोड ऑब्जेक्ट को जांचें। क्लाइंट के अनुरोध में दिया PID, पथ या identifier कभी भरोसेमंद न मानें।

साइन किया हुआ ऐप अपडेट होने पर ऑथराइज़ेशन का क्या होता है?

ठीक तरह चुना गया designated requirement वैध अपडेट को उसी पहचान से मेल खाने देगा। signer, identifier या वितरण मार्ग उस requirement के दायरे से बाहर बदल जाए तो स्पष्ट identity migration या नई मंजूरी लें।

क्या मैं unsigned development build को स्थायी रूप से अधिकृत कर सकता हूं?

आप कर सकते हैं, मगर पथ आधारित स्थायी अनुदान में कोड की भरोसेमंद निरंतरता नहीं होती। सटीक बिल्ड से जुड़ी, प्रोसेस के जीवनकाल तक सीमित development approval चुनें, उसे nonproduction सीक्रेट तक रखें और हर rebuild के बाद फिर मंजूरी मांगें।

क्या child process को अपने signed parent की पहचान विरासत में मिलनी चाहिए?

अपने आप नहीं। बच्चा प्रोसेस कनेक्ट करता है तो वही सीधा peer है। प्रोसेस ट्री में ऊपर जाना बदले हुए descendants को अधिकार दे सकता है। अगर डिज़ाइन में inheritance हो, तो नियंत्रित चैनल से सीमित capability भेजें।

क्या code hash, Team ID से बेहतर पहचान है?

हैश सटीक कोड बाइट्स पहचानता है, इसलिए अस्थायी unsigned-build अपवाद के लिए अच्छा है। वह वैध अपडेट के बाद नहीं चलता, जबकि Team ID और signing identifier का जोड़ा या designated requirement रिलीज़ के बीच निरंतरता व्यक्त कर सकता है।

Sallyport

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

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