WEBVTT

1
00:00:01.200 --> 00:00:02.905
Here's a checkout form.

2
00:00:03.046 --> 00:00:12.437
It has a product, a quantity from one to five, a price, a total, a shipping choice, a name, and a box to tick.

3
00:00:12.647 --> 00:00:16.593
On its developer's machine, it works perfectly.

4
00:00:16.793 --> 00:00:18.626
Then it goes live.

5
00:00:18.674 --> 00:00:33.428
Now it meets people who can edit the page, programs that never load the page at all, customers in other countries with other names, addresses and money, and laws about what a form may collect.

6
00:00:33.535 --> 00:00:36.412
Let's meet them, one at a time.

7
00:00:37.112 --> 00:00:44.134
Every check in this form runs in the browser, and the browser belongs to the person using it.

8
00:00:44.275 --> 00:00:50.833
Open the developer tools, and every constraint is just an attribute you can delete.

9
00:00:51.033 --> 00:00:53.121
Remove the limit on quantity.

10
00:00:53.146 --> 00:00:55.350
Enable the members-only shipping.

11
00:00:55.561 --> 00:00:59.936
And the price, in a hidden field, is just as easy to edit.

12
00:01:00.077 --> 00:01:01.306
One cent.

13
00:01:01.331 --> 00:01:07.030
Send it, and the server receives exactly that: a price of one cent.

14
00:01:07.230 --> 00:01:09.330
It doesn't even take a browser.

15
00:01:09.355 --> 00:01:17.166
One line of curl sends the same order, and never sees the form, so it never learns the constraints existed.

16
00:01:17.307 --> 00:01:20.580
All the server ever gets is text.

17
00:01:20.779 --> 00:01:33.409
Think of the form's checks less as a fence that keeps bad things out, and more as a receptionist: helpful, quick, there to start honest people on their way.

18
00:01:33.794 --> 00:01:39.667
Then they're passed on to a security guard, on your server, who checks everything again.

19
00:01:39.808 --> 00:01:42.592
The receptionist can be talked past.

20
00:01:42.617 --> 00:01:46.157
The security guard must never be skipped.

21
00:01:46.857 --> 00:01:58.488
So the server checks everything again, with the same rules: quantity one to five, shipping that this customer is allowed, a name of sensible length.

22
00:01:58.688 --> 00:02:01.658
It never reads a price from a form.

23
00:02:01.962 --> 00:02:06.093
It looks the price up from the product, in its own catalog.

24
00:02:06.304 --> 00:02:09.623
The price field shouldn't be in the form at all.

25
00:02:09.823 --> 00:02:23.161
It treats every field as untrusted text: encoded before it's shown on a page, so a name can't become a script, and passed to the database as data, never pasted into a query.

26
00:02:23.302 --> 00:02:31.660
And it checks that the request came from its own form, not from another site that tricked a logged-in browser into sending it.

27
00:02:31.963 --> 00:02:36.559
CSE 135 teaches the server side in full.

28
00:02:36.863 --> 00:02:41.098
For now, focus on making the collection smooth.

29
00:02:41.798 --> 00:02:48.019
Between the browser and the server, the form's data crosses networks you don't control.

30
00:02:48.404 --> 00:02:55.531
H T T P S encrypts it on the way, for every form, not just the password page.

31
00:02:55.742 --> 00:03:02.857
Browsers warn people about password fields on plain H T T P pages, and they're right to.

32
00:03:03.057 --> 00:03:07.583
H T T P S doesn't protect what the URL shows.

33
00:03:07.759 --> 00:03:18.323
A form sent with GET puts its fields in the address: in the history, in bookmarks, in server logs, and in the referrer sent to the site's own pages.

34
00:03:18.661 --> 00:03:21.515
Anything personal goes in a POST.

35
00:03:21.715 --> 00:03:25.974
For passwords, the current guidance is refreshingly simple.

36
00:03:26.359 --> 00:03:37.479
Let password managers fill them in, let people paste, require a long password rather than a complicated one, and don't force changes on a schedule.

37
00:03:38.180 --> 00:03:40.756
Not every visitor is a person.

38
00:03:40.897 --> 00:03:47.269
Bots fill in forms by the thousand: sign-ups, comments, password guesses.

39
00:03:47.410 --> 00:03:52.040
A form can catch a lot of them without bothering anyone.

40
00:03:52.240 --> 00:03:57.347
A honeypot field, hidden from people, that only a bot fills in.

41
00:03:57.743 --> 00:04:03.419
A check on timing, because no human completes a checkout in a tenth of a second.

42
00:04:03.815 --> 00:04:05.845
Rate limits on the server.

43
00:04:05.928 --> 00:04:11.255
And only as a last resort, a challenge, usually a CAPTCHA.

