দূরবর্তী হোস্ট করা কোড লঙ্ঘন সঙ্গে ডিল

রিমোটলি হোস্টেড কোড বা আরএইচসি (RHC) হলো এমন যেকোনো কিছু যা এক্সটেনশনের নিজস্ব ফাইল ছাড়া অন্য কোনো জায়গা থেকে লোড হয়ে ব্রাউজার দ্বারা এক্সিকিউট হয়। যেমন জাভাস্ক্রিপ্ট এবং WASM। এর মধ্যে ডেটা বা JSON অথবা CSS-এর মতো বিষয়গুলো অন্তর্ভুক্ত নয়

কেন RHC আর অনুমোদিত নয়?

Manifest V3 অনুযায়ী, এক্সটেনশনগুলোকে এখন তাদের ব্যবহৃত সমস্ত কোড এক্সটেনশনটির ভেতরেই বান্ডল করতে হবে। আগে, ওয়েবের যেকোনো URL থেকে ডাইনামিকভাবে স্ক্রিপ্ট ট্যাগ ইনজেক্ট করা যেত।

আমাকে বলা হয়েছে আমার এক্সটেনশনে RHC আছে। ব্যাপারটা কী?

পর্যালোচনার সময় যদি আপনার এক্সটেনশনটি একটি ব্লু আর্গন ত্রুটির কারণে প্রত্যাখ্যাত হয়, তাহলে আমাদের পর্যালোচকরা মনে করেন যে আপনার এক্সটেনশনটি দূরবর্তীভাবে হোস্ট করা কোড ব্যবহার করছে। সাধারণত, কোনো এক্সটেনশন যখন দূরবর্তী কোনো রিসোর্স (অর্থাৎ, এক্সটেনশনের অন্তর্ভুক্ত ফাইলগুলোর পরিবর্তে উন্মুক্ত ওয়েব থেকে) সহ একটি স্ক্রিপ্ট ট্যাগ যোগ করার চেষ্টা করে, অথবা সরাসরি কার্যকর করার জন্য কোনো রিসোর্স ফেচ করে , তখন এমনটা ঘটে।

RHC কীভাবে শনাক্ত করবেন

একবার কী খুঁজতে হবে তা জেনে গেলে RHC শনাক্ত করা তেমন কঠিন কিছু নয়। প্রথমে, আপনার প্রোজেক্টে "http://" বা "https://" স্ট্রিংগুলো আছে কিনা তা পরীক্ষা করুন। যদি আপনার কোনো RHC ভায়োলেশন থাকে, তবে সেটি খুঁজে বের করার মাধ্যমে আপনি সম্ভবত সমস্যাটি চিহ্নিত করতে পারবেন। যদি আপনার একটি সম্পূর্ণ বিল্ড সিস্টেম থাকে, অথবা আপনি npm বা অন্য কোনো থার্ড-পার্টি সোর্স থেকে ডিপেন্ডেন্সি ব্যবহার করেন, তবে নিশ্চিত করুন যে আপনি কোডের কম্পাইল করা সংস্করণটিই খুঁজছেন, কারণ স্টোরটি সেটিই মূল্যায়ন করে থাকে। এরপরও যদি আপনি সমস্যাটি খুঁজে না পান, তাহলে পরবর্তী পদক্ষেপ হলো ওয়ান স্টপ সাপোর্টের সাথে যোগাযোগ করা। তারা আপনাকে নির্দিষ্ট ভায়োলেশনগুলো সম্পর্কে বিস্তারিত জানাতে পারবে এবং যত দ্রুত সম্ভব এক্সটেনশনটি প্রকাশ করার জন্য কী প্রয়োজন তাও বলে দেবে।

কোনো লাইব্রেরি কোড অনুরোধ করলে কী করতে হবে

