সহজ অনুমোদিত তালিকার জন্য একটি নির্দিষ্ট, পোর্ট-নরমালাইজড স্ট্রিং লিটারালের (যেমন event.origin === 'https://app.example.com') সাথে event.origin তুলনা করা কাজ করলেও, ইচ্ছামতো URL, DOM লিঙ্ক এলিমেন্ট, ক্রস-সাবডোমেন রিডাইরেক্ট বা স্যান্ডবক্স করা মেসেজ যাচাই করার সময় ম্যানুয়াল স্ট্রিং তুলনা এবং রেগুলার এক্সপ্রেশন কাজ করে না:
- প্রিফিক্স ও সাবস্ট্রিং স্পুফিং:
url.startsWith('https://app.example.com')চেক করা'https://app.example.com.attacker.example'-এর মাধ্যমে বাইপাস করা হয়। - আননরমালাইজড URL: পাথ, কোয়েরি স্ট্রিং বা এক্সপ্লিসিট ডিফল্ট পোর্ট (
'https://app.example.com:443/path') সহ সম্পূর্ণ URL প্রথমে পার্স ও নরমালাইজ না করে স্ট্রিং ইকুয়ালিটির অধীনে'https://app.example.com'-এর সাথে মেলে না। - পাবলিক সাফিক্স তালিকার ভুল: একই সাইটের সম্পর্ক চেক করার জন্য
.-এ হোস্টনেম স্প্লিট করা মাল্টি-লেবেল পাবলিক সাফিক্সে (যেমন.co.ukবা.github.io-এর মতো শেয়ার করা হোস্টিং ডোমেন) কাজ করে না এবং স্কিম অমিল (http:বনামhttps:) উপেক্ষা করে। - অস্বচ্ছ
"null"অরিজিন কলিশন: স্যান্ডবক্স করা iframe (<iframe sandbox="allow-scripts">) এবংdata:URL,event.origin-কে আক্ষরিক স্ট্রিং"null"-এ সিরিয়ালাইজ করে।originA === originB-এর সাথে দুটি সিরিয়ালাইজড রানটাইম অরিজিন তুলনা করলে, দুটি সম্পর্কহীন অস্বচ্ছ প্রসঙ্গ ("null" === "null") ভুলভাবে সমান হয়ে যায়।
Origin API (Origin.from(), isSameOrigin(), isSameSite() এবং opaque) ব্রাউজারের URL পার্সার এবং পাবলিক সাফিক্স তালিকার মাধ্যমে স্ট্রাকচার্ড, স্পেক-কমপ্লায়েন্ট অরিজিন এবং স্কিমফুল একই-সাইটের তুলনা প্রদান করে।
আপনার পরিস্থিতির জন্য সঠিক তুলনা বেছে নেওয়া
- কঠোরভাবে প্রিভিলেজ বাউন্ডারি প্রয়োগ করতে
isSameOrigin()ব্যবহার করুন: ক্রস-উইন্ডোpostMessageকমান্ড (যেমন, এম্বেড করা চেকআউট বা প্রমাণীকরণ পপ-আপ) ম্যানেজ করার সময় বা ক্রেডেনশিয়াল অ্যাটাচ করা হবে কিনা তা নির্ধারণ করার সময়(scheme, host, port)-এর সাথে সম্পূর্ণ মিল থাকা প্রয়োজন। এমনকি, আলাদা সাবডোমেনও (https://blog.example.comবনামhttps://app.example.com) আলাদা উৎস হিসেবে বিবেচিত হয় এবং তা অবশ্যই বাতিল করতে হবে যাতে একটি সাবডোমেনের দুর্বলতা অন্যটিকে নিয়ন্ত্রণ করতে না পারে। - ক্রস-সাবডোমেন নেভিগেশন ও লিঙ্ক ক্লাসিফিকেশনের জন্য
isSameSite()ব্যবহার করুন: লগ-ইন করার পরে রিডাইরেক্ট URL (?returnTo=https://billing.example.co.uk/orders) যাচাই করার সময় অথবা ইন্টার্নাল বনাম এক্সটার্নাল হিসেবে লিঙ্ক ক্লাসিফাই করার সময় একই স্কিম ও রেজিস্টার করা যায় এমন ডোমেন শেয়ার করে এমন যেকোনও সাবডোমেন বা পোর্টকে অনুমতি দিন।isSameSite(),http:স্কিম ডাউনগ্রেড এবং শেয়ার করা পাবলিক সাফিক্সে (.co.uk,.github.io) সিবলিং টেন্যান্ট, দুটিই বাতিল করে দেয়। - অস্বচ্ছ বা স্যান্ডবক্স করা প্রসঙ্গের জন্য
origin.opaqueএবংOrigin.from(event)ব্যবহার করুন: রিডাইরেক্টের (origin.opaque === true) জন্যdata:URL বাতিল করুন অথবা নির্দিষ্ট<iframe sandbox="allow-scripts">উইজেটের সাথে যোগাযোগ করার সময়Origin.from(event)-এর মাধ্যমে এক্সট্র্যাক্ট করা অস্বচ্ছOriginপিন করুন, যার সিরিয়ালাইজ করাevent.originহল"null"।
১. প্রিভিলেজড অ্যাকশনের জন্য সঠিক অরিজিন যাচাই করুন (Origin.from() এবং isSameOrigin())
Origin অবজেক্ট এক্সট্র্যাক্ট করতে Origin.from() ব্যবহার করুন এবং isSameOrigin() ব্যবহার করে বিশ্বস্ত Origin-এর সাথে তুলনা করুন:
- উভয় পক্ষকে অবশ্যই
Originইনস্ট্যান্স হতে হবে:isSameOrigin(other)এবংisSameSite(other)শুধুমাত্র একটিOriginঅবজেক্ট গ্রহণ করে—একটি র স্ট্রিং পাস করলে একটিTypeErrorথ্রো করে। - কাজ করে এমন
Origin.from()ইনপুট:- সিরিয়ালাইজ করা URL স্ট্রিং (যেমন,
'https://app.example.com:443/path')। মনে রাখবেন যে, যেকোনও ভুল URL স্ট্রিং—যেমন'example', অথবাevent.origin-এর মাধ্যমে সিরিয়ালাইজ করা'null'স্ট্রিং, যা অস্বচ্ছ অরিজিনের জন্য ব্যবহার করা হয়—এর ফলেOrigin.from()-এTypeErrorদেখা যায়। - প্ল্যাটফর্ম অবজেক্ট যা HTML স্পেসিফিকেশনে অরিজিন-এক্সট্র্যাকশন ধাপগুলি সংজ্ঞায়িত করে:
Origin,URL,HTMLAnchorElement(<a>),HTMLAreaElement(<area>), একই-অরিজিনWindowবাWorkerGlobalScope(Origin.from(self)), এবং ব্রাউজার-ডিসপ্যাচ করাMessageEventইনস্ট্যান্স (Origin.from(event))। Location,WorkerLocation,Document,RequestএবংResponse-এর মতো অবজেক্ট অরিজিন-এক্সট্র্যাকশন ধাপকে সংজ্ঞায়িত করে না এবং সরাসরিOrigin.from()-এ পাস করা হলেTypeErrorথ্রো করে—পরিবর্তেself(বর্তমান প্রসঙ্গের জন্য) অথবাrequest.url/response.urlপাস করুন।
- সিরিয়ালাইজ করা URL স্ট্রিং (যেমন,
- ব্রাউজার-ডিসপ্যাচ করা এবং সিন্থেটিক
MessageEventইনস্ট্যান্স, দুটিই ম্যানেজ করুন: আসল ব্রাউজারpostMessageইভেন্টেOrigin.from(event)-এর মাধ্যমে এক্সট্র্যাক্ট করা ইন্টার্নাল অরিজিন থাকে, যেখানে ইউনিট টেস্টে তৈরি করা সিন্থেটিকnew MessageEvent('message', { origin })ইভেন্ট শুধুমাত্রevent.originস্ট্রিং পপুলেট করে এবংOrigin.from(event)-এ থ্রো করে।try...catch-এর মধ্যেOrigin.from(event.origin)-এ ফিরে যাওয়া, ভুল বা"null"স্ট্রিং বাতিল করার সময় দুটিই পরিষ্কারভাবে ম্যানেজ করে।
// Replace with your application's trusted origin(s)
const TRUSTED_ORIGIN = Origin.from('https://app.example.com');
function extractOrigin(candidate) {
try {
return Origin.from(candidate);
} catch (err) {
// Synthetic new MessageEvent('message', { origin }) objects in tests lack an
// internal browser origin; fall back to parsing candidate.origin if it is a URL.
if (typeof MessageEvent !== 'undefined' && candidate instanceof MessageEvent) {
return Origin.from(candidate.origin);
}
throw err;
}
}
export function isTrustedSameOrigin(candidate) {
try {
return extractOrigin(candidate).isSameOrigin(TRUSTED_ORIGIN);
} catch {
// Rejects invalid URLs, "null" strings, or unsupported objects
return false;
}
}
window.addEventListener('message', (event) => {
if (!isTrustedSameOrigin(event)) return;
// Safe to process privileged commands from the verified origin
});
২. ক্রস-সাবডোমেন রিডাইরেক্ট ও লিঙ্ক যাচাই করুন (isSameSite())
রিডাইরেক্ট টার্গেট (যেমন ?returnTo= প্যারামিটার) বা একই রেজিস্টার করা যায় এমন ডোমেনের সাবডোমেন জুড়ে ইন্টার্নাল লিঙ্ক (যেমন, https://app.example.co.uk এবং https://billing.example.co.uk:8443) যাচাই করার সময় isSameSite() ব্যবহার করুন:
isSameSite()স্কিমফুল সেম-সাইট তুলনা করে:https://sub.example.comএবংhttp://sub.example.comসেম-সাইট নয় কারণ তাদের স্কিম আলাদা।isSameSite()ব্রাউজারের বিল্ট-ইন সর্বজনীন সাফিক্স তালিকা ব্যবহার করে, তাই শেয়ার করা সর্বজনীন সাফিক্সে (যেমনhttps://tenant-a.github.ioএবংhttps://tenant-b.github.ioঅথবাhttps://a.co.ukএবংhttps://b.co.uk) আলাদা আলাদা টেন্যান্টfalseহিসেবে মূল্যায়ন করে।
// Replace with your application's primary origin
const APP_ORIGIN = Origin.from('https://app.example.co.uk');
export function isAllowedSameSiteUrl(candidateUrlOrElement) {
try {
return extractOrigin(candidateUrlOrElement).isSameSite(APP_ORIGIN);
} catch {
return false;
}
}
// true: same scheme (https) and same registrable domain (example.co.uk)
isAllowedSameSiteUrl('https://billing.example.co.uk:8443/checkout');
// false: scheme downgrade (http vs. https) is rejected by schemeful same-site
isAllowedSameSiteUrl('http://billing.example.co.uk/checkout');
৩. অস্বচ্ছ উৎস (origin.opaque এবং Origin.from(event)) আলাদা করা এবং পিন করা
স্যান্ডবক্স করা iframe (<iframe sandbox="allow-scripts">), data: URL এবং new Origin() অস্বচ্ছ উৎস (origin.opaque === true) তৈরি করে। তাদের স্ট্রিং সিরিয়ালাইজেশন সবসময় "null" হলেও, Origin.from(event) ব্রাউজার-ডিসপ্যাচ করা MessageEvent থেকে প্রেরকের আসল অন্তর্নিহিত অস্বচ্ছ উৎস এক্সট্র্যাক্ট করে:
- একই স্যান্ডবক্সড iframe থেকে পাঠানো দুটি মেসেজ
Originঅবজেক্ট তৈরি করে যা একে অপরের সাথেisSameOrigin()(true)। - বিভিন্ন স্যান্ডবক্সড iframe—বা আলাদা
Origin.from('data:...')/new Origin()কল—থেকে পাঠানো মেসেজ স্বতন্ত্র অস্বচ্ছ অরিজিন তৈরি করে যাisSameOrigin()থেকেfalseপর্যন্ত মূল্যায়ন করে, যা সম্পর্কহীন অস্বচ্ছ প্রসঙ্গ জুড়ে"null" === "null"স্পুফিং প্রতিরোধ করে। new Origin()একটি নতুন, অনন্য অস্বচ্ছ অরিজিন তৈরি করে যা নিজের ছাড়া অন্য কিছুর সাথে মেলে না, যা প্রত্যাশিত পিয়ার অরিজিন একবার ইনিশিয়ালাইজেশনে পিন করার আগে ডিফল্ট সব-অস্বীকার সেন্টিনেল হিসেবে উপযোগী।
// Initialize with a unique opaque sentinel that matches no other origin
let pinnedSandboxOrigin = new Origin();
let isSandboxPinned = false;
export function handleSandboxedWidgetMessage(event, expectedWidgetWindow) {
try {
const senderOrigin = Origin.from(event);
// Pin the opaque origin only once on initialization from the expected sandboxed iframe
if (!isSandboxPinned && event.source === expectedWidgetWindow && event.data?.type === 'init') {
pinnedSandboxOrigin = senderOrigin;
isSandboxPinned = true;
}
// Subsequent messages from the SAME sandboxed iframe match pinnedSandboxOrigin;
// messages from any other sandboxed iframe (also event.origin === "null") return false.
return senderOrigin.isSameOrigin(pinnedSandboxOrigin);
} catch {
return false;
}
}
পেশাদার পদ্ধতি
isSameOrigin(other)বাisSameSite(other)কল করার আগেOrigin.from()-এর মাধ্যমে তুলনার উভয় দিকOriginইনস্ট্যান্সে কনভার্ট করুন।- অস্পষ্ট সোর্স আইডেন্টিটি সংরক্ষণ করার প্রয়োজন হলে, ব্রাউজার-ডিসপ্যাচ করা
MessageEventসরাসরিOrigin.from(event)-এ পাস করুন এবং বর্তমান এক্সিকিউশন কন্টেক্সটেরOriginপেতেOrigin.from(self)(LocationবাDocument-এর পরিবর্তে, যাTypeErrorথ্রো করে) ব্যবহার করুন। - অবশ্যই
Origin.from()কলকেtry...catchব্লকে অবিশ্বস্ত বা রানটাইম ইনপুটে র্যাপ করুন যাতে ভুল URL,"null"স্ট্রিং বা কাজ করে না এমন অবজেক্ট আনক্যাচডTypeErrorথ্রো করার পরিবর্তে নিরাপদেfalseরিটার্ন করে। "null"(origin !== 'null') প্রথমে বাতিল না করে সরাসরি দুটি রানটাইমevent.originবাurl.originস্ট্রিংয়ের তুলনা করবেন না, কারণ দুটি সম্পর্কহীন অস্বচ্ছ অরিজিনই"null"-এ সিরিয়ালাইজ করে।- কখনও
startsWith(),includes(),endsWith()বা সাধারণ.split('.')হোস্টনেম স্লাইসিংয়ের মাধ্যমে উৎস বা সাইট যাচাই করবেন না।
ফলব্যাক স্ট্র্যাটেজি
আপনার বেসলাইন টার্গেটে যদি এমন ব্রাউজার অন্তর্ভুক্ত থাকে যা এখনও Origin ইন্টারফেস সাপোর্ট করে না, তাহলে ফিচার-ডিটেক্ট 'Origin' in globalThis এবং new URL()-এর মাধ্যমে URL পার্স করার পদ্ধতিতে ফিরে যান:
- একই-অরিজিন ফলব্যাক (টুপল অরিজিন): URL স্ট্রিং এক্সট্র্যাক্ট করুন (
MessageEventঅবজেক্টের জন্যevent.originবা লিঙ্ক এলিমেন্টের জন্যcandidate.hrefব্যবহার করে),new URL()-এর মাধ্যমে ক্যান্ডিডেট ও বিশ্বস্ত URL পার্স করুন,"null"অস্বচ্ছ অরিজিন (candidateUrl.origin !== 'null') বাতিল করুন এবংcandidateUrl.origin === trustedUrl.originতুলনা করুন। যেহেতু একটি অস্বচ্ছ অরিজিন কখনই'https://app.example.com'-এর মতো টিউপল অরিজিনের সাথে একই-অরিজিন হয় না, তাই অবিলম্বে'null'-এর সাথেOrigin.isSameOrigin()-এর মিল বাতিল করা হচ্ছে। - সেম-সাইট ফলব্যাক (সতর্কতা):
URLইন্টারফেস ব্রাউজারের পাবলিক সাফিক্স তালিকা প্রকাশ করে না।Originছাড়া ব্রাউজারে, শুধুমাত্র আপনার কন্ট্রোল করা একটি স্পষ্ট, পরিচিত ব্যক্তিগত রেজিস্টারযোগ্য ডোমেনের সাথে সাফিক্স ম্যাচিং করুন (protocolএবং একটি সঠিক বা ডট-প্রিফিক্সডhostnameম্যাচ উভয়ই যাচাই করা), অথবা একটি রক্ষণাবেক্ষণ করা পাবলিক সাফিক্স লিস্ট লাইব্রেরি ব্যবহার করুন। - অস্বচ্ছ / স্যান্ডবক্স করা iframe ফলব্যাক:
Originছাড়া ব্রাউজারগুলিMessageEvent-এ স্বতন্ত্র অস্বচ্ছ অরিজিন পরিচয় প্রকাশ করে না (event.originসবসময়"null"হয়)। আপনি যদি ইচ্ছাকৃতভাবে কোনও পরিচিত স্যান্ডবক্স করা<iframe sandbox="allow-scripts">থেকে মেসেজ গ্রহণ করেন, তাহলেevent.originতুলনা করার পরিবর্তেevent.source === expectedWidgetWindowযাচাই করুন (অথবা ইনিশিয়ালাইজ করার সময় iframe-এ ট্রান্সফার করা একটি নির্দিষ্টMessageChannelMessagePort-এর মাধ্যমে যোগাযোগ করুন)।
// Replace with your trusted reference URL and known registrable domain
const TRUSTED_URL = 'https://app.example.com';
const TRUSTED_SITE_DOMAIN = 'example.com';
function extractUrlString(candidate) {
if (typeof candidate === 'string') return candidate;
if (typeof MessageEvent !== 'undefined' && candidate instanceof MessageEvent) {
return candidate.origin;
}
if (candidate === globalThis) {
return globalThis.location?.href ?? '';
}
return candidate?.href ?? '';
}
function extractOrigin(candidate) {
try {
return Origin.from(candidate);
} catch (err) {
if (typeof MessageEvent !== 'undefined' && candidate instanceof MessageEvent) {
return Origin.from(candidate.origin);
}
throw err;
}
}
export function checkSameOriginWithFallback(candidate) {
try {
if ('Origin' in globalThis) {
return extractOrigin(candidate).isSameOrigin(Origin.from(TRUSTED_URL));
}
const candidateUrl = new URL(extractUrlString(candidate));
const trustedUrl = new URL(TRUSTED_URL);
return candidateUrl.origin !== 'null' && candidateUrl.origin === trustedUrl.origin;
} catch {
return false;
}
}
export function checkSameSiteWithFallback(candidate) {
try {
if ('Origin' in globalThis) {
return extractOrigin(candidate).isSameSite(Origin.from(TRUSTED_URL));
}
const candidateUrl = new URL(extractUrlString(candidate));
const trustedUrl = new URL(TRUSTED_URL);
return (
candidateUrl.origin !== 'null' &&
candidateUrl.protocol === trustedUrl.protocol &&
(candidateUrl.hostname === TRUSTED_SITE_DOMAIN ||
candidateUrl.hostname.endsWith(`.${TRUSTED_SITE_DOMAIN}`))
);
} catch {
return false;
}
}