The first time I found GPL-licensed code inside a contractor deliverable, it was 2017 and I was CTO of a 40-person payments company. A three-person agency had shipped us a settlement service in Go. The code was clean, well tested, and in one 200-line file it was a near-verbatim copy of a GPLv3 ledger library with the package names changed.
We shipped it anyway. Our statement of work said "original work" and nobody had defined what original meant. Eleven months later, during diligence for a Series B, an investor's technical reviewer found it. That cost us $46,000 in outside counsel and a week of two engineers ripping the file out. Cheaper than the alternative, still entirely avoidable.
I've run this intake review on roughly 30 contractor and vendor codebases since. The framework below is what I use so I don't repeat 2017.
What Does "Original" Actually Mean in a Contractor Deliverable?
Three separate claims get collapsed into the word original, and each one needs a different check.
Claim one: this code is not copied from a public source. That includes GitHub repos, Stack Overflow answers, blog tutorials, published books, and paid course material. This is the claim your contract is really about, and it's the one most teams never verify.
Claim two: this code is not copied from your codebase or another client's. Contractors move between engagements. Some of them reuse infrastructure modules across clients, which is a contract breach more often than it is copyright infringement, but it's still your problem when it surfaces.
Claim three: no model wrote it without disclosure. This is new, it's uncomfortable, and pretending it isn't happening is the fastest way to get surprised in a diligence review.
Notice that none of these three claims are about quality. A contractor can deliver excellent, working, well-tested code that fails all three checks. Plagiarism detection is not code review and it never was.
The Four Questions an Intake Review Has to Answer
1. Does this code exist somewhere else on the web?
MOSS and JPlag compare submissions against each other, plus whatever base corpus you hand them. Neither carries a live web index, so neither will tell you that a function came from a 2019 Stack Overflow answer or a GitHub repo with 4,000 stars. That is a provenance question, not a similarity question, and it needs a plagiarism checker for code that actually indexes the open web.
Practically, the matching unit that survives tampering is the token sequence, not the text. Strip comments, normalize whitespace, then compare 8 to 12 line windows. Renaming variables does not help a contractor, because the token stream stays identical.
def find_duplicates(items):
seen = set()
duplicates = []
for item in items:
if item in seen:
duplicates.append(item)
else:
seen.add(item)
return duplicates
def find_dupes(rows):
viewed = set()
repeats = []
for row in rows:
if row in viewed:
repeats.append(row)
else:
viewed.add(row)
return repeats
Systematic renaming of every identifier, with identical control flow and identical container choices, is the tell. Frankly, that six-line function means nothing on its own. Everyone writes a dedupe loop the same way, and flagging it wastes your afternoon. A 60-line contiguous match where the identifier substitutions are consistent from top to bottom is a different animal entirely.

An honest caveat: web matching catches maybe 70 to 80 percent of what I actually find. The remainder is copied from sources that have been deleted, sit behind a paywall, or live in a private repo. Web provenance raises your hit rate; it doesn't make it 100 percent.
2. Does it match code your own team or another vendor already wrote?
Peer similarity is the check people forget. Two scenarios I've hit more than once: a vendor reused a module from a prior client and shipped it to us, and two vendors on the same engagement independently produced near-identical service layers because both started from the same internal template we'd given them six months earlier.
The mechanic that matters here is comparing the deliverable against a reference corpus, not just against other files inside the deliverable. Some tools let you load your internal repo or a prior vendor's code as the comparison set. You need that, because the interesting matches usually live outside the submission.
Refactoring-resistance is the other half. Moving functions around, extracting helpers, and swapping a list for a generator will beat text diffing. Token-level and AST-level comparison generally survives all of it, because the shape of the logic is still there under the cosmetics.

3. Did a model write it?
Look at this, which is a real pattern I pulled out of a vendor handoff last spring:
def calculate_discount(customer_type: str, order_total: float) -> float:
"""Calculate the discount for a customer based on type and order total.
Args:
customer_type: One of 'standard', 'premium', 'vip'.
order_total: The pre-tax order total in USD.
Returns:
The discount amount in USD.
Raises:
ValueError: If customer_type is not recognized.
"""
if customer_type not in ("standard", "premium", "vip"):
raise ValueError(f"Unknown customer type: {customer_type}")
...
An eleven-line argument validator with a full Google-style docstring and a typed signature. Human contractors write that sometimes. Models write it constantly. The tells I look for:
- Comments that restate the line directly beneath them, in consistent grammatical form
- Defensive validation on every public function, including ones that can't be called wrong
- No dead code, no commented-out experiments, no leftover TODO
- Uniform exception message style across files written by different people
- Naming that is descriptive and slightly formal, never the shorthand a human under deadline reaches for
Detection rests on statistical signals more than pattern matching. Machines pick the most predictable next token, so generated code has lower perplexity than human code and far less burstiness. In human files, a weird helper name or a blunt one-line fix breaks the rhythm. Generated files hold a steady register for hundreds of lines.

