Skip to main content

Worksheet: browser security basics

CVE Lite Classroom · CVE Lite

You will use a supplied message board, watch a harmless demonstration, and repair how messages appear. Allow about 75–90 minutes, including discussion. You need a desktop browser and a plain-text code editor. You do not need a terminal or previous knowledge of browser programming.

Choose the row matching your folder. Keep the same copy open throughout the lesson.

Your folderOpen in your browserOpen in your code editor
Student-only kit (contains app/)app/index.htmlapp/render.js
Full repository, inside this exercise (contains student/)student/index.htmlstudent/render.js

Extract a downloaded ZIP first. Read Safety. Open the submission template to record observations. You only edit render.js; you do not need to read data.js, app.js, or the check code.

1. Send ordinary messages (10 minutes)​

  1. Double-click your index.html, or use the browser's Open File command. The address starts with file://: the page is on your computer.
  2. Click Reset board, then Reader view. You should see two example messages. Reset restores these two examples and removes messages you added.
  3. Click Author view. Click the box labelled Message and type Hello from our class!.
  4. Click Post message, then Reader view. Find your message below the examples. Record what you see.
  5. Click Author view, enter A < B & "quotes", click Post message, then Reader view. Record whether the punctuation appears.
  6. Click Author view, enter only three spaces, and click Post message. Record the feedback: Enter a message before posting. No message should be added.

Author view is where you write; Reader view is where the page displays messages. These are two views in the same tab. There are no accounts or other people receiving your messages. Reloading also restores the two examples.

2. Watch the harmless demonstration (10 minutes)​

  1. Click Reset board. Find Demo marker below the views and record its text: UNCHANGED.
  2. Click Author view, then Insert harmless demo. The button fills the Message box for you. You do not need to type or memorize the long text.
  3. Click Post message, then Reader view. Wait a moment and look at Demo marker again. In the starter it changes to DEMO EXECUTED. Record both values. A broken-image symbol may also appear; the marker text is the evidence to record.
  4. Click Run browser checks and wait until the buttons are available again. Expect 3 of the 6 checks to pass before repair. Record the six results using the table in section 5. The failures are part of the lesson.

The demo changes only this page's marker. Next, learn why a message could do that.

3. Understand text and browser instructions (15 minutes)​

A browser is the program displaying this page. HTML describes page parts, such as paragraphs, buttons, and messages. An HTML element is one such part. For example, <strong>Hello</strong> describes an element whose word Hello is emphasized, usually in bold. The opening and closing pieces are called tags.

JavaScript is the programming language that makes buttons and other page actions work. A string is a piece of text stored by a program, such as a message. The browser keeps a working collection of page elements called the DOM (Document Object Model). Rendering here means putting messages into that collection so you can see them.

Message stringTreated as HTML instructionsTreated as plain text
<strong>Hello</strong>Only Hello appears, emphasizedAll of <strong>Hello</strong> appears, including the tags

Try it: click Author view, type <strong>Hello</strong>, click Post message, then Reader view. In the starter, the tags become an element. This board is supposed to show messages as plain text, so the tags should have stayed visible.

Open your render.js in the editor. Find container.innerHTML. container names the page's message list. Assigning a string to innerHTML tells the browser to read it as HTML instructions. The starter combines messages with <li> tags (list items) using map and join. You do not need to learn those operations for this repair; you will replace the complete file below.

The demo uses the same HTML interpretation. Here are its three pieces:

PieceWhat it tells the browser if read as HTML
<img ...>Create an image element. The alt="Harmless demo" part supplies descriptive text.
src="data:image/png;base64,AA=="Try to load image data included in the message itself. These deliberately invalid bytes cannot make an image. They do not request an image from a website. You do not need to understand or memorize base64.
onerror="document.getElementById('demo-marker').textContent='DEMO EXECUTED'"If the image fails to load, run this JavaScript: find this page's marker and set its text to DEMO EXECUTED.

The browser treated the message as instructions, created an image, and ran the image's error action. We want it to display those characters as a message instead. In your own words, explain the difference between displaying <strong>Hello</strong> as text and interpreting it as HTML. You do not need to explain every symbol in the demo.

4. Make the guided repair (25 minutes)​

We will create the list item ourselves and put the message inside it as text. These are the four browser operations you need. An API is a named operation a program can ask the browser to perform.

OperationJob in this repair
container.replaceChildren()Remove old displayed list items before drawing the list again. It does not delete stored messages.
document.createElement('li')Create one empty list item. document refers to this page; 'li' is the HTML name for a list item.
item.textContent = textPut the complete message in the item as plain text. Even HTML-looking characters stay text. = assigns the value on the right to the place on the left.
container.appendChild(item)Add the new item to the displayed list.

