Project final - Secure comments
Finalize the comments app with XSS-safe rendering and CSP enforcement.
Final integration
In the final lesson we'll combine all parts and finish the app. The form handler reads the comment, adds it safely with renderComment, then clears the input.
We start the app with an initApp function: it focuses the input and makes it ready.
Now our app has three layers of protection: textContent, escapeHtml and CSP.
What we built
At the end of five lessons we've built a secure comments app:
- Capturing comments with a form submit listener
- XSS-safe rendering with
textContent - An extra encoding layer with
escapeHtml - A CSP meta tag to restrict scripts
- Input clearing and startup with
initApp
The app is now ready for production use.
Exercise Finish the app
Add the line commentInput.value = ""; to the submit handler (after the renderComment call) so the input clears after each comment. Then define an initApp function that calls commentForm.querySelector("#commentText").focus() inside. Finally call initApp() to start the app.
Show example solution
commentForm.addEventListener("submit", (event) => {
event.preventDefault();
const commentInput = commentForm.querySelector("#commentText");
const text = commentInput.value;
renderComment(text);
commentInput.value = "";
});
function initApp() {
commentForm.querySelector("#commentText").focus();
}
initApp();
Test yourself
-
Three layers of protection
textContent + escapeHtml + CSP- Only CSP is enough
- Only escapeHtml is enough
- textContent + escapeHtml + CSP together
- innerHTML + CSP is enough
Show answer
textContent + escapeHtml + CSP together — Correct! Defense in depth: textContent + escapeHtml + CSP.
-
Call initApp
function initApp() { commentForm.querySelector("#commentText").focus(); } ____Show answer
function initApp() { commentForm.querySelector("#commentText").focus(); } initApp(); -
Match threats to defenses
- XSS
- Prevented with textContent
- Inline script
- Blocked by CSP
- HTML injection
- Encoded with escapeHtml
- Page reload
- Stopped with preventDefault