The short answer
Most of the code in your app was written by someone else, and some of it sends your users' data to another company the moment a page loads. Before launch, make a list of every script, font, SDK, vendor and package your app uses, and write down what data each one receives. Then sign the data contracts your vendors offer, check that each package's license lets you ship it the way you plan to, and turn on a scanner that warns you about known bad packages.
Why this matters
These are real cases. Each one has a source you can open.
- A font cost a website owner in Germany. On 20 January 2022, the Regional Court of Munich (case 3 O 17493/20) ruled against a site that loaded Google Fonts from Google's servers, because that sent each visitor's IP address to Google without consent. The court ordered the site to stop, set a penalty of up to 250,000 EUR for each future violation, and awarded the visitor 100 EUR in damages. It said the site had no good reason, because the fonts can be used without a connection to Google (Bavarian court database). This is one first-instance German court. It does not bind other courts, and it is not US law. A wave of warning letters to site owners followed, and a German trade press report says the same court later held automated, crawler-based letters to be an abuse of rights (Der Betrieb, trade press).
- A worm in npm. npm is the main registry of JavaScript packages, the place your agent installs code from. In September 2025, a self-copying worm called Shai-Hulud stole GitHub tokens and cloud keys from developers, posted them publicly, then used each victim's npm account to publish infected versions of that person's other packages. The US cyber agency CISA says it "compromised over 500 packages" (CISA alert, GitHub).
- The second wave was bigger. In November 2025, Wiz, a company that sells security tools, reported a second wave of the same attack, with stolen secrets in more than 25,000 repositories. Other researchers give different counts, depending on method and date (Wiz).
- AI tools invent package names. Researchers tested 16 AI models on 576,000 code samples. On average, at least 5.2% of the packages suggested by commercial models and 21.7% of those suggested by open-source models did not exist. They counted 205,474 unique made-up names. An attacker can register one of those names and wait for an agent to install it. This is a preprint, so it may not be peer reviewed yet (arXiv 2406.10279).
- Supply chains are now a top-10 web risk. The 2025 OWASP Top 10, the standard list of web app security risks, added a new entry at number three: Software Supply Chain Failures (OWASP Top 10:2025).
You do not need to stop using other people's code. You need to know what you load, who receives what, and what each license asks of you.
Core concepts
Every script you load is a data flow
A third party is any company other than you and your user. A third-party script is code your page loads from another company's server, such as an analytics tag, a chat widget or a font file. An SDK (software development kit) is a library from a vendor that you build into your app, such as a payments, crash-report or analytics library.
When a browser fetches a file from another server, it sends that server the visitor's IP address, which is the network address of their device. It may also send the page address and cookies. That is how the Munich court reached its ruling: the font itself was harmless, but the request sent the IP address to Google.
Worked example. Your landing page has this line in its head, because your agent added it for a nicer font:
<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet">Every visitor's browser now contacts Google before it shows your page. The cheap fix is to download the font files once, put them in your own project, and load them from your own server:
@font-face {
font-family: "Inter";
src: url("/fonts/inter.woff2") format("woff2");
}Same font, no outside request.
When I checked my own site, Ducktate, on 2026-10-09, the homepage fonts were self-hosted. But the account page still loaded Google Fonts, added on 2026-08-28. An earlier quick check had marked fonts as clear. The same audit found a Google Analytics tag, added on 2026-09-14 to 77 pages, that was not on my public list of vendors. Both are still open as of 2026-10-09. The lesson: check every page, not one, and check again after each change.
Processors, DPAs and your subprocessor list
Europe's privacy law, the GDPR, uses two roles. The controller is the business that decides why and how personal data is used. That is you. A processor is a company that handles personal data on your behalf, such as your database host, payment provider, email sender or analytics tool. Stage 3 explains when the GDPR applies to an app outside the EU.
GDPR Article 28 says processing by a processor must be governed by a contract. That contract is usually called a data processing agreement (DPA). The article also says a processor may not bring in another processor (a subprocessor) without your prior specific or general written authorisation. If you gave general authorisation, the processor must tell you about changes so you can object (GDPR Art. 28, copy of the official text). The link is gdpr-info.eu, a copy of the law; the official text is on EUR-Lex.
That is why most vendors publish a DPA you can sign or accept online, plus a list of their own subprocessors. Many founders also publish their own subprocessor list. That public list is common practice. Article 28 itself only requires the authorisation and the change notice, not a public page.
Worked example. A simple notes app might have this vendor table. Write yours the same way:
| Vendor | What it does | Personal data it receives | DPA signed? | On your public list? |
|---|---|---|---|---|
| Supabase | Database and login | Emails, notes, IP addresses | Yes | Yes |
| Stripe | Payments | Name, email, card details | Yes | Yes |
| Email sender | Sends receipts | Emails | No | No |
| Analytics tool | Counts visits | IP address, pages viewed | No | No |
| Font host | Serves the font | IP address | Not needed after self-hosting | Removed |
Every "No" is a task. The analytics row also leads to Stage 4, because some tracking needs consent first.
Open-source licenses: what you owe
Your agent installs packages written by strangers. Each one comes with an open-source license, the legal terms that say what you may do with the code. You agree to those terms by using the code. Three licenses cover most of what you will see.
The MIT license lets you use, copy, change and sell the code. Its one condition: "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software." The code comes "AS IS", with no promise that it works (MIT license). In practice: keep the license notices that ship with your packages.
The GPL is a "copyleft" license, which means changed versions must stay under the same terms. The Free Software Foundation, which wrote it, says "The GPL does not require you to release your modified version" if you only use it privately. "But if you release the modified version to the public in some way, the GPL requires you to make the modified source code available to the program's users, under the GPL" (GPL FAQ).
The AGPL closes a gap that matters for web apps. Under section 13, if you modify the program, your modified version must offer all users who interact with it "remotely through a computer network" the source code (AGPL v3 text). Running it on your server for users counts.
| License | You may ship it in a closed app? | What you owe |
|---|---|---|
| MIT | Yes | Keep the copyright and license notice |
| GPL | Only if you are ready to comply | Source of your changed version, to the people you release it to |
| AGPL | Only if you are ready to comply | Source of your changed version, to every user who uses it over the network |
Worked example. Your agent adds an AGPL charting library to your web app and changes two files in it to fix a bug. Your users see the charts through the browser. Under section 13, those users are entitled to the source of your changed version. If you do not want that, replace the library before launch. The safe rule: keep GPL and AGPL packages out of your product unless you have decided to comply.
Supply-chain attacks and how to scan
A dependency is a package your app needs to run. Each one has its own dependencies, so a small app can pull in hundreds. A supply-chain attack poisons one of those packages, so that every app that installs the next version runs the attacker's code.
Shai-Hulud shows how it works. CISA's advice after the attack: review your dependencies, check your lockfiles, pin packages to versions from before 2025-09-16, and rotate developer credentials (CISA alert). A lockfile (such as package-lock.json) records the exact version of every package your app installed. Pinning means you install that exact version, not "the newest one". To rotate a credential means to replace it with a new one at the provider so the old one stops working.
Three free tools warn you about known bad versions:
npm auditchecks your project against a list of known vulnerabilities. The--audit-leveloption sets which severity makes the command fail, which is useful in an automated build (npm docs).- Dependabot alerts on GitHub tell you when a package you use has a known problem (GitHub docs).
- OSV-Scanner checks your dependency list against the open OSV.dev vulnerability database, from your terminal or your build (OSV-Scanner).
Worked example. Add one line to the script that builds your app:
npm audit --audit-level=highIf any installed package has a known high or critical problem, the build stops and tells you which one. A scanner only knows about problems that someone has already reported. It will not catch a package name your agent made up an hour ago. For that, read the list of new packages in every change your agent makes, and check that each one is the real package you meant.
Key terms
The checklist
The prompt for your agent
Copy this into Claude Code, Codex or Cursor from the root of your project. It asks for evidence, not reassurance.
Audit this project for Stage 2 of a launch checklist: third parties and dependencies.
Do not change any code, config, package, or lockfile until I approve a plan.
For each item below, report PASS, FAIL, or UNKNOWN, with the file and line that
proves it. If you cannot prove an item from the code, report UNKNOWN. Never report
PASS without evidence.
1. List every external script, stylesheet, font, iframe, and image host that any
page or screen loads (search every HTML file, layout, template, and component,
not only the home page). For each: the host, the file and line, and what data
it can receive (IP address, page address, cookies, form content).
2. List every SDK and vendor service the app calls from server or client code
(database, auth, payments, email, analytics, error reporting, AI APIs). For
each: the file and line, and which personal data it is sent.
3. Is any font loaded from fonts.googleapis.com, fonts.gstatic.com, or another
outside host? If so, which pages?
4. Is there a vendor or subprocessor list in the repo or on the site? Compare it
with items 1 and 2 and list every vendor that is missing from it.
5. List every direct dependency with its license. Flag any GPL, AGPL, or unknown
license, and say whether the code was modified.
6. Is a lockfile committed? Are versions pinned, or do any use open ranges?
7. Does any build or CI step run npm audit, OSV-Scanner, or a similar scanner,
and does a high-severity finding stop the build? Is Dependabot configured?
8. For every package added in the last 30 days of git history, confirm it
exists in the public registry and is the package the code expects. Flag any
name that looks like a typo of a popular package.
End with a table: item, status, evidence (file and line), and the smallest fix you
suggest. Then stop and wait for my approval.When the report comes back, open two of the PASS lines yourself. For item 1, load your site in a browser with the developer tools open on the Network tab, and compare the hosts you see with the agent's list.
Common mistakes
- Checking only the home page for outside scripts and fonts. Settings, account and checkout pages are often built later, by a different prompt.
- Accepting an analytics or chat snippet from your agent without writing down which company receives what.
- Treating "it is free and open source" as "there are no conditions". MIT asks you to keep a notice. AGPL can ask you to share your changed source with every user.
- Clicking "accept" on a vendor's terms but never signing or saving its DPA.
- Installing whatever package name the agent suggests without checking that it exists and is the real one.
- Deleting the lockfile to "fix" an install error, which lets every package jump to its newest version.
- Writing the vendor list once at launch and never updating it.
Check yourself
1. Your page loads a font from Google's servers. What does Google receive, even though the font file is harmless?
Why: Any request to another server sends the visitor's IP address. The Munich court found that sending it to Google without consent was the problem, not the font itself.
2. Under GDPR Article 28, what must exist between you and a company that processes personal data for you?
Why: Article 28 requires a contract between the controller and each processor. A public subprocessor list is common practice, but the contract is the requirement.
3. Your agent adds an AGPL library to your web app and modifies it. Users reach it through the browser. What do you owe?
Why: AGPL section 13 covers remote network interaction. Running modified code for users on your server triggers the source offer.
4. Which step would most likely have stopped your app from automatically picking up an infected new version of a package?
Why: Pinned versions in a committed lockfile install the exact version you tested. CISA advised checking lockfiles and pinning to versions from before the attack.
5. npm audit reports no problems. Your agent added a new package an hour ago. What is still unchecked?
Why: Scanners match known reports. A made-up or newly registered package name has no reports yet, so you must check it yourself.
6. You add a new analytics tool after launch. What else needs to change?
Why: Each new vendor that receives personal data needs to be on your list, and under the GDPR it needs a contract.
Resources
- GDPR Art. 28: Processor (copy of the official text)LawFree
The contract and subprocessor rules behind every vendor DPA.
- Munich Regional Court, 3 O 17493/20 (Google Fonts)LawFree
The official database entry for the Google Fonts ruling, in German.
- MIT LicenseDocsFree
The full MIT text: short, and the one condition is clear.
- GNU GPL FAQGuidanceFree
When the GPL does and does not require you to publish your changes.
- GNU AGPL v3DocsFree
Read section 13 if any package in your web app uses this license.
- CISA: npm supply chain compromiseGuidanceFree
What Shai-Hulud did and the steps CISA advises.
- GitHub: our plan for a more secure npm supply chainArticleFree
GitHub's account of the attack and what it changed.
- Wiz: Shai-Hulud 2.0ResearchFree
The second wave, from a security vendor that tracked it.
- Package hallucination study (arXiv 2406.10279)ResearchFree
The study that measured how often AI models invent package names.
- npm auditDocsFree
How to scan a project and fail a build on a severity level.
- OSV-ScannerToolFree
A free scanner that checks your dependencies against the OSV.dev database.
- GitHub: About Dependabot alertsDocsFree
How GitHub warns you about vulnerable packages you use.
- OWASP Top 10:2025GuidanceFree
The current list of top web risks, with Software Supply Chain Failures at number three.
Next stage
You now know who receives your users' data. Stage 3 turns that list into the paperwork: a privacy policy that says what your app really does, terms people actually agree to, and the rules that app stores, Google sign-in and Stripe check.
Worked through the checklist and passed the quiz? Mark the stage done. Your progress stays in this browser only.
Talk to Claude instead of typing to it.
Ducktate turns what you say into clean text, on your Mac, and pastes it anywhere.
Get early access