কোডটি কোথা থেকে এসেছে তা নির্বিশেষে, এতে RHC থাকা অনুমোদিত নয়। এর মধ্যে সেই কোডও অন্তর্ভুক্ত যা আপনি নিজে তৈরি করেননি, কিন্তু আপনার প্রোজেক্টে একটি ডিপেন্ডেন্সি হিসেবে ব্যবহার করছেন। Firebase ব্যবহারকারী কিছু ডেভেলপার এই সমস্যার সম্মুখীন হয়েছিলেন যখন Firebase Auth- এ ব্যবহারের জন্য রিমোট কোড অন্তর্ভুক্ত করা হচ্ছিল। যদিও এটি একটি ফার্স্ট পার্টি (অর্থাৎ গুগলের মালিকানাধীন) লাইব্রেরি ছিল, RHC-এর জন্য কোনো ছাড় দেওয়া হয়নি। আপনাকে হয় RHC সরিয়ে ফেলার জন্য কোডটি কনফিগার করতে হবে, অথবা শুরু থেকেই কোডটি অন্তর্ভুক্ত না করার জন্য আপনার প্রোজেক্ট আপডেট করতে হবে। যদি আপনি এমন কোনো সমস্যার সম্মুখীন হন যেখানে আপনার কোড নয়, বরং আপনার ব্যবহৃত কোনো লাইব্রেরি RHC লোড করছে, তাহলে সবচেয়ে ভালো উপায় হলো লাইব্রেরিটির লেখকের সাথে যোগাযোগ করা। তাদের জানান যে এমনটা ঘটছে, এবং এটি সরানোর জন্য হয় কোনো বিকল্প সমাধান অথবা কোড আপডেটের জন্য অনুরোধ করুন।

যদি আপনি লাইব্রেরি আপডেটের জন্য অপেক্ষা করতে না পারেন তাহলে কী হবে?

কিছু লাইব্রেরি অবহিত হওয়ার প্রায় সাথে সাথেই একটি আপডেট প্রকাশ করে, কিন্তু অন্যগুলো পরিত্যক্ত হতে পারে বা সমস্যাটি সমাধান করতে সময় নিতে পারে। নির্দিষ্ট লঙ্ঘনটিতে কী ঘটছে তার উপর নির্ভর করে, আনব্লক হওয়া এবং একটি সফল পর্যালোচনা সম্পন্ন করার জন্য আপনাকে তাদের পদক্ষেপ নেওয়া পর্যন্ত অপেক্ষা করতে হবে না। দ্রুত আবার কাজ শুরু করার জন্য বেশ কিছু বিকল্প রয়েছে।

কোডটি নিরীক্ষা করুন

আপনি কি নিশ্চিত যে যে কোডটি অনুরোধটি তৈরি করছে সেটি প্রয়োজনীয়? যদি এটিকে শুধু মুছে ফেলা যায়, অথবা যে লাইব্রেরিটি এর কারণ হচ্ছে সেটি সরিয়ে ফেলা যায়, তাহলে সেই কোডটি মুছে ফেলুন, এবং কাজটি হয়ে যাবে।

বিকল্পভাবে, এমন কোনো লাইব্রেরি আছে কি যা একই বৈশিষ্ট্যগুলো প্রদান করে? একই ধরনের কাজের জন্য npmjs.com , GitHub বা অন্যান্য সাইটগুলো দেখে নিতে পারেন।

গাছ কাঁপছে