A variable is a name for a value: var item names the new list item. A function is a group of instructions that can be run together. The app calls renderMessages when it needs to display messages. It supplies two values: container (the list on the page) and messages (the collection of message strings).

messages.forEach(function (text) { ... }); runs the instructions inside the braces once for each message, in order. Each time, text names the current message. This gives every message its own item.

window represents the browser window. window.renderMessages = function ... makes this function available to the supplied app. The outer (function () { ... }()); wrapper runs setup once, and 'use strict'; enables stricter JavaScript error checking. Keep those supplied lines exactly as shown; you do not need to design that setup yourself.

  1. In your editor, select all the contents of your render.js and replace them with the entire block below, from the first ( to the final );. Copy only the code, without the surrounding Markdown backticks. The block includes the complete function and its wrapper; do not keep any old braces.
  2. Replace the one ____ in the code with the property that puts a message into an item as plain text. Hint: the operations table shows item.textContent = text. Keep text on the right side of =.
(function () {
'use strict';
window.renderMessages = function (container, messages) {
container.replaceChildren();
messages.forEach(function (text) {
var item = document.createElement('li');
item.____ = text;
container.appendChild(item);
});
};
}());
  1. Save with Ctrl+S (Windows/Linux) or Command+S (Mac). Keep the filename render.js; do not save it as render.js.txt.
  2. Return to the browser tab containing your matching index.html. Reload using Ctrl+R or Command+R, or the reload button. Saving alone does not update the running page. Reload restores the two examples and the UNCHANGED marker.
  3. Click Author view → Insert harmless demo → Post message → Reader view. The full demo text, including <img, should now appear as a message. The marker should stay UNCHANGED.

If messages disappear or buttons stop working, check that the blank is filled, every line was copied, and the correct file was saved. Confirm that browser and editor use the same folder; then reload. Ask your instructor for help if needed. Do not change browser security settings or edit the checks.

Optional independent challenge for practiced JavaScript students: Instead of copying the scaffold, write your own complete renderMessages implementation. Keep all message characters, show messages separately in order, and remove previous displayed items before rendering again. Use the same verification below. The guided repair can earn full credit; this challenge is not required.

5. Check the repair (10–15 minutes)​

  1. Repeat the ordinary message, punctuation message, and spaces-only steps from section 1. Check that messages appear in posting order and the spaces-only feedback is unchanged.
  2. Post <strong>Hello</strong> again. Confirm that you see the angle brackets and tags as text this time.
  3. Record the demo's full-text display and UNCHANGED marker from section 4.
  4. Click Run browser checks. Expect 6 of 6 checks to pass after repair. Record what actually happens, even if it differs from these expectations.
Browser checkExpected starterExpected repaired app
Plain text is displayedPASSPASS
Special characters are preservedFAILPASS
Multiple messages stay separate and in orderPASSPASS
Empty lists clear previous messagesPASSPASS
Markup stays literal textFAILPASS
Message code does not executeFAILPASS

The special-character check includes the exact text &amp;. The starter reads that as HTML and changes it to &, so this check fails even if your earlier punctuation message looked fine. The empty-list check tests a temporary list; Reset board itself restores two example messages. Checks use a separate temporary area and restore the marker to its prior value afterward, so record your manual demo observation before running checks.

  1. Click Reset board, then Reader view. Confirm that only the two examples remain and the marker reads UNCHANGED.

6. Explain and submit (5–10 minutes)​

Finish the submission template and attach your edited render.js. Explain in one or two sentences why a message could change the marker before repair and why the same message is displayed as text afterward. Use innerHTML and textContent if helpful. Include results that did not match expectations so your instructor can help.

Optional extension: vocabulary for later lessons (not graded)​

The unsafe behavior is an example of cross-site scripting (XSS): message content becomes JavaScript instructions in the browser. A trust boundary is a point where outside data is handled by program code; here it is where message strings become displayed elements. OWASP Top 10:2025 groups injection risks, including XSS, under A05 Injection. This lesson covers one example, not that whole category.

A server is a program that answers other programs' requests; a database stores data for later use. This lab uses neither: messages stay in this tab's memory. Stored XSS in a shared application could involve saving a harmful message and displaying it to another person later. This local demo does not show that delivery or a database break-in. A future server lesson can address account permissions, input checks, and safe database queries separately.

CVE Lite checks third-party dependencies for known vulnerabilities. This flaw is in the board's own display code, so dependency scanning does not repair it. The six checks support this plain-text repair; they do not prove every part of an application is secure. Discuss these distinctions only if time and prior experience permit.

Screenshot preview