Key idea
Three risks look exactly like working code. Injection: user text gets treated as instructions. Invented packages: a dependency that doesn't exist, or isn't what it seems. Licences: code you don't have the rights to ship. None of them fails a test unless you write one for it.
Injection: keep data apart from instructions
Injection happens when text from a user is pasted into something that runs: a database query, a web page, a spreadsheet formula. You met one in lesson 4.4.2: a task titled =1+1 became a formula in the CSV export.
The same bug in SQL looks like this:
// Unsafe: the title becomes part of the query itself
db.query(`SELECT * FROM tasks WHERE title = '${title}'`);
// Safe: the query has a placeholder; the title travels separately, as data
db.query("SELECT * FROM tasks WHERE title = $1", [title]);
A title like ' OR '1'='1 rewrites the first query to return every row. The second can't be rewritten, because the database never reads the title as SQL.
The rule is the same everywhere: use the tool's way of passing data separately (placeholders for SQL, textContent rather than innerHTML for web pages, escaping for CSV). The starter's page already gets this right: it sets each title with textContent. When an agent builds a string out of user input and hands it to something that runs, stop and ask how the data is kept separate.
Invented packages
Agents sometimes name packages that don't exist, because the name sounds like one that should. They tend to invent the same names again and again, so attackers publish real packages under those names, with harmful code inside. It's called slopsquatting, a cousin of typosquatting: look-alike names one typo from a popular package.
Installing a package runs its install scripts on your machine, and its code ends up in your app. Before any new dependency goes in:
- Ask whether you need it. "No new dependencies" belongs in most briefs.
- Find it yourself. Open its page on the registry (npmjs.com for Node, pypi.org for Python) and check the exact spelling against the library's own documentation.
- Check it's alive and real. A linked source repository, a history of releases, more than one maintainer or a known one, and plenty of downloads.
- Read the diff to
package.jsonand the lockfile. A dependency you didn't ask for is a scope change.
From the terminal, npm view express shows a real package's registry entry: versions, maintainers, homepage. npm view express repository.url prints where its source lives.
Licences
Every dependency comes with a licence that says what you may do with it. npm view express license prints MIT, a permissive one; some licences require you to publish your own source if you ship theirs. Agents don't check this when they add a package; you do.
Generated code can also closely resemble code from public repositories. Read your agent's terms on who owns its output and whether it filters matches with public code. For anything commercial, ask someone qualified before a licence question becomes a launch blocker.
Check yourself