1.Why you need to verify AI-written code
An AI coding assistant writes convincing code in seconds. The syntax is clean and the explanation sounds confident. But the AI produces "code shaped like what it has often seen"; it does not actually run it on your data in your situation before answering. So you can get code that is right for common inputs but wrong for empty or boundary values, or code that runs but is dangerous.
You are the one who runs the code and uses its results. If a sales total is wrong and a bad report goes out, or code containing a password becomes public, "the AI wrote it that way" is no excuse. Checking the results and taking responsibility falls to the person and organization that used the code. Everything you learned up to Lesson 9 — values, conditions, loops, functions, arrays and strings — is a tool for exactly this verification. If you can read short code yourself, you can use AI far more safely and effectively.
Verification has four main strands: reading the code to understand what it does, checking results with tests you wrote yourself, reviewing security risks, and checking issues outside the code such as licenses and personal data. This lesson practices them one by one in that order.
- Reading: what does this function take, and what does it return?
- Testing: do common inputs, empty values, 0 and boundary values give the expected result?
- Security: are there secrets, unvalidated input,
evalor unfamiliar packages? - Outside the code: were license terms, company or school policy, and personal data handled properly?
2.Reading line by line — input, process, output
When you read code an AI gave you, do not just skim it from top to bottom; fit it to the "input → process → output" frame from Lesson 1. Look at the function name and parameters to see what it takes, and find return to see what it gives back. Then go through the middle lines one at a time and say in words what each variable holds once that line has run. Any line where your explanation stalls is the place to check.
Ask "what if" questions as you read. What if the array is empty? What if the values come in as strings? What if they are 0 or negative? The average function below is correct for ordinary scores, but an empty array gives 0 / 0, which is NaN, and string scores taken from a CSV make + join text and produce a nonsense value. It is all the more dangerous because the wrong value comes out with no error message.
If you hit syntax you do not understand, it is fine to ask the AI to "explain what this line does for a beginner." But after hearing the explanation, print intermediate values with console.log as in Lesson 8 and check for yourself that the explanation matches reality. The explanation is also an AI answer, so it needs checking too.
// A function an AI coding assistant wrote (as is)
function averageScore(scores) {
let sum = 0;
for (const s of scores) {
sum += s;
}
return sum / scores.length;
}
console.log(averageScore([80, 90, 100]));
console.log(averageScore([]));
console.log(averageScore(["80", "90"]));90 NaN 4045
3.Writing your own tests — boundary values find bugs
A test means writing down in advance "this input should give this value" and checking it with code. You decide the expected value by hand before looking at the code. If you leave the tests to the AI as well, it may put the same misunderstanding into the tests as into the code, so write at least a few yourself. A small tool like the check function below, which compares the result with the expected value and prints PASS or FAIL, is all you need.
A good set of tests includes edge cases alongside ordinary cases: an empty array or empty string, 0, negative numbers, a single value, the exact value where a condition flips (the boundary values from Lesson 3), numbers with a different number of digits, and repeated values. Bugs usually hide at these edges.
Below is an "AI-written function that picks the top scores." Tested only with two-digit scores, it passes and looks correct. But it goes wrong once a score of 100 is included. Without a compare function, JavaScript's sort() converts values to strings and sorts them in dictionary order, so "100" comes before "80". On top of that, sort changes the order of the original array, so the caller's data is quietly changed too.
function check(name, got, want) {
const same =
JSON.stringify(got) === JSON.stringify(want);
console.log(same ? "PASS" : "FAIL", name, got);
}
// AI-written function: the top n scores
function topScores(scores, n) {
return scores.sort().reverse().slice(0, n);
}
check("two digits", topScores([70, 90, 85], 2), [90, 85]);
check("100 points", topScores([100, 95, 80], 2), [100, 95]);
check("n is 0", topScores([70, 90], 0), []);
const mine = [70, 90, 85];
topScores(mine, 1);
console.log("original", mine);PASS two digits [ 90, 85 ] FAIL 100 points [ 95, 80 ] PASS n is 0 [] original [ 90, 85, 70 ]
(a, b) => b - a to put the biggest numbers first.function topScores(scores, n) {
const copy = [...scores];
copy.sort((a, b) => b - a);
return copy.slice(0, n);
}
const mine = [100, 95, 80];
console.log(topScores(mine, 2));
console.log(topScores([], 3));
console.log("original", mine);[ 100, 95 ] [] original [ 100, 95, 80 ]
// AI-written function (as is)
function shippingFee(price) {
return price > 50000 ? 0 : 3000;
}
for (const p of [49999, 50000, 50001]) {
console.log(p, shippingFee(p));
}49999 3000 50000 3000 50001 0
- Step 1: Find the boundary in the rule. The value where the condition flips is 50,000 won.
- Step 2: Pick just below, at and just above the boundary: 49,999 won → 3,000, 50,000 won → 0, 50,001 won → 0.
- Step 3: Add extreme and odd values: decide first what should happen with 0 won, a negative amount and the string "50000".
- Step 4: When you run it, 50,000 won gives 3,000. Reading the code, it uses
>instead of>=.
> must be changed to >=.4.Security — secrets, input validation, `eval`
The first rule is to never put secrets such as passwords, API keys or access tokens into code or prompts. A key written in code easily leaks through file sharing, a repository made public or a screenshot. Pasting code that contains a key into an AI assistant while asking about an error carries the same risk. Replace the key with a fake value like "YOUR_API_KEY" when you show it, and keep the real key outside the code in the way each service recommends (environment variables, a configuration file, a secrets manager and so on). If a key has already been exposed, deleting it is not enough; revoke it with that service and issue a new one.
The second rule is input validation. Treat values from users, files and other programs as possibly different from what you expect, and check their shape and range before using them. AI-written code often assumes only "normal input." As below, the safe approach is to define the allowed shape first and reject everything else with null. "Accept only good values" misses less than "filter out bad values."
Third, never pass untrusted input to eval or new Function. eval runs a string as code, so commands hidden in the input can run as is. If you asked for a calculator or a settings reader and the AI gave you code that uses eval, ask for another approach. If the goal is to exchange data, read the JSON from Lesson 6 with JSON.parse. JSON.parse only reads data, never runs code, and throws an error if the format is wrong.
^\d+$ means "digits only, from start to end." Anything outside the allowed range is null.// accepts only whole-number ages from 0 to 150
function parseAge(input) {
const s = String(input).trim();
if (!/^\d+$/.test(s)) return null;
const n = Number(s);
if (n > 150) return null;
return n;
}
const tries = ["35", " 7 ", "-3", "2.5", "abc", "", "999"];
for (const x of tries) {
console.log(JSON.stringify(x), "→", parseAge(x));
}"35" → 35 " 7 " → 7 "-3" → null "2.5" → null "abc" → null "" → null "999" → null
JSON.parse does not run a string that looks like code; it rejects it with a SyntaxError. try { … } catch (e) { … } is syntax that keeps going when an error occurs, catching the error in the catch part to handle it.const input = '{"name": "Alex", "score": 90}';
const data = JSON.parse(input);
console.log(data.name, data.score);
try {
JSON.parse("console.log('secretly run')");
} catch (e) {
console.log("Rejected:", e.name);
}Alex 90 Rejected: SyntaxError
5.Nonexistent packages — check before installing
Real-world code often installs and uses packages (libraries) that others have built and published. But AI assistants sometimes make up plausible package names that do not actually exist, or recommend packages that stopped being maintained long ago. The bigger problem is that someone can publish a malicious package in advance under such a frequently invented name, or under a name one letter off from a popular package. If you run the install command without checking, someone else's code runs on your computer.
So before running an install command, check a few things: whether the package really exists in the official package registry, whether the name is spelled exactly as in the official documentation, whether it has been maintained recently, whether it has a public source repository and documentation, and whether it is widely used. Companies and schools may have an approved package list or a security review process, so follow those rules first.
For a small job, also ask whether it can be done without a package. The text cleanup and totals in Lesson 9 needed nothing beyond JavaScript's built-in features. The fewer packages you depend on, the less there is to check and the fewer places things can go wrong. That said, for jobs with tricky rules, such as reading real CSV files or encryption, choosing a well-tested package is safer than writing it yourself.
- Does that name really exist in the official package registry?
- Is the spelling exactly the same as in the official docs? (Watch for fake names one letter off)
- Has it been updated recently, and is it maintained?
- Are its source repository, documentation and license public?
- Did you follow your company's or school's approved list and security procedures?
6.Copyright, licenses and personal data
Being public does not mean code is free to use however you like. Open-source code comes with a license, and a license is a promise: "you may use this if you follow these terms." The terms differ from license to license. A common term is to keep the copyright notice and license text along with the code, and some licenses require that when you distribute a program containing the code, you publish its source code under the same terms. Code with no license at all may not be licensed for use, even if it is publicly visible.
AI-written code may also closely resemble existing public code. Before putting a long piece of code straight into a product, check whether you can trace its origin and whether your company or school has a policy on AI-generated code and open-source use. The table below lists only general features of common types and is not legal advice. Read the license text for the actual terms, and when in doubt, ask the relevant department at your organization or an expert.
Personal data is another important issue outside the code. If you paste a real customer list, student grades or phone numbers while asking an AI for code, that information leaves your control. What you need to build code is the "shape" of the data, not the real values. As below, create fake data to show, and run the real data only on your own computer. For example addresses, use a domain reserved for documentation such as example.com, so nothing ever reaches a real person. When you share results, show only as much as needed, for example by masking the middle digits of phone numbers.
function fakeCustomers(n) {
const list = [];
for (let i = 1; i <= n; i++) {
const no = String(i).padStart(4, "0");
list.push({
id: i,
name: "Customer" + i,
phone: "010-0000-" + no,
email: "user" + i + "@example.com",
});
}
return list;
}
console.log(fakeCustomers(2));[ { id: 1, name: 'Customer1', phone: '010-0000-0001', email: '[email protected]' }, { id: 2, name: 'Customer2', phone: '010-0000-0002', email: '[email protected]' } ]| Type | Examples | Common terms |
|---|---|---|
| Permissive | MIT, BSD | Broadly allows copying, modification and commercial use. Keep the copyright notice and license text with the code |
| Permissive (with patent clause) | Apache-2.0 | Broadly permissive like MIT. Keep a copy of the license and notices, mark changes in modified files, and includes patent-related clauses |
| Copyleft | GPL family | Stronger terms, such as having to provide source code under the same license when you distribute a program that includes the code |
| No license | Public code with no license file | Being public may not mean you have permission to use it. Check before using |
7.Making the review steps a habit
If you build the habit of checking AI-given code in the same order every time, you miss less. First read it to see whether what the code does matches what you asked for, and for any line you do not understand, get an explanation and then confirm with console.log. Next, write tests with expected values you set yourself — two or three ordinary cases and three or four edge cases — and run them.
If a test fails, gather the failing input, the value you got and the expected value, and ask the AI again. As in Lesson 8, "input [100, 95, 80], expected [100, 95], actual [95, 80]" gets fixed much faster than "it's wrong." When you get the fixed code, rerun all the original tests to make sure fixing one place did not break another. Putting the code before and after the fix into a text diff checker shows exactly what changed.
Finally, do the security and outside-the-code checks: no secrets left in the code, input is validated, no eval, unfamiliar packages were checked, and license and personal-data rules were followed. Only code that has been through this process is "code you can take responsibility for." This completes the Coding Basics course. Now that you can read, test and fix short code, keep AI as your assistant and turn your repetitive tasks into code one at a time.
- Purpose: does what the code does match what you asked for?
- Line-by-line reading: input, process, output; confirm unclear lines with
console.log - Tests: set the expected values yourself and always include boundary values
- Rerun: after any fix, run every test from the start
- Security and beyond the code: secrets, input validation,
eval, packages, licenses, personal data
📌 Key points
- AI code can be right for common inputs and wrong at the edges — the person using it must verify it
- Set the expected values yourself first, and test with empty values, 0, boundary values and numbers of different lengths
- Without a compare function,
sort()sorts in string order and changes the original - Keep secrets out of code and prompts, validate input, and never use
evalon untrusted input - Check that packages really exist and are maintained, check license terms and policies, and use fake data instead of personal data
🧪 Code lab
Use tests to find and fix hidden bugs in code that looks AI-written, and build functions for input validation and masking personal data. Look at the failing inputs in the test results first.
Your code runs only inside an isolated sandbox in this browser and is never sent to a server. It has no network access and is stopped after 2 seconds. Edited code is saved only in this browser. Ctrl+Enter (⌘+Enter) runs it; Tab inserts two spaces (press Esc, then Tab, to move on).
JavaScript is off, so the code can't run here, but you can still read each task, its starter code, the automatic checks and a sample solution.
1Fixing the edge case in an average function
The AI-written average(nums) returns NaN for an empty array. Fix it so it returns 0 for an empty array and the average otherwise. The array contains only numbers.
average([80,90,100])expected90average([])expected0average([0,0])expected0average([-10,10,30])expected10average([7])expected7
💡 Hint
At the very start of the function, if nums.length === 0, immediately return 0;.
Show a sample solution
function average(nums) {
if (nums.length === 0) return 0;
let sum = 0;
for (const x of nums) {
sum += x;
}
return sum / nums.length;
}2The sorting bug in a top-scores function
The AI-written topScores(scores, n) should return the top n scores from largest to smallest, but it goes wrong once a 100 is included. Fix it to sort by numeric value, and do not change the original array. If n is larger than the array length, return as many as there are.
topScores([70,90,85], 2)expected[90,85]topScores([100,95,80], 2)expected[100,95]topScores([5,100,20,9], 3)expected[100,20,9]topScores([60,70], 0)expected[]topScores([], 3)expected[]topScores([88], 5)expected[88]
💡 Hint
Copy with [...scores], sort largest first with sort((a, b) => b - a), then slice(0, n).
Show a sample solution
function topScores(scores, n) {
const copy = [...scores];
copy.sort((a, b) => b - a);
return copy.slice(0, n);
}3Validating an order quantity
Complete the function parseQuantity(input). After removing leading and trailing spaces from the string input, return the number if it is a whole number made only of digits between 1 and 99 inclusive; otherwise return null. "2.5", "-1", "1e3" and the empty string all give null.
parseQuantity("3")expected3parseQuantity(" 12 ")expected12parseQuantity("0")expectednullparseQuantity("100")expectednullparseQuantity("2.5")expectednullparseQuantity("1e3")expectednull
💡 Hint
Check for digits only with /^\d+$/.test(s), and return null if n < 1 || n > 99. Also note that Number("") is 0.
Show a sample solution
function parseQuantity(input) {
const s = input.trim();
if (!/^\d+$/.test(s)) return null;
const n = Number(s);
if (n < 1 || n > 99) return null;
return n;
}4Masking the middle of a phone number
Write a function maskPhone(s) that hides personal data when you share results. If s has the 3-4-4 digit shape like 010-1234-5678, return 010-****-5678 with the middle four digits replaced by ****; if it does not have this shape, return null.
maskPhone("010-1234-5678")expected"010-****-5678"maskPhone("010-0000-0001")expected"010-****-0001"maskPhone("01012345678")expectednullmaskPhone("")expectednullmaskPhone("010-12-5678")expectednull
💡 Hint
The regular expression /^\d{3}-\d{4}-\d{4}$/ lets through only "3 digits-4 digits-4 digits." Anything that fails is null.
Show a sample solution
function maskPhone(s) {
if (!/^\d{3}-\d{4}-\d{4}$/.test(s)) return null;
const parts = s.split("-");
return parts[0] + "-****-" + parts[2];
}🤖 Try asking AI like this
Copy a prompt and replace the [ ] parts with your own situation. Don't take the answer on trust — check it against this lesson.
When you want to understand code an AI gave you
Explain the JavaScript code below line by line, as if to a beginner. Using the sample input [sample input], trace what the main variables hold after each line, and point out what happens when an empty value, 0 or a string comes in. [code]
When you want to find every case worth testing
The purpose of the function below is [purpose]. Make a list of inputs to test, grouped into ordinary cases, boundary values, empty values and invalid input. I'll decide the expected values myself, so just write the inputs and why each case matters. [function code]
When you want a security and license review of your code
Review the code below from a security point of view. List any secrets left in the code, unvalidated input, dangerous features like `eval`, and how to check that the packages it uses really exist and are maintained. If any part was taken from open-source code, tell me in general terms which license terms I should check (it doesn't need to be legal advice). I've already replaced keys and personal data in the code with fake values. [code]
🧰 Related tools
Tools for checking and tidying the JSON, regular expressions and text from this lesson. Don't paste real personal data or passwords.
- Text Diff CheckerPut the AI's fixed code side by side with the original and see exactly what changed.
- Regex TesterTest in advance whether an input-validation pattern like
^\d+$correctly separates values to accept from values to reject. - JSON FormatterExpand fake test data, or data to be read with
JSON.parse, neatly to find format errors. - Password GeneratorA tool that generates random passwords. Use strong passwords even for test accounts, but never write them in code or prompts; keep them somewhere safe outside the code, such as a password manager.
- MDN Web Docs — reference pages for Array.prototype.sort, JSON.parse and eval (including the advice to avoid eval)
- OWASP — general guidance on input validation and secrets management
- Open Source Initiative — texts and general explanations of open-source licenses (MIT, Apache-2.0, GPL and others)
Reached every goal above? Mark the lesson complete.
Storage is unavailable in this browser, so this lasts only for this page.💻 Coding Basics
- 1What Is a Program? — Breaking Work into Sequence, Choice, and Repetition
- 2Values, Variables, and Types — Putting Name Tags on Values
- 3Conditionals — Taking Different Paths Depending on the Situation
- 4Loops — Doing the Same Thing Many Times, Exactly
- 5Functions — Splitting Work into Small Named Machines
- 6Arrays and Objects — Storing and Handling Data
- 7Strings and Text — Cutting, Finding and Replacing Characters
- 8Debugging and Reading Errors — Turning Red Text into Clues
- 9Simple Automation — Spreadsheet Math and Text Cleanup in Code
- 10Reading and Verifying AI-Written Code — Tests, Security, Licenses, Privacy