הפיכת האתר שלך "מבודד ממקורות שונים" באמצעות COOP ו-COEP

אפשר להשתמש ב-COOP וב-COEP כדי להגדיר סביבה מבודדת בין מקורות שונים ולהפעיל תכונות חזקות כמו SharedArrayBuffer, ‏ performance.measureUserAgentSpecificMemory() וטימר ברזולוציה גבוהה עם דיוק משופר.

עדכונים

  • 21 ביוני 2022: צריך להיזהר גם כשמפעילים בידוד בין מקורות (CORS) בסקריפטים של עובדים. הוספנו כמה הסברים.
  • 5 באוגוסט 2021: JS Self-Profiling API הוזכר כאחד מממשקי ה-API שדורשים בידוד בין מקורות, אבל בהתאם לשינוי שנעשה לאחרונה, הוא הוסר.
  • 6 במאי 2021: על סמך המשוב והבעיות שדווחו, החלטנו לשנות את לוח הזמנים להגבלת השימוש ב-SharedArrayBuffer באתרים שלא מבודדים מדומיינים אחרים בגרסה M92 של Chrome.
  • 16 באפריל 2021: נוספו הערות לגבי מצב חדש ל-COEP ללא פרטי כניסה וCOOP‏ same-origin-allow-popups כתנאי מופחת לבידוד בין מקורות.
  • 5 במרץ 2021: הסרנו את המגבלות על הפונקציות SharedArrayBuffer,‏ performance.measureUserAgentSpecificMemory() ותיקון באגים, והן מופעלות עכשיו באופן מלא ב-Chrome 89. נוספו יכולות עתידיות, performance.now() ו-performance.timeOrigin, עם רמת דיוק גבוהה יותר.
  • 19 בפברואר 2021: הוספנו הערה לגבי מדיניות התכונות allow="cross-origin-isolated" ולגבי הפונקציונליות של ניפוי הבאגים ב-DevTools.
  • 15 באוקטובר 2020: התכונה self.crossOriginIsolated זמינה מ-Chrome 87 ואילך. בהתאם לכך, המשתנה document.domain לא ניתן לשינוי כש-self.crossOriginIsolated מחזיר את הערך true. performance.measureUserAgentSpecificMemory() מסיים את תקופת הניסיון במקור, והוא מופעל כברירת מחדל ב-Chrome 89. התכונה 'מערך משותף של מאגרי נתונים זמניים' ב-Chrome ל-Android תהיה זמינה החל מגרסת Chrome 88.

ממשקי API מסוימים לאינטרנט מגבירים את הסיכון להתקפות בערוץ צדדי כמו Spectre. כדי לצמצם את הסיכון הזה, הדפדפנים מציעים סביבה מבודדת שמבוססת על הסכמה, שנקראת 'מבודדת בין מקורות'. במצב של בידוד בין מקורות, דף האינטרנט יוכל להשתמש בתכונות עם הרשאות, כולל:

API תיאור
SharedArrayBuffer נדרש לשרשור של WebAssembly. התכונה הזו זמינה ב-Android Chrome 88 ואילך. הגרסה למחשב מופעלת כרגע כברירת מחדל בעזרת בידוד האתרים, אבל תידרש לה סטטוס בידוד חוצה-מקורות, ו היא תושבת כברירת מחדל ב-Chrome 92.
performance.measureUserAgentSpecificMemory() התכונה זמינה מ-Chrome 89.
performance.now(), performance.timeOrigin האפשרות הזו זמינה כרגע בדפדפנים רבים, והרזולוציה מוגבלת ל-100 מיקרו-שניות ומעלה. בידוד בין מקורות יכול להוביל לרזולוציה של 5 מיקרו-שניות או יותר.
תכונות שיהיו זמינות אחרי מצב מבודד ממקורות שונים.

המצב 'חסום לגישה מדומיינים אחרים' מונע גם שינויים ב-document.domain. (היכולת לשנות את document.domain מאפשרת תקשורת בין מסמכים באותו אתר, ונחשבה לפרצה במדיניות המקור הזהה).

כדי להביע הסכמה למצב של בידוד ממקורות שונים, צריך לשלוח את כותרות ה-HTTP הבאות במסמך הראשי:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

הכותרות האלה מורות לדפדפן לחסום את טעינת המשאבים או ה-iframes שלא הביעו הסכמה לטעינת מסמכים ממקורות שונים, ולמנוע מחלונות ממקורות שונים לקיים אינטראקציה ישירה עם המסמך. המשמעות היא גם שצריך לקבל הסכמה להפעלת משאבים שנטענים ממקורות שונים.