44
00:04:11.455 --> 00:04:22.471
Because a puzzle meant to stop bots also stops people: those using screen readers, or switch controls, or just a small screen on a bad day.

45
00:04:22.775 --> 00:04:29.866
The web's design principles say it plainly: when there's a trade-off, put user needs first.

46
00:04:30.067 --> 00:04:36.729
And now some visitors are agents: AI assistants filling in forms on a person's behalf.

47
00:04:37.126 --> 00:04:40.503
A well-labeled form is easier for them too.

48
00:04:40.644 --> 00:04:43.475
What doesn't change is who decides.

49
00:04:43.685 --> 00:04:49.732
The server still must check every value, whoever, or whatever, sent it.

50
00:04:50.432 --> 00:04:53.878
Real customers aren't all in one country.

51
00:04:54.019 --> 00:04:58.139
This form requires a state and a five-digit ZIP code.

52
00:04:58.350 --> 00:05:02.063
That fits an address in the United States.

53
00:05:02.264 --> 00:05:05.211
A British postcode mixes letters and digits.

54
00:05:05.294 --> 00:05:09.855
A Japanese address is written from the largest area to the smallest.

55
00:05:10.159 --> 00:05:13.315
Hong Kong has no postal code at all.

56
00:05:13.619 --> 00:05:17.611
For each of them, this form is simply broken.

57
00:05:17.810 --> 00:05:21.523
Ask for the country first and adapt the rest to it.

58
00:05:21.723 --> 00:05:29.941
Use one field for a full name, because not everyone has a first name and a last name in that order, or at all.

59
00:05:30.082 --> 00:05:34.643
And let people write in their own language and direction.

60
00:05:35.343 --> 00:05:37.535
Money changes shape too.

61
00:05:37.677 --> 00:05:45.001
Americans write one thousand two hundred thirty-four dollars and fifty-six cents with a comma and a point.

62
00:05:45.304 --> 00:05:50.132
Germans write the same amount with a point and a comma.

63
00:05:50.332 --> 00:05:59.827
In our test, one browser's number field read a German customer's amount as more than a hundred thousand, without a word of warning.

64
00:06:00.038 --> 00:06:07.165
A text field with a decimal keyboard, and a server that knows the customer's locale, does better.

65
00:06:07.365 --> 00:06:12.727
Always say which currency, and never guess it from where someone seems to be.

66
00:06:12.938 --> 00:06:20.529
And remember the first lesson: the page shows a price, but the server decides what to charge.

67
00:06:21.229 --> 00:06:27.880
Every field you add is data you have to protect, and a reason for someone to give up.

68
00:06:28.276 --> 00:06:38.572
So the best rule is the oldest: collect only what you need, for a purpose you've said, and keep it only as long as you need it.

69
00:06:38.772 --> 00:06:41.916
In much of the world, that's also the law.

70
00:06:42.127 --> 00:06:50.067
Europe's privacy regulation requires exactly that minimization, and consent that's really given.

71
00:06:50.370 --> 00:06:53.178
A pre-ticked box isn't consent.

72
00:06:53.319 --> 00:06:59.181
California has its own privacy law, which reaches many of the sites you'll build.

73
00:06:59.380 --> 00:07:03.105
Children under thirteen bring stricter rules.

74
00:07:03.246 --> 00:07:08.028
Card numbers belong in your payment processor's own fields, never yours.

75
00:07:08.238 --> 00:07:12.892
And accessible forms are a legal duty in more and more places.

76
00:07:13.196 --> 00:07:15.585
None of this is legal advice.

77
00:07:15.611 --> 00:07:18.999
It's a reason to ask before you build.

78
00:07:19.199 --> 00:07:20.706
One more thing to know.

79
00:07:21.010 --> 00:07:32.607
In a 2022 study, thousands of popular sites sent people's email addresses to tracking companies as they typed, sometimes before they ever pressed send.

80
00:07:33.003 --> 00:07:43.137
Every script you put on a page can read every field, so think carefully about whether your third-party dependencies are breaking your rules.

81
00:07:43.837 --> 00:07:48.827
Real forms meet real people, real attackers, and real rules.

82
00:07:48.969 --> 00:07:50.848
The browser helps the person.

83
00:07:50.931 --> 00:07:53.193
The server protects the data.

84
00:07:53.276 --> 00:07:57.605
And the form in between asks only for what it needs.

85
00:07:57.805 --> 00:08:05.617
JavaScript can take forms further: sending them without a page reload, formatting what people type, saving a draft.

86
00:08:05.700 --> 00:08:08.182
The rest of the course gets there.

87
00:08:08.382 --> 00:08:11.167
But HTML is the start.

88
00:08:11.192 --> 00:08:14.754
Get it wrong here, and nothing later fixes it.

89
00:08:14.895 --> 00:08:22.428
Try the tamper demo on the Form Security page, and see for yourself what a server receives.
