What is a trust boundary?
Every site has places where data passes from something you control to something you do not, or the other way round. Your server and your database are under your control. The visitor's browser, the network in between and anything another site sends are not. The line between those two areas is a trust boundary, and most security bugs happen where data crosses it without a check.
For a small site the main boundary sits at the edge of your server. Everything inside server.js was written by you. Everything in req, the object that holds the incoming request, arrived from outside: req.body with the form fields, req.query with the part of the address after ?, req.params with parts of the path, req.headers with the headers and req.cookies with the cookies. Any of it could have been typed, edited or invented by whoever sent the request.
- Form fields, including hidden ones and drop-down choices.
- The page address and everything after
?in it. - Cookies, which the browser stores and the visitor can edit.
- Headers such as
User-Agent,RefererandOrigin. - Uploaded files, including their names and claimed types.
- Replies from other sites' APIs, which may be wrong or compromised.
Why could the attacker change the price?
The bakery's order form has a hidden field, <input name="price" type="hidden" value="32.00">. It is hidden on the page, which makes it feel private, but it is part of the HTML the browser received, and the browser belongs to the visitor. Anyone can open developer tools, find the field in the Elements panel and change 32.00 to 0.01. They can also skip the form altogether and send the request with a tool.
The server then ran const total = req.body.price * qty;. It took the price from the request and trusted it. In the lab this let the attacker order a celebration cake for 0.01. On a real shop the same pattern has let people pay whatever they liked, apply discounts many times, or order items marked as sold out.
The fix is to decide which facts the server already knows and stop accepting them from outside. The price of item 7 lives in the bakery's own database. The browser only needs to say which item and how many.
app.post('/order', (req, res) => {
const qty = Number(req.body.qty);
const item = db.get('SELECT price FROM menu WHERE id = ?', [req.body.item]);
const total = item.price * qty;
// ...
});

Does checking the form in the browser help?
Checks in the browser make the form friendlier and do nothing for security. The bakery's quantity box has min="1" max="5", so the browser refuses to submit 50 cakes and shows a helpful message. A visitor who edits the HTML, turns off JavaScript or sends the request with a tool skips all of that. To the server, a request from a tool looks the same as one from the form.
The working habit is to check everything twice: once in the browser for a quick, kind response to honest mistakes, and again on the server as the real rule. In the bakery, the server should turn the quantity into a number, refuse anything below 1 or above 5, and refuse an item id that is not on today's menu. If the server check is missing, the browser check is only decoration.
What should the server check on the way in?
For each field, ask what a correct value looks like and refuse anything else. A quantity is a whole number in a range. An item id must exist in the menu table. An email address should look like one and fit in the column. A pickup date must be in the future and on a day the shop is open. Checking this way, against a description of what is allowed, is often called validation.
Validation narrows what reaches the rest of your code, and it catches many mistakes. It does not make text safe for every place it goes later. A comment that passes your length check can still contain < and '. Those characters are fine in a comment and become dangerous only when the text is placed into HTML or SQL. That is the job of escaping and parameterised queries, which later lessons cover. Validate on the way in and make text safe on the way out, at the place where it is used.
const qty = Number(req.body.qty);
if (!Number.isInteger(qty) || qty < 1 || qty > 5) {
return res.status(400).send('Please choose between 1 and 5.');
}Are cookies and headers trusted?
They come from the browser, so no. A cookie feels like something your server owns, because your server set it. The visitor's browser stores it, though, and the visitor can read and change it under Application, then Cookies, in developer tools. A cookie that says role=admin or discount=20 is an invitation to edit it.
A login cookie is safe to accept only because it holds a long random id that the server looks up in its own records. Guessing another member's id is impractical, and editing your own gives you nothing. The meaning lives on the server. The same goes for headers: Referer and User-Agent are whatever the sender chose to write. The Origin header is more reliable, since browsers set it themselves and pages cannot change it, which is why a later lesson uses it against forged requests. A tool outside a browser can still write any Origin it likes.
Where are the other boundaries?
Data also crosses boundaries on the way out. When the server puts text into a page, it crosses into HTML, where < has a meaning. When it puts text into a query, it crosses into SQL, where ' has a meaning. When it builds a shell command or a file path, a different set of characters gets special powers. Each crossing needs its own treatment, and the same text may be harmless in one place and dangerous in another.
Other services are boundaries too. Data from a payment provider's webhook should be checked against the provider's signature before you mark an order paid. Packages you install run with your server's full power. An AI tool's suggestion is text from outside. Draw the line around what you wrote and checked, and treat everything else as untrusted until you have looked at it.
How much does the lab simplify here?
The tamper attack looks for one pattern: an order or booking route that reads req.body.price, total, amount or cost. A real review looks wider. Prices can arrive under other names such as unitPrice, discounts can be applied twice, a quantity of -3 can turn a charge into a refund, and an id for an item on another customer's order can expose their details. The lab's rule teaches the habit; your own reading has to apply it to every field.
The fixed route in the lab also skips a check a real one needs: if db.get finds no item with that id, item is undefined and the line after it throws an error. A real handler would answer with a 400 status and a short message when the item is missing.
What do AI tools get wrong about trust?
Assistants often build checkout forms that send the price, the total or a discount from the browser, because the browser already has those values on screen. They also tend to add validation only in the browser, with HTML attributes or a React form library, and describe the result as validated. Read any generated route and list every value it takes from req. For each one, ask whether the server could have known it already, and whether anything on the server checks it.
Watch for the advice to "sanitise all input" with no detail. It suggests one function can make text safe for every purpose, which is never true. Ask what the value will be used for, then use the specific tool for that place: escaping for HTML, placeholders for SQL, a fixed list of allowed values for choices.
Field notes
- A trust boundary is the line where data from outside reaches your server.
- Anything in
req.body,req.query, cookies or headers could have been typed by anyone. - Checks in the browser help honest visitors and do nothing to stop an attacker.
- The server should look up prices itself and check every number it receives.
Easy to get wrong
The browser's copy of the price can be edited. The server's copy cannot, so use that.
Browser checks are skipped by anyone who edits the page or sends the request with a tool. Only server checks are rules.
Visitors can edit their cookies. Keep any fact that grants power on the server.
Text that passes a length or format check can still contain characters that mean something in HTML or SQL.
Questions people ask
Is a hidden form field secret?
No. It is hidden from the page layout only. It is in the HTML the visitor received, and they can see and change it in developer tools.
Can I trust data from my own JavaScript?
Once it is sent to the server, it arrives as a request like any other. Your script runs in the visitor's browser, and they can change it or send the request without it.
What about data from my own database?
You stored it, but a visitor may have typed it originally. A comment saved last week is still visitor text when you show it today, so it still needs escaping.
Is it fine to send the price for display?
Yes. Showing the price is normal. The rule is only that the server ignores any price the browser sends back and uses its own.