যদি RHC ভায়োলেশন সৃষ্টিকারী কোডটি আসলে ব্যবহৃত না হয়, তবে টুলিংয়ের মাধ্যমে এটি স্বয়ংক্রিয়ভাবে মুছে ফেলা যেতে পারে। webpack , Rollup , এবং Vite-এর মতো আধুনিক বিল্ড টুলগুলিতে (কয়েকটির নাম উল্লেখ করা হলো) ট্রি-শেকিং (tree-shaking) নামে একটি ফিচার রয়েছে। আপনার বিল্ড সিস্টেমে এটি চালু করা হলে, ট্রি-শেকিং যেকোনো অব্যবহৃত কোড পাথ মুছে ফেলবে। এর ফলে আপনি শুধু আপনার কোডের একটি অধিক কমপ্লায়েন্ট সংস্করণই পাবেন না, বরং এটি আরও হালকা এবং দ্রুততরও হবে! এটি মনে রাখা গুরুত্বপূর্ণ যে, সব লাইব্রেরি ট্রি-শেক করা যায় না, তবে অনেকগুলোই করা যায়। Rollup এবং Vite-এর মতো কিছু টুলে ডিফল্টভাবেই ট্রি-শেকিং চালু থাকে। এটি চালু করার জন্য webpack-কে কনফিগার করতে হবে । আপনি যদি আপনার এক্সটেনশনের অংশ হিসেবে কোনো বিল্ড সিস্টেম ব্যবহার না করে কোড লাইব্রেরি ব্যবহার করেন , তবে আপনার ওয়ার্কফ্লোতে একটি বিল্ড টুল যুক্ত করার বিষয়টি খতিয়ে দেখার জন্য আপনাকে বিশেষভাবে উৎসাহিত করা হচ্ছে। বিল্ড টুল আপনাকে আরও নিরাপদ, নির্ভরযোগ্য এবং সহজে রক্ষণাবেক্ষণযোগ্য প্রজেক্ট তৈরি করতে সাহায্য করে।

কীভাবে ট্রি-শেকিং প্রয়োগ করতে হবে তার বিস্তারিত বিবরণ আপনার নির্দিষ্ট প্রজেক্টের উপর নির্ভর করে। কিন্তু রোলআপের একটি সহজ উদাহরণ দিতে গেলে, আপনি শুধু আপনার প্রজেক্ট কোড কম্পাইল করেই ট্রি-শেকিং যোগ করতে পারেন। উদাহরণস্বরূপ, যদি আপনার main.js নামে একটি ফাইল থাকে যা শুধুমাত্র ফায়ারবেস অথ-এ লগইন করে:

import { GoogleAuthProvider, initializeAuth } from "firebase/auth";

chrome.identity.getAuthToken({ 'interactive': true }, async (token) => {
  const credential = GoogleAuthProvider.credential(null, token);
  try {
    const app = initializeApp({ ... });
    const auth = initializeAuth(app, { popupRedirectResolver: undefined, persistence: indexDBLocalPersistence });
    const { user } = await auth.signInWithCredential(credential)
    console.log(user)
  } catch (e) {
    console.error(error);
  }
});

তাহলে আপনাকে শুধু রোলআপকে ইনপুট ফাইল, নোড ফাইল লোড করার জন্য প্রয়োজনীয় প্লাগইন @rollup/plugin-node-resolve , এবং এটি যে আউটপুট ফাইলটি তৈরি করছে তার নাম জানিয়ে দিতে হবে।

npx rollup --input main.js --plugin '@rollup/plugin-node-resolve' --file compiled.js

টার্মিনাল উইন্ডোতে ওই কমান্ডটি চালালে, আপনি আমাদের main.js ফাইলের একটি জেনারেটেড ভার্সন পাবেন, যা সম্পূর্ণভাবে কম্পাইল হয়ে compiled.js নামের একটিমাত্র ফাইলে পরিণত হয়েছে।

রোলআপ সহজ হতে পারে, কিন্তু এটি খুব কনফিগারযোগ্যও বটে। আপনি এতে সব ধরনের জটিল লজিক এবং কনফিগারেশন যোগ করতে পারেন, শুধু তাদের ডকুমেন্টেশনটি দেখুন। এই ধরনের বিল্ড টুলিং যোগ করলে কোড আরও ছোট ও কার্যকর হবে এবং এক্ষেত্রে, এটি আমাদের রিমোট হোস্টেড কোডের সমস্যাটি সমাধান করে।

স্বয়ংক্রিয়ভাবে ফাইল সম্পাদনা করা

