JavaScript is designed as an open scripting language. It is not intended to replace proper security measures, and should never be used in place of proper encryption.

JavaScript has its own security model, but this is not designed to protect the Web site owner or the data passed between the browser and the server. The security model is designed to protect the user from malicious Web sites, and as a result, it enforces strict limits on what the page author is allowed to do. They may have control over their own page inside the browser, but that is where their abilities end.

  • It can't read or write files on the visitor's machine — the only thing it can persist locally is a cookie
  • It can talk to other frames from the same origin, but not across origins (postMessage later relaxed this, but that's outside the scope of this piece)
  • It can't populate a file input's value or upload files without the user's direct action
  • It can't read browsing history, only navigate forward/back through it, and can't see other open tabs
  • It can't touch another site's cookies or variables
  • It can't observe activity in other programs or other parts of the browser chrome
  • It can't open off-screen or invisible windows, and generally can't close windows it didn't open

Most people asking about "JavaScript security" really want one of two things: a password-gated page, or some way to send encrypted data to and from a visitor. Neither is something JavaScript can genuinely provide. If someone can intercept what you're sending over the wire, they can also rewrite it — so a password box on an unencrypted page can be silently swapped for one that ships the password straight to an attacker instead. That's exactly the problem TLS exists to solve, and no amount of client-side scripting closes that gap. This piece covers what JavaScript can and can't do here, for the record.

Protecting the Source of Your Scripts

Short answer: you can't, and it isn't worth trying. JavaScript ships as plain text to every visitor, so "view source" or a look through the browser cache will always reveal it. Disabling right-click context menus or stripping browser chrome via window.open doesn't hold up either — several browsers never supported blocking right-click in the first place, and anyone can disable scripting entirely or just view an earlier page's source to find the protected one. Referrer checks are trivially bypassed with a tool like curl that can forge headers, cookies, and form fields. Even obfuscation — renaming variables to gibberish, stripping whitespace, padding in dead code — just slows down someone determined enough to read it, it doesn't stop them.

Password Protecting a File

Doing this properly means a server-side check over an encrypted connection. But since this is a JavaScript piece — here's the naive approach and why it falls short. Say you want to gate a page behind a password field and only let the visitor through if it matches:

JavaScript gate.js
if( document.forms[0].elements[0].value == 'mypassword' ) {
  location.href = 'protectedpage.html';
}

As covered above, the source is never actually hidden, so the password sitting right there in the script is trivial to find. A slightly different approach: name the protected file after the password itself, put an index page alongside it, and redirect based on whatever the visitor types:

HTML index.html
<form action="" onsubmit="location.href = this.elements[0].value + '.html'; return false;">
<input type="text">
<input type="submit" value="Submit">
</form>

This is security through obscurity, nothing more — the page name still travels over the wire in plain text, and packet-level snooping (illegal in plenty of places, which doesn't stop it happening) would expose it instantly. A more involved option is to encrypt the page content with the password as a key, prompt for the key client-side with window.prompt, and only render the decrypted result with document.write if it comes out readable. That at least keeps the password and content off the wire in plain text, though it's still crackable by brute force given enough attempts — better passwords and stronger ciphers raise the cost, but don't make it impossible.

Encrypting Data Before It's Sent

Client-side-only encryption runs into the same key-distribution problem every time: the visitor needs a key you both know, and getting that key to them without exposing it over the same channel you're trying to protect is the whole difficulty. Public-key schemes like Diffie-Hellman or RSA sidestep that, but need to handle numbers far larger than JavaScript's native number type comfortably supports — there are big-number emulation libraries that make RSA-in-JavaScript technically possible, at the cost of real complexity. Even then, without something equivalent to an SSL certificate, there's no way for the visitor to verify they're actually talking to you rather than a third party sitting in the middle. For anything that actually matters, real TLS is still the answer.

Protecting Your Email Address

This is one area where JavaScript genuinely helps. Search engines crawl pages by following links; spam harvesters do the same thing looking for anything that resembles an email address, whether it's in a mailto: link or just sitting in plain text. Posting an address anywhere public is often enough to start the flood, and replying to "unsubscribe" spam usually just confirms the address is live. A few standard mitigations help before JavaScript even enters the picture:

  • Use a disposable address for newsgroups, guestbooks, and public pages — burn it and get a new one once the spam piles up
  • Turn off read-receipts in your mail client so replying doesn't confirm the address is active
  • Be careful with auto-responders, for the same reason
  • Munge the address (e.g. name@REMOVE_THISdomain.com) — imperfect, since not every reader figures out what to strip, but it slows harvesters down
  • Or, generate the address with JavaScript instead of writing it as plain text

Using JavaScript to Write Your Email Address

Harvesters generally read rendered text, not script logic, so an address assembled at runtime rather than written directly into the page tends to slip past them — provided it isn't reassembled as one obvious literal string. Splitting it into parts is enough:

JavaScript email.js
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( 'My email address is ' + theName + '@' + theDomain );

Or write it out as a clickable mailto: link:

JavaScript email-link.js
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<a href="mailto:' + theName + '@' + theDomain + '">Contact me</a>' );

Or combine both, so the visible link text is the address itself:

JavaScript email-link-visible.js
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<a href="mailto:' + theName + '@' + theDomain + '">' + theName + '@' + theDomain + '</a>' );

The obvious catch: this only works for visitors with JavaScript enabled, and some of the people most likely to want to reach you are exactly the ones who browse with it off. A <noscript> fallback with a manually munged address covers that case without exposing a clean address to harvesters:

HTML email-with-fallback.html
<script type="text/javascript">
var theName = 'myEmailName', theDomain = 'myEmailDomain.com';
document.write( '<p><a href="mailto:' + theName + '@' + theDomain + '">' + theName + '@' + theDomain + '</a></p>' );
</script>
<noscript>
  <p><a href="mailto:myEmailName(replace with @ symbol)myEmailDomain.com">
  myEmailName(replace with @ symbol)myEmailDomain.com</a></p>
</noscript>

Key Takeaways

  • JavaScript's security model protects the visitor from the page, not the other way around
  • Source code, passwords, and page names embedded client-side are never actually hidden — only obscured
  • Anything that needs real security — password gates, encrypted data — belongs on the server, over TLS
  • Email obfuscation is the one place JavaScript earns its keep here, and even then a noscript fallback is worth including