Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
HTTP headers for the responsible developer
Search
stefan judis
March 16, 2019
Technology
5.1k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HTTP headers for the responsible developer
stefan judis
March 16, 2019
More Decks by stefan judis
See All by stefan judis
Back to boring (part 2)
stefanjudis
0
380
Playwright can do this?
stefanjudis
0
260
Things you should know about Frontend Development in 2022
stefanjudis
0
560
Throw yourself out there for fun and profit
stefanjudis
0
140
Back to Boring
stefanjudis
1
540
Wanna scale up? Make sure your CMS is ready for it!
stefanjudis
0
290
Did we(b development) lose the right direction?
stefanjudis
6
2.2k
Regular expressions – my secret love
stefanjudis
1
1.1k
Write a Function
stefanjudis
0
630
Other Decks in Technology
See All in Technology
AIエージェントのためのデータ設計
daiz21
0
460
Introduction to Sansan, inc / Sansan Global Development Center, Inc.
sansan33
PRO
0
3.2k
1.5時間を無駄にして学んだwsl2におけるaptとsnapの選択と仕組み
yosaka0123
0
460
Claude Codeで開発以外の業務も爆速化しよう!
minorun365
PRO
9
8.1k
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.5k
わたしが知り合いゼロの勉強会に 行けるようになるまで
r5ni4
2
820
Kiro5兄弟のいまどきのセキュリティ基礎知識
kentapapa
0
340
全社に広がるMCPサーバーを、 どう安全に管理するか MCPass開発の舞台裏
mtpooh
2
130
Point Cloud as a Foreign Language for Multi-modal Large Language Model
takmin
0
130
フィジカルAIの知識ゼロの僕でも AIを使えばここまでできた
tatsuya1970
0
190
Claude Teamプランの コスト最適化を考える
rfdnxbro
0
760
dbt in Microsoft Fabric
ryomaru0825
0
290
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Tell your own story through comics
letsgokoyo
1
1k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
430
Skip the Path - Find Your Career Trail
mkilby
1
200
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.4k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
Transcript
@stefanjudis HTTP headers for the responsible developer
My journey on the web
uboot.com
1999
The web connects people
2010
The web connects people
We connect people! We enable people! We help people!
[he/him] @stefanjudis www.stefanjudis.com Heyo, I'm Stefan!
... and I want to be a responsible developer
None
1999
2019
2019
2019
2019 We should be building for everybody
"We don't have users in/that ..."
"We don't have users in/that ..."
The challenge of building a "good" website
Design Performance Content Accessibility Devices Network Frameworks
Design Performance Content Accessibility Network Frameworks Devices
Let's talk HTTP
https://the-responsible.dev/ Accept: text/html,application/xhtml+xml,application/xml Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7 ...
Connection: keep-alive Content-Type: text/html; charset=utf-8 Date: Mon, 11 Mar 2019 12:59:38 GMT ... Response Body
Accept: text/html,application/xhtml+xml,application/xml Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7 ... https://the-responsible.dev/
Connection: keep-alive Content-Type: text/html; charset=utf-8 Date: Mon, 11 Mar 2019 12:59:38 GMT ... Response Body
the-responsible.dev
How can we use headers to make this site better?
The web is a scary place
thenextweb.com/contributors/2018/03/10/protect-website-cryptojacking-attacks/
shoptalkshow.com/episodes/special-one-one-hacker/
blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident
www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers
www.twilio.com/blog/learned-about-security-from-calling-35-contact-centers We always rely on others
The web has to be safe!
HTTPS
HTTP/2 ServiceWorker getUserMedia() ...
whynohttps.com
whynohttps.com
Ensure encryption
Strict-Transport-Security: max-age=1000; includeSubDomains; preload Response Header
hstspreload.org
chromium.googlesource.com/chromium/src/net/+/master/http/ transport_security_state_static.json
None
caniuse.com/#feat=stricttransportsecurity
Upgrade HTTP requests
Content-Security-Policy: upgrade-insecure-requests Response Header
www.chromestatus.com/feature/5557268741357568
Limit what's allowed
requestmap.webperf.tools
base-uri block-all-mixed-content connect-src default-src font-src form-action frame-ancestors frame-src img-src manifest-src
media-src navigate-to object-src plugin-types report-sample report-to require-sri-for sandbox script-src strict-dynamic style-src upgrade-insecure-requests worker-src developer.mozilla.org/en-US/docs/Web/HTTP/CSP prefetch-src
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*;">
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe- inline' 'unsafe-eval' just-comments.com www.google-analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Report-To: { "group": "csp-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../csp-report"
}] }
Report-To: { "group": "csp-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../csp-report"
}] }, { "group": "network-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../network-report" }] }, { "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../general-report" }] }
developers.google.com/web/updates/2018/09/reportingapi
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' just-comments.com www.google- analytics.com
production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just- comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame- ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'; report-uri https:// stefanjudis.report-uri.com/r/d/csp/reportOnly Response Header
Content-Security-Policy: default-src 'self'; script-src 'sha256-blL...' <script> console.log('Inline script executing ...');
</script> Response Header
Content-Security-Policy: default-src 'self'; script-src 'nonce-abc...' <script nonce="abcdef"> console.log('Inline script executing
...'); </script> Response Header
caniuse.com/#feat=contentsecuritypolicy
caniuse.com/#feat=contentsecuritypolicy2 * * not complete
httparchive.org
How many pages use CSP?
USE CSP DON'T USE CSP 94% 6%
USE CSP DON'T USE CSP 94% 6% We can do
better!
Always monitor your CSP reports and "test in production" with
report-only before enforcing them! Troy Hunt
Disallow third-party cookies!
Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ...
Set-Cookie: widget_session=abc123; Response Header Set-Cookie: ... This behaviour leads to
security and privacy issues
Set-Cookie: widget_session=abc123; SameSite=None; Secure Set-Cookie: widget_session=abc123; SameSite=Lax; Secure Set-Cookie: widget_session=abc123;
SameSite=Strict; Secure Response Header
caniuse.com/#feat=same-site-cookie-attribute * * somewhat ready but maybe buggy
web.dev/samesite-cookies-explained
the-responsible.dev/safe/
The web is crucial for people.
Your sh** doesn't work in Africa. William Imoh
None
You get 6MB for 2Euros but you have only 24h
to use them! Right...
whatdoesmysitecost.com
The web has to be affordable!
Don't request the same content over and over again
Cache-Control: max-age=31536000, public, immutable Response Header
immutable developer.mozilla.org/en-US/docs/Web/HTTP/ Headers/Cache-Control
csswizardry.com/2019/03/cache-control-for-civilians/
Send the right data
Accept-Encoding: gzip, deflate, br Request Header
None
None
But Brotli compression is so slow!
GZIP Brotli vs Default Mode 6 11
GZIP Brotli Default Mode vs 6 11
GZIP Brotli Optimal middle ground vs 6 4
GZIP Brotli Optimal middle ground vs 6 4 Brotli tends
to compress better with the same speed
GZIP Brotli Optimal middle ground vs 6 4 You don't
have to do it on the fly...
blogs.akamai.com/2016/02/understanding-brotlis-potential.html
caniuse.com/#feat=brotli
None
None
Serve tailored media
<picture> <!-- serve WebP to Chrome and Opera --> <source
media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.webp 200w, /image/thing-400.webp 400w, /image/thing-800.webp 800w, /image/thing-1200.webp 1200w, /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w" type="image/webp"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w, /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w, /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w" type="image/webp"> <!-- serve JPEG to others --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w, /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w, /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w"> <source sizes="(min-width: 30em) 100vw"
/image/thing-800.webp 800w, /image/thing-1200.webp 1200w, /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w" type="image/webp"> <source
sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w, /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w, /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w" type="image/webp"> <!-- serve JPEG to others --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w, /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w, /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.jpg 200w, /image/thing-crop-400.jpg 400w, /image/thing-crop-800.jpg 800w, /image/thing-crop-1200.jpg 1200w, /image/thing-crop-1600.jpg 1600w, /image/thing-crop-2000.jpg 2000w"> <!-- fallback for browsers that don't support picture --> <img src="/image/thing.jpg" width="50%"> </picture>
Accept: image/webp, image/apng, image/*,*/*;q=0.8 Request Header
caniuse.com/#feat=webp
Accept-CH: Width, Viewport-Width Accept-CH-Lifetime: 100 Request URL: https://.../header.jpg Viewport-Width: 980
Width: 980
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 980
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 1960
<img src="/header.jpg" alt="" sizes="100vw" /> Accept: image/webp,image/apng,image/*,*/*;q=0.8 Request URL: https://.../header.jpg
Viewport-Width: 980 Width: 1064 Serve a tailored version via server/service worker
speaking.jeremy.codes/yD4dKY/take-a-client-hint
www.zdnet.com/article/privacy-concerns-raised-about-upcoming-client-hints-web-standard/
Sec-CH-UA: "Examplary Browser"; v="73" Accept-CH: UA, Platform Sec-CH-UA: "Examplary Browser";
v="73.3R8.2H.1" Sec-CH-UA-Platform: "Windows"; v="10"
wicg.github.io/ua-client-hints/
Save data
save-data: on if ("connection" in navigator) { if (navigator.connection.saveData ===
true) { // Implement data saving operations here. } } Request Header
None
Let's use the platform and make these features more visible
https://.... Save data?
https://.... Save data? We should provide an easy way to
save data!
Save data? https://.... Prefer reduced motion? Prefer a dark interface?
Save data? https://.... Reduced Motion? Dark colour Scheme? All these
settings should be easily accessible all the time!
None
blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html
blog.chromium.org/2019/03/chrome-lite-pages-for-faster-leaner.html I'm not sure how I feel about that...
Cache-Control: max-age=31536000, public, no-transform Response Header
Be aware of CDNs and proxies – use vary
None
Should browsers or developers optimise?
The browser can only optimise to a certain extend...
None
20% of requests...
https:/ /nooshu.github.io/blog/2019/09/01/speeding-up-the-web-with-save-data-header/
Less Data Doesn't Mean a Lesser Experience Tim Kadlec
the-responsible.dev/affordable/
The web is with us every day
2018.bloomca.me
It has to be respectful!
Get stuff "down" as quickly as possible
Link: </unleashed.jpg>; rel=preload; as=image; no-push <link rel="preload" href="/unleashed.jpg" as="image"> Response
Header
Link: </unleashed.jpg>; rel=preload; as=image; no-push <link rel="preload" href="/unleashed.jpg" as="image"> Response
Header This is great to speed up critical resources
caniuse.com/#feat=link-rel-preload * * behind a flag
Don't annoy the user (aka. the AMP reaction)
speakerdeck.com/stefanjudis/amp-tries-to-fix-the-web-what-can-we-learn-from-it?slide=112
Feature-Policy: vibrate 'none'; geolocation 'none' Response Header
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
accelerometer ambient-light-sensor autoplay camera document-domain encrypted-media fullscreen geolocation gyroscope layout-animations
legacy-image-formats magnetometer microphone midi oversized-images payment picture-in-picture speaker sync-xhr unoptimized-images unsized-media usb vibrate vr developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
tiny-helpers.dev
<img srcset="/screenshots/{{ item.slug }}@1.jpg 1x, /screenshots/{{ item.slug }}@2.jpg 2x" src="/screenshots/{{
item.slug }}@2.jpg" alt="Screenshot of {{ item.name }}" loading="lazy"> <img srcset="/screenshots/{{ item.slug }}@1.jpg 1x, /screenshots/{{ item.slug }}@2.jpg 2x" src="/screenshots/{{ item.slug }}@2.jpg" alt="Screenshot of {{ item.name }}" width="1000" height="600" loading="lazy">
tiny-helpers.dev
www.youtube.com/watch?v=4-d_SoCHeWE
www.youtube.com/watch?v=4-d_SoCHeWE Define width & height to avoid jumpy pages
None
new ReportingObserver((reports, observer) => { reports.forEach(({type, url, body}) => {
console.log(type, url); // 'feature-policy-violation', https://some-url.com/... console.log(body); // { // featureId: 'oversized-images', // sourceFile: 'https://path-to-image/... // ... // } }); }, {types: ['feature-policy-violation'], buffered: true}).observe();
Report-To: { "max_age": 10886400, "endpoints": [{ "url": "https://stefanjudis.com/.../general-report" }] }
timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/
feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer
'none'; microphone 'none'; payment 'none'; usb 'none' Response Header
<iframe allow="camera 'none'; microphone 'none'"> document.featurePolicy.allowedFeatures(); // → ["geolocation", "midi",
...] document.featurePolicy.allowsFeature('geolocation'); // → true document.featurePolicy.getAllowlistForFeature('geolocation'); // → ["https://example.com"]
What happened to the most annoying one?
github.com/w3c/webappsec-feature-policy/issues/243
blog.chromium.org/2020/01/introducing-quieter-permission-ui-for.html
caniuse.com/#feat=feature-policy ** support only for allow on iframes ** *
support for Feature-Policy header, allow on iframes, and JS API behind a flag * * * **
Respect privacy
None
caniuse.com/#feat=do-not-track
webkit.org/blog/8594/release-notes-for-safari-technology-preview-75/
caniuse.com/#feat=do-not-track
caniuse.com/#feat=do-not-track It was a nice try, but I don't really
see that happening...
None
None
None
None
www.xanjero.com/news/samsung-internet-beta-version-9-2-now-includes-oneui-design-smart- anti-tracking-and-more-features/
webkit.org/blog/category/privacy/
www.engadget.com/2019/11/04/chromium-edge-browser-release-date/
The next browser war is on its way...
the-responsible.dev/respectful/
Building for the web is very hard
Design Performance Content Accessibility Devices Network Frameworks
Lighthouse
webhint.io
If you want to get a more complete overview...
www.twilio.com/blog/a-http-headers-for-the-responsible-developer
securityheaders.com
schepp.github.io/HTTP-headers
youtu.be/II9m9_esNZc
The web has to be safe...
The web has to be safe, affordable...
The web has to be safe, affordable and respectful...
... so that it really is for everybody!
@stefanjudis www.stefanjudis.com Thanks. Slides: my-links.online/the-responsible-dev
@stefanjudis www.stefanjudis.com Thanks. Slides: my-links.online/the-responsible-dev I have some stickers!