দূরবর্তীভাবে হোস্ট করা কোড আপনার কোডবেসে প্রবেশ করার একটি ক্রমবর্ধমান সাধারণ উপায় হলো, আপনার অন্তর্ভুক্ত করা কোনো লাইব্রেরির সাবডিপেন্ডেন্সি হিসেবে আসা। যদি লাইব্রেরি X একটি CDN থেকে লাইব্রেরি Y import করতে চায়, তাহলে এটিকে স্থানীয় উৎস থেকে লোড করার জন্য আপনাকে এটি আপডেট করতে হবে। আধুনিক বিল্ড সিস্টেমের সাহায্যে, আপনি সহজেই একটি রিমোট রেফারেন্স বের করে আনার জন্য প্লাগইন তৈরি করতে পারেন এবং এটিকে সরাসরি আপনার কোডে ইনলাইন করতে পারেন।

তার মানে হল, প্রদত্ত কোডটি দেখতে এইরকম:

import moment from "https://unpkg.com/moment@2.29.4/moment.js"
console.log(moment())

আপনি একটি ছোট রোলআপ প্লাগইন তৈরি করতে পারেন।

import { existsSync } from 'fs';
import fetch from 'node-fetch';

export default {
  plugins: [{
    load: async function transform(id, options, outputOptions) {
      // this code runs over all of out javascript, so we check every import
      // to see if it resolves as a local file, if that fails, we grab it from
      // the network using fetch, and return the contents of that file directly inline
      if (!existsSync(id)) {
        const response = await fetch(id);
        const code = await response.text();

        return code
      }
      return null
    }
  }]
};

নতুন প্লাগইনটি দিয়ে বিল্ডটি রান করার পর, প্রতিটি রিমোট import URL খুঁজে পাওয়া যায়, সেটি আমাদের কোড, কোনো সাবডিপেন্ডেন্সি, সাবসাবডিপেন্ডেন্সি বা অন্য কোথাও থেকে নেওয়া হয়েছে কি না, তা নির্বিশেষে।

npx rollup --input main.js --config ./rollup.config.mjs --file compiled.js

ম্যানুয়ালি ফাইল সম্পাদনা করা

সবচেয়ে সহজ উপায় হলো RHC (রাইট-হাইপারটেনশন) এর কারণ যে কোডটি, সেটি মুছে ফেলা। আপনার পছন্দের টেক্সট এডিটরে ফাইলটি খুলুন এবং সমস্যা সৃষ্টিকারী লাইনগুলো মুছে দিন। সাধারণত এটি খুব একটা পরামর্শযোগ্য নয় , কারণ এটি ভঙ্গুর এবং ভুলে যাওয়ার সম্ভাবনা থাকে। যখন "library.min.js" নামের একটি ফাইল আসলে library.min.js হয় না, তখন এটি আপনার প্রোজেক্ট রক্ষণাবেক্ষণ করা কঠিন করে তোলে। সরাসরি ফাইলগুলো সম্পাদনা করার পরিবর্তে, patch-package-এর মতো একটি টুল ব্যবহার করা কিছুটা বেশি রক্ষণাবেক্ষণযোগ্য একটি উপায়। এটি একটি অত্যন্ত শক্তিশালী বিকল্প যা আপনাকে ফাইলটির পরিবর্তে, ফাইলটিতে করা পরিবর্তনগুলো সংরক্ষণ করতে দেয়। এটি প্যাচ ফাইলের উপর ভিত্তি করে তৈরি, যা Git বা Subversion-এর মতো ভার্সন কন্ট্রোল সিস্টেমগুলোকে শক্তি জোগায়। আপনাকে শুধু ম্যানুয়ালি সমস্যা সৃষ্টিকারী কোডটি পরিবর্তন করতে হবে, diff ফাইলটি সংরক্ষণ করতে হবে এবং আপনি যে পরিবর্তনগুলো প্রয়োগ করতে চান তা দিয়ে patch-package কনফিগার করতে হবে। আপনি প্রোজেক্টের readme- তে একটি সম্পূর্ণ টিউটোরিয়াল পড়তে পারেন। আপনি যদি কোনো প্রোজেক্ট প্যাচ করেন, তবে আমরা আপনাকে প্রোজেক্ট কর্তৃপক্ষের সাথে যোগাযোগ করে আপস্ট্রিমে পরিবর্তনগুলো প্রয়োগ করার জন্য অনুরোধ করতে উৎসাহিত করি। যদিও patch-package প্যাচ পরিচালনাকে অনেক সহজ করে তোলে, তবে প্যাচ করার মতো কিছুই না থাকা আরও ভালো।