Use an AI code detector to prioritize human review, never to make an accusation by itself. We haven't tested this past a few hundred contractor submissions, and I'd be lying if I said the score was decisive on its own. It is good at telling me which files to read carefully first.
4. Is it legal to ship?
This is where plagiarism turns into procurement. A dependency scanner tells you that your package.json pulls in a copyleft library. It does not tell you that your contractor pasted 60 lines out of a GPL repo into a first-party file. That's a similarity problem wearing a license costume.
Run both. ScanCode Toolkit, FOSSA, Snyk, and Black Duck will catch declared dependencies and detected license headers. Your similarity engine catches the copy that has no header at all. If a web match traces cleanly back to a GitHub repository, the repo page tells you the license in about four seconds.
Thresholds You Can Actually Defend
Percentages shift between tools, so calibrate on your own corpus before you write anything into a contract. These are the numbers I start with.
| Signal | Investigate when | Escalate when |
|---|---|---|
| Web/source token match within one file | 30% of the file matches | 70%+, or a contiguous run over 40 lines |
| Peer similarity against reference corpus | 40% match | 85% match on a substantial file |
| AI probability score | Average above 0.6 | Never as a standalone trigger |
| Match to a copyleft repository | Any match | Any match |
The copyleft row is the one people argue with me about. I don't care. A single matched block from a GPL repository in a distributed binary is a legal question, not a similarity percentage, and the answer is a call to counsel rather than a threshold.
What to Do When You Find Something
Boilerplate and idiom matches get ignored. A dedupe loop, a binary search, a standard React form handler: these exist in ten thousand repos and finding a match proves nothing.
A snippet under a permissive license gets attribution. Add the notice, note it in your third-party file, move on. Most MIT and Apache matches are two lines of an answer to a question the contractor would have solved anyway.
Copyleft or a large verbatim block gets withheld milestone payment and a written demand for a rewrite by a named engineer, with a re-scan before the funds move. Say this in the contract before you sign it, not after you find the problem, because a contractor who has already been paid has very little incentive to argue about provenance.
Undisclosed AI generation is a conversation, not a lawsuit. Most of the contractors I work with will simply tell you if you ask before the engagement starts. Put one paragraph in the statement of work: AI-assisted code is fine and must be disclosed, wholesale generation of an entire module needs sign-off, and copied public source must carry attribution. That paragraph prevents more arguments than any tool I've bought.
Where This Breaks Down
False positives cluster in predictable places. Generated protobuf and OpenAPI stubs, config files, anything where two people both used the same library the obvious way. Two contractors who both scaffolded a service with Claude 3.5 Sonnet will look similar to each other, and that's not plagiarism, that's the same tool producing the same idiom.
Cross-language translation is the harder gap. A contractor who ports a Python library to Go function by function will not trigger token matching in most engines, and should still be crediting the original. If the deliverable is a port, ask directly.
A Note on Tooling
MOSS is free, still runs, and I've used it since 2012. JPlag and Dolos are fine for peer comparison in a course or a cohort. None of them carry a web index or an AI detector, which means running this framework with them requires three tools and a spreadsheet, and the spreadsheet is where the process dies. I've watched that happen twice.
Codequiry puts peer comparison, web and GitHub matching, and AI detection in a single report, with token and AST comparison underneath so renaming and reformatting don't get you a clean bill of health. The Codequiry vs MOSS comparison is worth ten minutes if you're currently on MOSS and tired of stitching results together manually. For teams running intake continuously rather than once a quarter, the REST API means the check is a pipeline step on every vendor branch instead of a manual exercise.

Frequently Asked Questions
Does scanning contractor code for originality violate their rights?
Not if you disclose it. Name the practice in the statement of work, keep the scan scoped to the delivered work product, and give them the report if they ask. Contractors who have nothing to hide generally don't object, and the ones who do have told you something useful.
What similarity percentage counts as plagiarism?
There is no universal number, and anyone quoting one is selling something. Contiguous blocks matter more than percentages. A 12 percent match spread across 40 files of standard boilerplate is noise; a 12 percent match concentrated in one 80-line function is a problem.
Can you reliably detect AI-generated code in a contractor deliverable?
Partially. The signals are statistical and they degrade when code is refactored or when a human rewrites the generated output. Treat the score as a triage tool. If a vendor's file scores high and also matches a public source, you don't need a detector to make the case.
How is this different from a normal code review?
A code review asks whether the code works and whether it fits your architecture. This asks where the code came from and whether you're allowed to ship it. Different questions, different tools, and doing one without the other is how you find GPL code during due diligence. If you want to see what the provenance half looks like in practice, the code plagiarism checker runs a peer, web, and AI pass on the same submission set in a few minutes.