Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
🛡️ Days 23–27 – Professional JavaScript  ·  Day 26

Day 26: Security & Clean Code

⏱ 95 min📶 Pro🎯 100% self-study
Day 26 / 30

✅ Today you will learn

  • XSS: how attackers inject scripts – and how to stop them
  • Safe rendering: textContent, escaping, sanitising
  • CSP, HTTPS, cookies and third-party scripts
  • Secrets and “never trust the client” (prices, discounts)
  • Clean code: naming, small functions, comments, consistency

🏢 In the real world

A real pattern from small Indian e-commerce sites: the product review box rendered reviews with innerHTML. Someone posted a “review” containing a script that copied every visitor’s session token. Another site calculated the discount in JavaScript – a customer changed the price in DevTools and paid ₹1 for a gift box. Both are front-end mistakes you will never make after today.

XSS: the number one front-end vulnerability

HTML + JavaScript
<p>A customer review (imagine it came from the database):</p>
<div id="unsafe" style="border:2px solid #dc2626;padding:8px;border-radius:8px"></div>
<div id="safe" style="border:2px solid #16a34a;padding:8px;border-radius:8px;margin-top:8px"></div>
<p id="alarm" style="color:#b91c1c;font-weight:700"></p>

<script>
const review = 'Tasty! <img src="x" onerror="document.querySelector(\'#alarm\').textContent=\'⚠️ Attacker code ran – it could have stolen your login!\'">';

document.querySelector('#unsafe').innerHTML = '❌ innerHTML: ' + review;       // executes the attacker’s code
document.querySelector('#safe').textContent = '✅ textContent: ' + review;     // shown as harmless text
</script>
▶  innerHTML runs injected code; textContent shows it as text
Sink (dangerous)Safe alternative
el.innerHTML = userTextel.textContent = userText
Template literal HTML with user datacreateElement + textContent, or escape() every value
insertAdjacentHTML / document.writeappend() nodes you created
href = userUrl (javascript: URLs!)Allow only http(s): new URL(u).protocol check
eval(), new Function(), setTimeout("string")Never with user data – use functions and JSON.parse
Rich text (HTML editor content)Sanitise with DOMPurify before inserting

Escaping when you must build HTML strings

JavaScript
function escapeHTML(value) {
  return String(value)
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#39;');
}
// a tagged template that escapes every ${value} automatically
function html(strings, ...values) {
  return strings.reduce((out, str, i) => out + str + (i < values.length ? escapeHTML(values[i]) : ''), '');
}

const review = { name: 'Rahul <script>steal()</script>', text: 'Best "ghewar" ever & fresh' };
console.log(html`<li><b>${review.name}</b>: ${review.text}</li>`);

function safeLink(url) {
  try {
    const u = new URL(url, 'https://sharmasweets.in');
    return ['http:', 'https:'].includes(u.protocol) ? u.href : '#';
  } catch { return '#'; }
}
console.log(safeLink('https://maps.google.com/?q=Johari+Bazaar'), safeLink('javascript:alert(1)'));
<li><b>Rahul &lt;script&gt;steal()&lt;/script&gt;</b>: Best &quot;ghewar&quot; ever &amp; fresh</li> https://maps.google.com/?q=Johari+Bazaar #

Never trust the client

Done in the browser only ❌

  • Price and discount sent from JS: { total: 1 }
  • Coupon validity checked only in JS
  • Stock checked only in JS
  • “isAdmin: true” flag in localStorage

Correct design ✅

  • Send only product ids and quantities
  • Server looks up prices, applies coupons, checks stock
  • Server calculates the total the customer pays
  • Permissions checked on every server request
🧠 Our practice API follows this rule

On Day 20 the POST body contained only { id, qty } – the API looked up prices itself, refused sold-out items and calculated delivery. Front-end validation is for user experience; the server is for truth.

Secrets, keys and tokens

ItemCan it be in front-end JS?Why
Payment gateway SECRET key❌ NeverAnyone can read your JS (View Source, DevTools)
Database password❌ NeverLives only on the server
Payment PUBLIC/key-id (Razorpay key_id)✅ YesDesigned to be public; secret stays on server
Google Maps browser key✅ With restrictionsRestrict by domain (HTTP referrer) in the console
Login sessionPrefer HttpOnly cookieJS cannot read it, so XSS cannot steal it
.env filesOnly VITE_ prefixed values reach the browserTreat them as public

Defence in depth: CSP, HTTPS and third-party scripts