কোডটি ব্যবহার না হলে কী করতে হবে

কোডবেস বড় হওয়ার সাথে সাথে, ডিপেন্ডেন্সি (বা ডিপেন্ডেন্সির ডিপেন্ডেন্সি, বা তারও ডিপেন্ডেন্সি...) এমন কোড পাথ ধরে রাখতে পারে যা আর ব্যবহৃত হচ্ছে না। যদি সেই সেকশনগুলোর কোনোটিতে RHC লোড বা এক্সিকিউট করার কোড থাকে, তাহলে সেটি সরিয়ে ফেলতে হবে । এটি ডেড বা অব্যবহৃত কিনা তা বিবেচ্য নয়। যদি এটি ব্যবহৃত না হয়, তবে ট্রি-শেকিং (treeshaking) করে অথবা লাইব্রেরিটি প্যাচ (patch) করে এটিকে সরিয়ে ফেলা উচিত।

এর কি কোনো বিকল্প উপায় আছে?

সাধারণভাবে বলতে গেলে, না। আরএইচসি (RHC) অনুমোদিত নয়। তবে, এমন কিছু ক্ষেত্র রয়েছে যেখানে এটি অনুমোদিত হয় । এই ক্ষেত্রগুলো প্রায় সবসময়ই এমন হয়, যেখানে অন্য কোনো বিকল্প থাকা অসম্ভব।

ব্যবহারকারী স্ক্রিপ্ট এপিআই

ইউজার স্ক্রিপ্ট হলো ছোট ছোট কোড স্নিপেট যা সাধারণত ব্যবহারকারী সরবরাহ করে থাকেন এবং এটি TamperMonkeyViolentmonkey-এর মতো ইউজার স্ক্রিপ্ট ম্যানেজারদের জন্য তৈরি। এই ম্যানেজারদের পক্ষে ব্যবহারকারীদের লেখা কোড বান্ডল করা সম্ভব নয়, তাই ইউজার স্ক্রিপ্ট এপিআই ব্যবহারকারীর সরবরাহ করা কোড এক্সিকিউট করার একটি উপায় প্রদান করে। এটি chrome.scripting.executeScript বা অন্যান্য কোড এক্সিকিউশন এনভায়রনমেন্টের বিকল্প নয় । যেকোনো কিছু এক্সিকিউট করার জন্য ব্যবহারকারীদের অবশ্যই ডেভেলপার মোড চালু করতে হবে। যদি ক্রোম ওয়েব স্টোর রিভিউ টিমের মনে হয় যে এটি এর উদ্দিষ্ট উদ্দেশ্য ছাড়া অন্য কোনোভাবে (অর্থাৎ ব্যবহারকারীর সরবরাহ করা কোড) ব্যবহার করা হচ্ছে, তবে এটি বাতিল করা হতে পারে অথবা স্টোর থেকে এর তালিকা সরিয়ে ফেলা হতে পারে।

ক্রোম.ডিবাগার