כדי לקבוע אם דף אינטרנט נמצא במצב של בידוד בין מקורות, אפשר לבדוק את הערך של self.crossOriginIsolated.

במאמר הזה נסביר איך משתמשים בכותרות החדשות האלה. במאמר המשך אציג רקע והקשר נוספים.

פריסה של COOP ו-COEP כדי לבצע בידוד של האתר ממקורות שונים

שילוב של COOP ו-COEP

1. מגדירים את הכותרת Cross-Origin-Opener-Policy: same-origin במסמך ברמה העליונה

הפעלת COOP: same-origin במסמך ברמה העליונה תגרום לכך שלחלונות עם אותו מקור ולחלונות שנפתחים מהמסמך תהיה קבוצה נפרדת של הקשרי גלישה, אלא אם הם נמצאים באותו מקור עם אותה הגדרת COOP. כך מתבצעת אכיפה של בידוד בחלונות פתוחים, ותקשורת הדדית בין שני החלונות מושבתת.

קבוצת הקשר של הגלישה היא קבוצה של חלונות שיכולים להפנות זה לזה. לדוגמה, מסמך ברמה העליונה ומסמכי הצאצא שלו שמוטמעים באמצעות <iframe>. אם אתר (https://a.example) פותח חלון קופץ (https://b.example), לחלון הפותח ולחלון הקופץ יש את אותו הקשר גלישה, ולכן יש להם גישה זה לזה דרך ממשקי API של DOM, כמו window.opener.

קבוצת הקשר של גלישה

אפשר לבדוק אם הגורם שפתח את החלון והגורם שפתח את החלון שנפתח נמצאים בקבוצות הקשר נפרדות של גלישה מ-DevTools.

2. מוודאים שהאפשרות CORP או CORS מופעלת במשאבים

חשוב לוודא שכל המשאבים בדף נטענים עם כותרות HTTP מסוג CORP או CORS. השלב הזה נדרש לשלב ארבע, הפעלת COEP.

כך עושים זאת בהתאם לאופי המשאב:

  • אם המשאב צפוי להיטען רק מאותו מקור, צריך להגדיר את הכותרת Cross-Origin-Resource-Policy: same-origin.
  • אם המשאב צפוי להיטען רק מאותו אתר אבל ממקורות שונים, צריך להגדיר את הכותרת Cross-Origin-Resource-Policy: same-site.
  • אם המשאב נטען ממקורות שונים בשליטתכם, אפשר להגדיר את הכותרת Cross-Origin-Resource-Policy: cross-origin אם אפשר.
  • למשאבים ממקורות שונים שאין לכם שליטה עליהם:
    • משתמשים במאפיין crossorigin בתג ה-HTML של הטעינה אם המשאב מוצג באמצעות CORS. (לדוגמה, <img src="***" crossorigin>).
    • מבקשים מבעלי המשאב לתמוך ב-CORS או ב-CORP.
  • ב-iframes, פועלים לפי אותם עקרונות שמפורטים למעלה ומגדירים את הערך של Cross-Origin-Resource-Policy: cross-origin (או same-site, same-origin, בהתאם להקשר).
  • סקריפטים שנטענים באמצעות WebWorker חייבים להיכלל מאותו מקור, כך שאין צורך בכותרות CORP או CORS.
  • במסמך או בעובד שמוצגים באמצעות COEP: require-corp, משאבי משנה ממקורות שונים שנטענים ללא CORS חייבים להגדיר את הכותרת Cross-Origin-Resource-Policy: cross-origin כדי להביע הסכמה להטמעה. לדוגמה, הכלל הזה חל על <script>, importScripts, <link>, <video>, <iframe> וכו'.

3. שימוש בכותרת ה-HTTP של COEP לדיווח בלבד כדי להעריך משאבים מוטמעים

לפני שמפעילים את COEP באופן מלא, אפשר לבצע בדיקה באמצעות הכותרת Cross-Origin-Embedder-Policy-Report-Only כדי לבדוק אם המדיניות פועלת בפועל. תקבלו דוחות בלי לחסום תוכן מוטמע.

מחילים את זה באופן רפלקסיבי על כל המסמכים, כולל המסמך ברמה העליונה, iframes וסקריפטים של עובדים. למידע על כותרת ה-HTTP 'דיווח בלבד', ראו מעקב אחר בעיות באמצעות Reporting API.

4. הפעלת COEP

אחרי שמוודאים שכל מה שצריך עובד ושאפשר לטעון את כל המשאבים, מחליפים את הכותרת Cross-Origin-Embedder-Policy-Report-Only בכותרת Cross-Origin-Embedder-Policy עם אותו ערך בכל המסמכים, כולל אלה שמוטמעים באמצעות iframes וסקריפטים של עובדים.

בדיקה אם הבידוד הצליח באמצעות self.crossOriginIsolated

הנכס self.crossOriginIsolated מחזיר את הערך true כשדף האינטרנט נמצא במצב של בידוד בין מקורות, וכל המשאבים והחלונות מבודדים באותה קבוצת הקשר של הגלישה. אפשר להשתמש ב-API הזה כדי לקבוע אם הצלחתם לבודד את קבוצת ההקשר של הגלישה וקיבלתם גישה לתכונות מתקדמות כמו performance.measureUserAgentSpecificMemory().

ניפוי באגים באמצעות כלי הפיתוח ל-Chrome

במקורות מידע שמוצגים במסך, כמו תמונות, קל לזהות בעיות שקשורות ל-COEP כי הבקשה תיחסם והדף יציג הודעה על כך שחסרה תמונה. עם זאת, במשאבים שלא בהכרח יש להם השפעה חזותית, כמו סקריפטים או סגנונות, יכול להיות שלא תבחינו בבעיות שקשורות ל-COEP. במקרים כאלה, צריך להשתמש בחלונית Network (רשת) של DevTools. אם יש בעיה ב-COEP, הערך (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) יופיע בעמודה Status.

בעיות COEP בעמודה &#39;סטטוס&#39; בחלונית &#39;רשת&#39;.

לאחר מכן תוכלו ללחוץ על הרשומה כדי לראות פרטים נוספים.

פרטי הבעיה בנושא COEP מוצגים בכרטיסייה Headers (כותרות) אחרי שלוחצים על משאב רשת בחלונית Network (רשת).

אפשר גם לקבוע את הסטטוס של iframes וחלונות קופצים באמצעות החלונית Application. עוברים לקטע Frames (מסגרות) בצד ימין ומרחיבים את האפשרות top (ראש) כדי לראות את פירוט מבנה המשאב.

אפשר לבדוק את סטטוס ה-iframe, למשל את הזמינות של SharedArrayBuffer וכו'.

הכלי לבדיקת iframe ב-Chrome DevTools

אפשר גם לבדוק את הסטטוס של חלונות הקופצים, למשל אם הם מבודדים בין מקורות.

הכלי לבדיקת חלונות קופצים ב-Chrome DevTools

איתור בעיות באמצעות Reporting API

Reporting API הוא מנגנון נוסף שבעזרתו אפשר לזהות בעיות שונות. אפשר להגדיר את Reporting API כך שיורה לדפדפן של המשתמשים לשלוח דוח בכל פעם ש-COEP חוסם את טעינת המשאב או ש-COOP מבודד חלון קופץ. Chrome תומך ב-Reporting API מאז הגרסה 69 למגוון שימושים, כולל COEP ו-COOP.

במאמר שימוש ב-Reporting API מוסבר איך מגדירים את Reporting API ואת השרת לקבלת דוחות.

דוגמה לדוח COEP

דוגמה למטען ייעודי (payload) של דוח COEP כשמשאב מאתר אחר חסום:

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.glitch.me/check.svg?",
    "blockedURL": "https://third-party-test.glitch.me/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.glitch.me/?coep=require-corp&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]

דוגמה לדוח COOP

דוגמה למטען ייעודי (payload) של דוח COOP כשחלון קופץ נפתח בנפרד:

[{
  "age": 7,
  "body": {
    "disposition": "enforce",
    "effectivePolicy": "same-origin",
    "nextResponseURL": "https://third-party-test.glitch.me/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

כשקבוצות שונות של הקשרי גלישה מנסים לגשת זו לזו (רק במצב 'דיווח בלבד'), גם דיווח COOP נשלח. לדוגמה, דוח של ניסיון להפעיל את postMessage() ייראה כך:

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.glitch.me/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
  "age": 51785,
  "body": {
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "property": "postMessage",
    "type": "access-to-coop-page-from-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

סיכום

שימוש בשילוב של כותרות HTTP מסוג COOP ו-COEP כדי להעביר דף אינטרנט למצב מיוחד של בידוד בין מקורות. תוכלו לבדוק את הערך של self.crossOriginIsolated כדי לקבוע אם דף אינטרנט נמצא במצב מבודד בין מקורות.

נעדכן את הפוסט הזה כשתכונות חדשות יהיו זמינות למצב המבודד הזה בין מקורות, וכשיבוצעו שיפורים נוספים ב-DevTools בנושאי COOP ו-COEP.

משאבים