White-Label · OEM · Sublicensed Redistribution · Attribution

Several partners are shipping near-identical copies of your code. When one leaks, which one was it?

Every other distribution model on this site is answered mainly by raising the cost of reading delivered code. This one is not. Under a white-label or OEM agreement your product is deliberately stripped of your branding, handed to a partner, and often hosted by them — and the same build goes out to several partners at once. The question that defines the model is attribution, and a build that is merely hard to read provides none of it. That has to be designed in.

The Short Version

Identity beats difficulty here

Three decisions, and the first one is the one teams get wrong.

Different is not identifiedPer-licensee seeds give you builds that differ, with nothing you can read back out of a recovered file.
The tag is unforgeable, not hiddenThe scanner prints a tag without the key; the key is what stops a partner relabelling a copy.
A domain lock fits the partner badlyThe hostnames are theirs, they change, and the failure path throws rather than skipping.
What This Model Actually Is

Your code, someone else's name on it, running somewhere you do not control

White-label and OEM arrangements cover a wide range of commercial shapes, but they share a set of engineering properties that no other distribution model on this site combines. Recognising which of them apply to your agreement is most of the work of choosing controls, because they pull in different directions and some of the usual advice inverts.

The branding is removed on purpose

Your name is not in the interface and often not in the file. Attribution by inspection — a distinctive namespace, a visible product string, a console banner — is exactly what the agreement asks you to remove, so the informal signals other models rely on are gone by design.

The partner frequently hosts the files

Where a widget is usually loaded from your origin, a white-label build is commonly handed over as artefacts and served by the partner. You lose delivery-time telemetry, you lose the ability to revoke by unpublishing, and you lose any control over caching lifetime.

Several near-identical copies exist at once

This is the property that changes everything. When many partners run builds that differ only in configuration, a recovered file is consistent with all of them. Nothing about the transformation narrows it down, because the transformation was applied the same way to each.

The partner is a legitimate holder

Unlike most threat models here, the party with the code is supposed to have it. The realistic risks are onward leakage, retention after termination, and scope creep beyond the licensed use — none of which a runtime guard is well shaped to address.

Support flows backwards through them

When something breaks, an end user reports it to the partner, who reports it to you, often without the build identifier. Anything that makes a file self-identifying pays for itself in support long before it is ever needed for a leak.

Termination is a real event

Agreements end, and code already delivered does not come back. Planning for the model means deciding in advance what you can demonstrate about a copy still in circulation after the relationship is over, because that is when the question is most likely to be asked.

The Mistake Worth Naming First

Different builds are not identified builds

The intuitive move is to give every licensee its own build with its own entropy, on the reasoning that unique output means a unique fingerprint. The first half is true and the second does not follow, and the gap between them only becomes visible at the moment you actually need the answer.

What a seed is for

Determinism. With a seed recorded, the same input, the same options and the same seed regenerate byte-identical output; omit it and each build differs from the last. That is exactly the property you want for reproducibility and release evidence, and it is a genuinely valuable thing to have.

Why it does not attribute

To match a recovered file to a licensee you would have to regenerate every licensee's build from the correct era, with the exact inputs, options and toolchain of that era, and compare. That is a reconstruction exercise done under time pressure, and it decays as dependencies move.

What identity actually requires

Something you can read directly out of the artefact in front of you, without reconstructing anything. A tag embedded in the file, scanned for and reported. The difference is between deriving an answer and looking one up, and only one of those works at 2am.

Use both, for different jobs

Record the seed so the build is reproducible and your release evidence holds. Embed a per-licensee tag so a recovered file names its own distribution. They are not alternatives and neither one substitutes for the other.

How Attribution Works Here

A tag you can read, a signature you cannot fake

The mechanism is deliberately simple, and understanding its two halves separately is what stops teams from expecting the wrong thing. One half is a label. The other half is a signature over that label. They fail in different ways and it is worth knowing which is which before you build a process on top.

The tag is embedded per file