chrome.debugger API এক্সটেনশনগুলোকে Chrome Devtools Protocol-এর সাথে ইন্টারঅ্যাক্ট করার ক্ষমতা দেয়। এটি সেই একই প্রোটোকল যা Chrome-এর Devtools এবং আরও অসংখ্য টুলের জন্য ব্যবহৃত হয়। এর মাধ্যমে, একটি এক্সটেনশন রিমোট কোডের জন্য অনুরোধ করতে এবং তা এক্সিকিউট করতে পারে। ইউজার স্ক্রিপ্টের মতোই, এটি chrome.scripting-এর বিকল্প নয় এবং এর ইউজার এক্সপেরিয়েন্স অনেক বেশি উল্লেখযোগ্য। এটি ব্যবহার করার সময়, ব্যবহারকারী উইন্ডোর উপরে একটি সতর্কীকরণ বার দেখতে পাবেন। ব্যানারটি বন্ধ বা ডিসমিস করা হলে, ডিবাগিং সেশনটি টার্মিনেট হয়ে যাবে।

ক্রোমের অ্যাড্রেস বারের স্ক্রিনশট, যেখানে 'ডিবাগার এক্সটেনশন এই ব্রাউজারটি ডিবাগ করা শুরু করেছে' বার্তাটি রয়েছে।
ক্রোমের অ্যাড্রেস বারের স্ক্রিনশট, যেখানে 'ডিবাগার এক্সটেনশন এই ব্রাউজারটি ডিবাগ করা শুরু করেছে' বার্তাটি রয়েছে।

স্যান্ডবক্সড আইফ্রেম

যদি আপনাকে কোড হিসেবে কোনো স্ট্রিং মূল্যায়ন করার প্রয়োজন হয় এবং আপনি একটি DOM পরিবেশে (যেমন একটি কন্টেন্ট স্ক্রিপ্ট, কোনো এক্সটেনশন সার্ভিস ওয়ার্কারের পরিবর্তে) থাকেন, তাহলে আরেকটি বিকল্প হলো একটি স্যান্ডবক্সড আইফ্রেম ব্যবহার করা। নিরাপত্তা সতর্কতা হিসেবে এক্সটেনশনগুলো ডিফল্টভাবে eval() এর মতো বিষয়গুলো সমর্থন করে না। ক্ষতিকর কোড ব্যবহারকারীর সুরক্ষা ও নিরাপত্তাকে ঝুঁকির মধ্যে ফেলতে পারে। কিন্তু যখন কোডটি শুধুমাত্র একটি পরিচিত নিরাপদ পরিবেশে, যেমন ওয়েবের বাকি অংশ থেকে স্যান্ডবক্স করা একটি আইফ্রেমে, এক্সিকিউট করা হয়, তখন সেই ঝুঁকিগুলো অনেকাংশে কমে যায়। এই প্রেক্ষাপটে, কন্টেন্ট সিকিউরিটি পলিসি যা eval-এর ব্যবহার ব্লক করে, তা তুলে নেওয়া যেতে পারে, যার ফলে আপনি যেকোনো বৈধ জাভাস্ক্রিপ্ট কোড চালাতে পারবেন।

আপনার যদি এমন কোনো ব্যবহারের ক্ষেত্র (use case) থাকে যা এখানে অন্তর্ভুক্ত নয়, তাহলে মতামত (feedback) পেতে chromium-extensions মেইলিং লিস্ট ব্যবহার করে টিমের সাথে নির্দ্বিধায় যোগাযোগ করুন, অথবা ওয়ান স্টপ সাপোর্ট (One Stop Support) থেকে নির্দেশনা চেয়ে একটি নতুন টিকেট খুলুন।

কোনো রায়ের সঙ্গে দ্বিমত পোষণ করলে কী করবেন

নীতিমালা প্রয়োগ করা বেশ সূক্ষ্ম একটি বিষয় হতে পারে এবং পর্যালোচনার জন্য হাতে-কলমে তথ্য দেওয়ার প্রয়োজন হয়, যার ফলে ক্রোম ওয়েব স্টোর টিম কখনও কখনও পর্যালোচনার সিদ্ধান্ত পরিবর্তন করতে রাজি হতে পারে। যদি আপনার মনে হয় যে পর্যালোচনায় কোনো ভুল হয়েছে, তাহলে আপনি ওয়ান স্টপ সাপোর্টের মাধ্যমে এই প্রত্যাখ্যানের বিরুদ্ধে আপিল করতে পারেন।