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

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

עדכונים

  • 21 ביוני 2022: צריך לטפל גם בסקריפטים של worker כשמופעלת בידוד בין מקורות. הוספנו כמה הסברים.
  • 5 באוגוסט 2021: ה-API לפרופיל עצמי של JS הוזכר כאחד מממשקי ה-API שדורשים בידוד בין מקורות, אבל הוא משקף שינוי שבוצע לאחרונה בכיוון, הוא יוסר.
  • 6 במאי 2021: על סמך משוב ובעיות שדווחו, החלטנו להתאים את לוח הזמנים לשימוש ב-SharedArrayBuffer באתרים שאינם מבודדים ממקורות שונים שיוגבלו בגרסה M92 של Chrome.
  • 16 באפריל 2021: נוספו הערות לגבי מצב חדש ללא פרטי כניסה ב-COEP וחלונות קופצים עם אפשרות מקור זהה של COOP כך שיהיו תנאי רגוע לבידוד בין מקורות.
  • 5 במרץ 2021: הוסרו המגבלות על הפונקציות של SharedArrayBuffer, performance.measureUserAgentSpecificMemory() וניפוי באגים. ההגבלות האלה מופעלות עכשיו באופן מלא ב-Chrome 89. נוספו יכולות עתידיות, performance.now() ו-performance.timeOrigin, שיהיו מדויקות יותר.
  • 19 בפברואר 2021: נוספה הערה לגבי המדיניות בנושא תכונות allow="cross-origin-isolated" ופונקציונליות של ניפוי באגים בכלי הפיתוח.
  • 15 באוקטובר 2020: self.crossOriginIsolated זמין ב-Chrome 87. על סמך זאת, אי אפשר לשנות את הערך document.domain כאשר self.crossOriginIsolated מחזיר את הערך true. גרסת המקור של performance.measureUserAgentSpecificMemory() עומדת להסתיים, והיא מופעלת כברירת מחדל ב-Chrome 89. Shared Array Buffer ב-Android Chrome יהיה זמין ב-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.

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

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

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 אם אפשר.
  • במשאבים ממקורות שונים שאין לכם שליטה עליהם:
    • אם המשאב מוצג עם CORS, השתמשו במאפיין crossorigin בתג ה-HTML שנטען. (לדוגמה, <img src="***" crossorigin>).
    • יש לבקש מבעל המשאב לתמוך ב-CORS או ב-CORP.
  • במסגרות iframe, צריך לפעול לפי אותם העקרונות שלמעלה ולהגדיר את הערך Cross-Origin-Resource-Policy: cross-origin (או same-site, same-origin בהתאם להקשר).
  • חובה להציג סקריפטים שנטענים עם WebWorker ממקור זהה, כך שלא צריך כותרות CORP או CORS.
  • למסמך או ל-worker שמוצגים באמצעות 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 כדי לבדוק אם המדיניות באמת עובדת. יתקבלו דיווחים בלי לחסום תוכן מוטמע.

להחיל אותה באופן חזרתי על כל המסמכים, כולל מסמכים ברמה העליונה, מסגרות iframe וסקריפטים של worker. למידע נוסף על כותרת ה-HTTP של Report-Only, ראו מעקב אחר בעיות באמצעות Reporting API.

4. הפעל COEP

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

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

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

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

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

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

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

פרטים על בעיית COEP מוצגים בכרטיסייה &#39;כותרות&#39; לאחר לחיצה על משאב רשת בחלונית &#39;רשת&#39;.

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

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

כלי לבדיקת iframe של כלי פיתוח ל-Chrome

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

כלי לבדיקת החלון הקופץ של כלי הפיתוח ל-Chrome

איתור בעיות באמצעות 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"
}]

סיכום

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

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

משאבים