Back to the blog
JavaScriptGitHubLicensingOpen Source

Cracked copies on GitHub: what a JavaScript dev can do

October 09, 2026·7 min read·Diego Horvatti

A developer went to Hacker News to say they asked GitHub to remove cracked copies of their software. They waited over a month, and the repositories are still there. Public, with install instructions and all. The post is Tell HN: GitHub refuses to remove cracked copies of my software after a month, and the thread turned into a group venting session for people who sell software. If you have a JavaScript product with a paid version, this case matters to you directly. Cracked copies of your code may be hosted on the biggest code platform in the world, and getting them taken down is harder than it looks.

I'll split this into two parts. First, what you can do when the crack is already live. Then, what to change in your code so the crack does less damage.

What happened, in short

The script is familiar. You launch a paid app. Someone strips out the license check, pushes the result to a public repository and writes a polished README. Sometimes the README is better than yours. The crack shipped before your changelog did.

Then you do what everyone tells you to do: you file a DMCA takedown request. And you wait. According to the author, the wait passed a month and the repositories are still up.

The thread brought the usual two takes. One side thinks GitHub is failing the people who own the code. The other points out that the platform gets a huge volume of requests, many of them abusive, and that taking down repos without checking is a problem too. Both can be true at the same time.

How DMCA works on GitHub (and why it's slow)

GitHub has a formal, public process. Accepted requests are published in the github/dmca repository, with personal data removed. That alone tells you a lot. It's a legal process, not a report button.

A few details trip up a lot of people:

  • Every URL counts. The request has to list the infringing repositories. "User X has several copies" isn't enough.
  • Forks don't go down on their own. If you don't explicitly say that all forks also infringe, and explain why, the takedown may only hit the original repository. With a cracked project, forks multiply fast.
  • Incomplete requests bounce back. Missing the good faith statement, the signature or a clear description of the original work? The request sits there waiting for you to fix it. And often nobody tells you with the urgency you'd like.
  • Counter notices exist. The repo owner can push back. In that case, the content may come back after a few business days unless you go to court.

In other words, the process is slow by design. It assumes the person reporting might be lying. That's frustrating when you're right. But it's the same mechanism that stops a competitor from taking down your repo with a fake claim.

DMCA protects your rights, not your timeline.

What to do when the cracked copy is already live

If you're in this spot right now, here's the practical path:

  1. List everything. Original repository, forks, releases with binaries, gists. Paste the URLs one by one.
  2. Name the forks explicitly. Say the whole project is an unauthorized copy and that every fork inherits the infringement.
  3. Prove authorship. A link to your site, your private repository, the date of your first release, the hash of a file that shows up identical in the copy.
  4. Follow up through support. If a week or two goes by with no reply, open a ticket referencing the original request. Silence usually means "incomplete request," not "request denied."
  5. Go after discovery too. Users almost never find the crack by browsing GitHub. They find it through search engines. Asking for removal from search results usually limits the damage more than taking down a repo that will come back under another name tomorrow.

That last point is the one few people act on. Taking down the copy is mopping the floor. Getting it off Google's first page is turning off the tap.

Why license checks in JavaScript break so easily

Now the part that hurts. If your product is JavaScript running on the client, whether it's an Electron app, a browser extension or a CLI in Node or Bun, whoever has the file has the code. Minifying hides nothing. Obfuscating only slows people down.

The most common check I see out there looks something like this:

const license = localStorage.getItem('license')

if (license === 'PRO') {
  unlockProFeatures()
}

Breaking this takes less time than reading this paragraph. Just open DevTools and set the key. Or swap the if for true in the bundle.

One step up is validating the license with a digital signature. You sign the license on your server with a private key, and the app only checks it with the public key. With Web Crypto you can do this with zero dependencies, in modern browsers, Node and Bun:

const PUBLIC_KEY_B64 = 'MCowBQYDK2VwAyEA...' // your Ed25519 public key

const fromB64 = (s: string) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0))

export async function isValidLicense(payload: string, signatureB64: string) {
  const key = await crypto.subtle.importKey(
    'spki',
    fromB64(PUBLIC_KEY_B64),
    { name: 'Ed25519' },
    false,
    ['verify'],
  )

  return crypto.subtle.verify(
    'Ed25519',
    key,
    fromB64(signatureB64),
    new TextEncoder().encode(payload),
  )
}

This solves a real problem. Nobody can generate fake license keys, because they don't have your private key. The keygen era is over.

But be honest with yourself. Crackers don't need to generate a license. They delete the call to isValidLicense and they're done. The signature protects against forgery, not against code edits.

Where protection actually works

The right question isn't "how do I stop the crack." It's "what can't the crack deliver."

Anything that runs on the user's machine can be copied. What runs on your server can't. So move the value there:

  • Sync and backup across devices.
  • Features that depend on your API, like heavy processing, AI, integrations or exports.
  • Automatic updates. The cracked version stays frozen in time, and every release you ship widens the gap.
  • Support and accounts. Paying users have somewhere to complain. Crackers have a README.

In practice, the client code asks the server for a short-lived token, and the server only issues it if the license is active:

const res = await fetch('https://api.yourapp.com/session', {
  headers: { Authorization: `License ${licenseKey}` },
})

if (!res.ok) return showFreeTier()

const { token } = await res.json() // expires in minutes, used for paid calls

The crack can still unlock the UI. But a UI without the backend is a pretty shell. And that changes the conversation. Instead of protecting the code, you protect the service.

Is it worth fighting GitHub?

It's worth sending the request, and sending it well. It's your right and it's cheap. But I wouldn't bet the business model on it. Even if GitHub acts within a week, the same file shows up on another host, in a Discord, in a torrent.

My opinion, and I know some people disagree: for JavaScript software that runs on the client, the war against cracks was lost at the first npm run build. Most people who download cracks were never going to pay. People who would pay want updates, support and the feeling that the app won't steal their password. A cracked binary from a random repo is, by the way, a great way to install malware. That's worth mentioning on your pricing page, politely.

So the split of effort I suggest is simple. One hour to write a complete DMCA request, with URLs and forks. One afternoon to replace the naive check with a signed license. And the rest of your time building things that only work with your server on the other end.

The Hacker News case is an annoying reminder, but a useful one: no platform will protect your product for you. Architecture does. If you want to see how I think about this balance between client and server in the apps I build, take a look at my projects.

LinkedIn summary

I asked GitHub to take down cracked copies of my software. A month later, they're still up.

That was a dev venting on Hacker News, and it shows an annoying truth: DMCA protects your rights, not your timeline.

If your product is JavaScript running on the client, whoever has the file has the code. Minifying hides nothing and obfuscating only slows people down.

An Ed25519-signed license kills the keygen, but it doesn't stop anyone from deleting the `if`.

The protection that actually works lives in the architecture: sync, API, AI and updates running on your server. The crack unlocks the UI, but without the backend it's just a pretty shell.

I wrote on the blog how to file a DMCA that works and how to move your product's value to the server. If you sell software, it's worth a read.

#JavaScript #SoftwareDevelopment #GitHub #SaaS #CyberSecurity