Enabling the watermark embeds an HMAC-SHA256 watermark into every protected file in the build, carrying a tag you choose — in this model, the licensee identifier. It rides with the artefact wherever the artefact goes.

Scanning reads it back

The scanner walks a directory tree and lists every JavaScript file carrying a watermark. Point it at a folder of recovered artefacts, a partner's deployed bundle, or your own release directory, and it reports what it finds.

The key is what makes it evidence

Supplied with the key, the scan validates the HMAC rather than merely reporting a string. Without the key it prints the tag only. So the tag is legible to anyone who looks; the signature is what distinguishes a genuine tag from a typed one.

What a missing tag tells you

That someone removed it, which is itself informative. Absence is not attribution, but a partner's deployed bundle scanning clean when it should carry a tag is a finding worth raising while it is still a commercial conversation.

What it does not do

It does not stop copying, and it does not make a file harder to reuse. Attribution is an after-the-fact capability. Anyone selling it as prevention is describing a different product than the one you have.

Keep the mapping properly

The tag-to-licensee mapping is the weakest link in most implementations because it lives in someone's head or a spreadsheet. Store it with the release record, retain it past the life of the agreement, and treat the key with the care you would give any signing key.

The Header Comment Constraint

Your attribution tag and your license notices share one region

This is the practical detail that surprises teams during their first watermarked build, and the tool is deliberately loud about it rather than resolving it quietly. It matters more in this model than most, because a white-label build is exactly the kind that carries third-party notices you are contractually obliged to preserve.

The watermark requires header preservation

Turning the watermark on force-enables header comment preservation. Asking for the watermark while explicitly turning that preservation off is rejected rather than silently reconciled, so the conflict surfaces at build time instead of as a missing tag three months later.

Only the leading run survives

The preserved region is the run of comments at the very top of the file, collected across consecutive comment blocks and stopping at the first real statement. It is not "the first comment" and it is not every comment in the file.

Bundler banners will not survive as emitted

Per-dependency notices scattered through a bundle sit after the first statement, so they fall outside the preserved region. Aggregate every notice you are obliged to carry into one block above all code, as part of the bundle step rather than after it.

Check the built artefact, not the intent

Open a released file and look at the top. The tag and the notices should both be there. This is a thirty-second check that belongs in your release routine, because both of the things it verifies are contractual rather than cosmetic.

Runtime Guards In This Model

Where the usual advice inverts

Runtime defenses are attractive here because the code is leaving your control entirely, and that instinct leads to switching on more than the model can support. The partner's environment is not yours, their users are not your users, and a guard that trips produces a support ticket routed through them.

The domain lock fits badly

It compares the page hostname against a list fixed at build time, and in this model that list belongs to the partner. New environments, previews, staging hosts and acquisitions all become rebuild requests, and a build issued to fix one is a build you now have to track.

Absent signals fail rather than skip

Where there is no usable hostname the guard treats it as a failure, and every failure action except degrade ends by throwing. Anywhere the code runs outside a normal page — a test harness, a server-side render, a build-time smoke check — that is a hard stop.

Pick a survivable failure action

If you use a guard at all, prefer one that degrades or calls back so the partner's users are not handed a blank screen for a condition that is usually a configuration difference rather than an attack.

Console suppression costs you support

Suppressing console output removes the diagnostic channel you will be asking the partner to read from when something breaks two organisations away from you. In a model where debugging is already indirect, that is an expensive setting.

The contract carries what guards cannot

Scope of use, sublicensing, retention on termination and audit rights are contractual instruments. They are the actual controls on a legitimate holder, and technical measures work best as the evidence that supports them rather than as a substitute.

Server-side authority is unchanged

Whatever the partner may do, entitlement and limits belong on a server you run. A white-label agreement changes the branding on the client, not the rule that a decision made only in delivered code is a decision the holder can change.

Frequently Asked Questions

Frequently asked questions

What makes white-label distribution different from shipping a widget or an SDK?