HTTP header – Content Security Policy (set on the server, e.g. .htaccess)
Content-Security-Policy: default-src 'self';
  script-src 'self' https://checkout.razorpay.com;
  img-src 'self' data: https:;
  style-src 'self' https://fonts.googleapis.com;
  font-src https://fonts.gstatic.com;
  connect-src 'self' https://codingeasily.in;
  frame-ancestors 'none'

# Even if an attacker injects <script>, the browser refuses scripts not on the list.
  • Serve everything over HTTPS; set cookies with Secure, HttpOnly and SameSite=Lax/Strict.
  • Every third-party script (chat widgets, analytics, ad tags) can read your page – add only trusted ones, pin versions and use Subresource Integrity (integrity="sha384-…") for CDN files.
  • Keep npm packages updated: npm audit lists known vulnerabilities.
  • Use rel="noopener noreferrer" on links opened with target="_blank" to untrusted sites.

Clean code: write for the next developer

Before

  • function calc(a, b, c) { if (c) { return a*b - a*b*0.1 + (a*b > 1500 ? 0 : 60) } else { return a*b + (a*b>1500?0:60) } }
  • Magic numbers 0.1, 1500, 60
  • Name says nothing
  • Duplicated logic

After

  • const COUPON_RATE = 0.10, FREE_DELIVERY_FROM = 1500, DELIVERY_FEE = 60;
  • const subtotal = price * qty;
  • const discounted = hasCoupon ? subtotal * (1 - COUPON_RATE) : subtotal;
  • return discounted + (discounted >= FREE_DELIVERY_FROM ? 0 : DELIVERY_FEE);
HabitExample
Names reveal intentisDeliveryFree, getProductsByCategory, MAX_CART_ITEMS
Functions do one thingvalidateOrder(), calculateTotal(), renderCart() – not doEverything()
Early returns / guard clausesif (!cart.length) return showEmpty();
No magic numbersconst GST_RATE = 0.05
Comments explain why, not what// Courier refuses milk sweets – they spoil in transit
Consistent stylePrettier + ESLint on save (Day 21)
Small commits with clear messages“Fix: delivery fee shown on free orders”

🏅 Job skills unlocked today

✔ Recognise and prevent XSS with safe rendering✔ Validate and calculate prices on the server, not the client✔ Keep secrets out of front-end code; use CSP, HTTPS and safe cookies✔ Write clean, reviewable JavaScript

Practice tasks

🏋️ Practice – do it yourself

Task 1: Rewrite this unsafe render safely with createElement/textContent: list.innerHTML += `<li>${comment.author}: ${comment.text}</li>`.
Show solution
▶  Result
Task 2: Refactor a 40-line “doEverything” checkout function from your own code into validate, calculate and render functions with named constants.
Task 3: Run npm audit on a Vite project and read what each warning means before fixing it.

Quick quiz

🧠 Quick Quiz – test yourself

1. Safest way to display a user comment?
No HTML parsing.
2. Where must the final order total be calculated?
Clients can be modified.
3. Can a payment gateway secret key be in front-end JS?
Everything in JS is public.
4. CSP mainly helps by…
Defence in depth against XSS.
5. A good comment explains…
Code shows what.

Interview corner

💼 Interview Corner

What is XSS and how do you prevent it?

Cross-site scripting: attacker-controlled data is rendered as HTML/JS and runs in other users’ browsers. Prevent by treating data as text (textContent, framework escaping), escaping in HTML/attribute/URL contexts, sanitising rich HTML (DOMPurify), validating URLs, avoiding eval, using CSP and HttpOnly cookies.

Why should business rules not live only in the front end?

The client is fully under the user’s control – code, requests and storage can be changed. Prices, discounts, stock, permissions and payments must be enforced on the server; the front end mirrors them only for a fast, friendly experience.

Summary

  • Render user data with textContent or escaping; sanitise rich HTML.
  • Never trust the client: prices, stock, permissions on the server.
  • No secrets in front-end code; HTTPS, CSP, HttpOnly cookies, careful third parties.
  • Clean code: clear names, small functions, constants, why-comments, consistent style.
➡️ Next

Day 27: testing and interview preparation – write automated tests and practise the most asked JavaScript questions.

Frequently Asked Questions

Does React protect me from XSS?
React escapes values in JSX by default, which prevents most XSS. dangerouslySetInnerHTML, href with user URLs and third-party HTML still need care.
Is minifying or obfuscating code a security measure?
No – it only makes code harder to read. Anything shipped to the browser should be considered public.
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicDay 27: Testing & Interview Preparation Your progress: 26 / 30 (87%) · Lesson 27 / 30 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free