एक API key जिसे आपको browser में ship करना ही पड़ता है

उसे restrict करें, proxy करें, rotate करें, फिर जो बचे उसे obfuscate करें। आपके bundle में एक credential को encode करने से असल में क्या मिलता है, और यह कहाँ रुक जाता है।

कभी-कभी किसी key या token को client bundle में होना ही पड़ता है, क्योंकि call सीधे browser करता है। Obfuscation इस समस्या का एक हिस्सा बदलता है, बाकी नहीं।

पढ़ने योग्य key को लोग नहीं, bots ढूँढते हैं

Ship हुए JavaScript में पढ़ने योग्य text के रूप में पड़ी key, देखने वाले किसी के लिए भी बस एक grep की दूरी पर है। Crawl करने वाले secret scanners इसे तब भी ढूँढ लेते हैं जब कोई इंसान आपकी site खोलता तक नहीं, और यह automated खोज ship हुई key से उसके दुरुपयोग तक पहुँचने का एक आम रास्ता है।

ऐसा होने के लिए किसी को आपके product में दिलचस्पी होना ज़रूरी नहीं। एक bot हर उस public bundle में, जिस तक वह पहुँच सकता है, credential जैसी दिखने वाली string खोजता है, और आपका bundle बाकियों के साथ उसी कतार में है।

Key को encode करने से क्या मिलता है, और यह कहाँ रुक जाता है

किसी भी positive complexity target पर strings.encode चालू रहता है, इसलिए आपके source के string literals output में text के रूप में ship होने के बजाय encode होकर जाते हैं। जो scanner bundle में credential जैसी strings के लिए grep करता है, उसे इस तरह key नहीं मिलती।

यह रखने लायक है, और बस इतना ही है। Obfuscation छिपाता है कि किसी value का उपयोग कैसे होता है। वह value को नहीं छिपाता: आपके code को चलाने के लिए browser को जो कुछ भी चाहिए, वह उस code को चलाकर हासिल किया जा सकता है। Sealed key सुरक्षित key नहीं है।

Restrict, proxy, rotate, फिर obfuscate

ये चार काम इसी क्रम में करें, और obfuscation को आख़िरी मानें:

  1. Provider पर key को सबसे सीमित scope, origins और quota तक restrict करें जो वह देता है।
  2. Authority को अपने endpoint के पीछे ले जाएँ, ताकि असली credential कभी browser के पास न हो।
  3. जो key पहले ही ship हो चुकी है, उसे rotate करें। मानकर चलें कि जिस पल वह बाहर गई, उसी पल से वह compromised है।
  4. जो सचमुच server-side नहीं जा सकता, उसे obfuscate करें।

इस आख़िरी कदम के लिए डिफ़ॉल्ट build उसे पहले से encode करती है। CI के लिए build gate सेट करने के लिए:

{
  "strings": {
    "leaks": {
      "max": 0
    }
  }
}

Pro builds पर एक directive किसी एक value को program के बाकी हिस्से से ऊपर उठाता है।

const apiKey = /* @afterpack preset=extreme */ "YOUR_SECRET";

बचे हुए literal पर build को विफल करें

--strings.leaks.max=0 जैसे ही कोई पढ़ने योग्य literal बच जाता है, build को विफल कर देता है और DIAG_SURVIVING_READABLE_LITERAL का नाम बताता है। इसे CI में wire करें ताकि यह आँख से की जाने वाली जाँच न रहे। कोई deployed site अभी क्या expose कर रही है, यह देखने के लिए उस पर npx afterpack@latest audit चलाएँ।

Ship हुई key फिर भी ship हुई key है

Encoding ship हुई फ़ाइल पढ़कर key ढूँढने की लागत बढ़ाती है, और leak gate पार करने वाली build एक वास्तविक नतीजा है। यह इस बात का सबूत नहीं है कि key पहुँच से बाहर है: value अब भी output में है, encoded, और जिस पल आपका code उसका उपयोग करता है उसी पल reconstruct होती है, इसलिए अपने नियंत्रण वाले browser में page चलाने वाला कोई भी उसे वापस पढ़ सकता है। Key को rotate करना और authority को अपने server पर ले जाना ही वे कदम हैं जो इस exposure को बंद करते हैं।

आगे

  • FAQ: ठीक इसी सवाल का छोटा जवाब।
  • Threat model: static reader और आपका code चलाने वाले व्यक्ति के बीच की सीमा।
  • Best practices: अगर कोई key पहले ही बाहर जा चुकी है तो rotation के कदम।