The partner's job is to make your code look like theirs. In a widget or embeddable SDK the origin is usually visible and often deliberately branded, so the questions are about domain scope and tampering. Under a white-label or OEM agreement the branding is stripped by design, the partner may host the files themselves, and several partners run near-identical copies at once. That last property is the one that changes the engineering answer: when a copy turns up somewhere it should not be, reading cost tells you nothing about where it came from. Attribution becomes the primary problem and it needs a deliberate mechanism, because nothing about a well-protected build provides it by accident.

Can we just use a different seed for each licensee?

You can, and it is the most common version of this mistake. A seed controls deterministic entropy: the same input, options and seed produce byte-identical output, and omitting it gives per-build polymorphism. Different seeds per licensee therefore give you builds that look different from each other, which feels like identity but is not. To attribute a recovered file you would need to have kept every licensee's seed, regenerated every licensee's build with the exact inputs and options of the era, and compared. That is an archive and a reconstruction exercise, performed under time pressure, and it degrades the moment a dependency version moves. Seeds are for reproducibility. Identity needs a tag that is read directly out of the file.

Is a watermark tag secret?

No, and designing around the belief that it is will disappoint you. The scanner walks a directory tree and lists every JavaScript file carrying a watermark; supplied with the key it validates the HMAC, and without the key it still prints the tag. So a partner who goes looking can find the tag and remove it. What the key buys is not concealment but unforgeability: producing a valid signature over a different tag requires the key, so a partner cannot relabel their copy as somebody else's. Treat a present, valid tag as strong evidence of origin, a missing tag as evidence that something removed it, and neither as a barrier to copying.

Should we lock each partner's build to their domain?

Usually not as the primary control, and this is where the white-label model diverges most sharply from the widget model. The domain lock compares the page's hostname against a list you compiled at build time. In a white-label arrangement those hostnames belong to the partner: they add them, change them, run staging and preview environments, and acquire other companies. Every one of those events becomes a support ticket that ends with you issuing a rebuild. Worse, the failure path is not benign. If there is no usable hostname the guard treats it as a failure rather than skipping, and every failure action except degrade ends by throwing. Use it where a partner's surface is genuinely fixed, and prefer contractual scope plus attribution everywhere else.

What does the watermark do to our license header?

They share one channel, and the tool enforces it rather than letting you discover it later. Enabling the watermark force-enables header comment preservation, and asking for the watermark while explicitly disabling that preservation is rejected outright rather than silently resolved. The practical consequence is about ordering: the preserved region is the leading run of comments at the very top of the file, collected until the first real statement. A bundler that emits per-dependency banners scattered through the output will not have those banners survive, so aggregate every notice you are obliged to carry into one block above all code, and expect your attribution tag to live in that same region.

What records make an attribution defensible if it ever matters commercially?

Three, kept per licensee and retained past the life of the release. A manifest recording a source hash and an output hash for every file in the build, so a recovered artefact matches a specific build rather than a general belief. A signed release attestation over that manifest, so the record can be verified later by someone who was not there when it was written, with the public key pinned by whoever verifies. And the tag-to-licensee mapping itself, which is the part that is usually held informally and is worthless in that state. None of this prevents a copy from being made. It changes the conversation from an accusation into a demonstration, which is the only realistic goal here.

Related Guides

Where to read next

Widgets and distributed SDKs

The neighbouring model, where the origin is visible and a domain lock genuinely is the primary control rather than a maintenance cost.

Marketplace add-ins

The distribution model with a reviewer between you and your user, and the constraints that reviewer imposes on protection.

Next Step

Decide attribution before the first partner build ships

Retrofitting identity onto a fleet of builds already in the field is the version of this problem nobody wants. Choose a licensee identifier scheme now and embed it as a tag in every partner build. Record the seed and write a manifest so each build is reproducible and matchable. Sign the manifest so the record survives the people who made it. Aggregate your license notices into one leading block so the header region carries both obligations cleanly. Then keep the tag-to-licensee mapping with the release record rather than in someone's memory, because that mapping is the entire mechanism and it is the piece most often lost.