1
00:00:01,200 --> 00:00:06,283
The loader that fetches the cat photo also fetches the keylogger.

2
00:00:06,483 --> 00:00:12,901
To the browser, every URL in a page is a request to make and a response to use.

3
00:00:13,043 --> 00:00:14,643
A picture is drawn.

4
00:00:14,726 --> 00:00:17,058
A stylesheet is applied.

5
00:00:17,141 --> 00:00:22,665
A script is run, with all the power the page itself has.

6
00:00:22,866 --> 00:00:26,092
The browser does not ask whether you meant it.

7
00:00:26,175 --> 00:00:31,061
It trusts the page, and the page trusted everything it named.

8
00:00:31,261 --> 00:00:34,812
So everything you embed is a decision.

9
00:00:34,953 --> 00:00:46,422
This film follows five ways that decision goes wrong, on Demo Company's pages, and the line or two of HTML that answers each one.

10
00:00:47,121 --> 00:00:51,508
Some of a page comes from your own server: the first party.

11
00:00:51,649 --> 00:00:55,281
Some comes from someone else's: a third party.

12
00:00:55,306 --> 00:00:58,160
A component library from a CDN.

13
00:00:58,185 --> 00:00:59,728
An analytics tag.

14
00:00:59,811 --> 00:01:02,932
A photo from a stock site.

15
00:01:03,132 --> 00:01:07,600
92% of pages load something from a third party.

16
00:01:07,997 --> 00:01:16,760
Each one is another server to reach, another connection to set up, and another organization you are trusting.

17
00:01:16,960 --> 00:01:21,869
You don't control its speed, its uptime, or what it sends tomorrow.

18
00:01:21,894 --> 00:01:30,310
And the browser won't even show you its real sizes unless that server agrees to share them.

19
00:01:31,010 --> 00:01:34,433
A slow image is an inconvenience.

20
00:01:34,516 --> 00:01:41,805
When it finally arrives, though, everything below it jumps, and the reader loses their place.

21
00:01:42,006 --> 00:01:44,245
The answer is two numbers.

22
00:01:44,363 --> 00:01:51,722
Give the image its width and height, and the browser saves the space before a single byte arrives.

23
00:01:51,991 --> 00:01:59,767
Add loading="lazy" to images below the fold, and they stop competing with what the reader can see.

24
00:01:59,967 --> 00:02:02,775
A slow script is worse.

25
00:02:02,800 --> 00:02:09,520
A plain script tag in the head stops the page until that script has downloaded and run.

26
00:02:09,917 --> 00:02:15,453
If someone else's server is having a bad day, your page is blank.

27
00:02:15,653 --> 00:02:21,572
Add defer, and the script downloads alongside the page and runs after it.

28
00:02:21,783 --> 00:02:27,099
The reader gets your content, whatever the other server is doing.

29
00:02:27,798 --> 00:02:30,606
Sometimes the file isn't there at all.

30
00:02:30,817 --> 00:02:35,900
The server answers 404, and the picture never comes.

31
00:02:36,100 --> 00:02:38,838
What's left is whatever you wrote around it.

32
00:02:39,049 --> 00:02:42,913
Good alt text tells the reader what should be there.

33
00:02:43,054 --> 00:02:47,824
A width and height keep the page from collapsing.

34
00:02:48,024 --> 00:02:50,216
The same holds for scripts.

35
00:02:50,358 --> 00:02:56,509
If the page works without the script, a missing script costs a feature, not the page.

36
00:02:56,592 --> 00:03:02,163
That is progressive enhancement, doing its job on an ordinary Tuesday.

37
00:03:02,864 --> 00:03:11,790
Page eleven loads a script that writes down every key you press, every click, and where your mouse goes.

38
00:03:11,931 --> 00:03:15,145
Here it only prints them to the console.

39
00:03:15,171 --> 00:03:18,768
It could just as easily send them somewhere.

40
00:03:18,967 --> 00:03:23,284
A script on your page runs with your page's full power.

41
00:03:23,588 --> 00:03:27,417
It sees what the reader types, including passwords.

42
00:03:27,628 --> 00:03:30,831
Nothing in HTML gives it less.

43
00:03:31,031 --> 00:03:33,711
And a script you trusted can change.

44
00:03:33,771 --> 00:03:47,213
In 2024, a widely used script changed owners and began serving harmful code to thousands of sites that still loaded it, without any of them changing a line.

45
00:03:47,413 --> 00:03:52,694
So load as few scripts as you can, and read the ones you load.

46
00:03:53,090 --> 00:04:01,831
A Content Security Policy header limits where scripts may come from and where the page may send data.

47
00:04:02,531 --> 00:04:08,125
Page twelve waits three seconds, then covers everything with a message of its own.

48
00:04:08,522 --> 00:04:13,326
A script that can draw on your page can draw over it.

49
00:04:13,527 --> 00:04:25,158
If that script came from someone else's server, the server can change the file at the same address, and every page that loads it gets the new version.

50
00:04:25,358 --> 00:04:29,234
Subresource Integrity pins the exact bytes.

51
00:04:29,445 --> 00:04:37,825
The script tag carries a hash of the file you checked, and the browser refuses any file that doesn't match.

52
00:04:38,025 --> 00:04:46,824
A changed file then fails safely: one feature missing, instead of your page working for someone else.

53
00:04:47,524 --> 00:04:52,909
Slow, blocked, missing, watching, hostile.

54
00:04:53,213 --> 00:04:56,369
None of these needed an attacker on your server.

55
00:04:56,510 --> 00:04:59,620
They only needed you to embed something.

56
00:04:59,819 --> 00:05:10,452
Each fix is a line or two of HTML or one header: sizes, defer, alt text, a policy, a hash.

57
00:05:10,756 --> 00:05:13,865
Cheap, once you know to write them.

58
00:05:14,066 --> 00:05:22,957
Open Demo Company's broken pages beside their fixed twins, and watch the Network panel tell both stories.

59
00:05:23,157 --> 00:05:29,517
Everything you embed works for you, or against you, on someone else's screen.

60
00:05:29,821 --> 00:05:32,141
Choose it on purpose.
