After the last lesson the Hacker added protection that removes ../ from the file name, but it removes it once in a single pass and does not re-check the result.
The same document server, but the developer added protection that strips the literal climb sequence once. A single-pass strip is defeated by writing the segment nested so it returns intact after the removal.
You bypassed the ../ removal with a nested string and read /etc/passwd.
Why the solution worked
The protection removed ../ once, and a one-time removal leaves a hole: text nested inside itself, ....//, comes back as ../ after the removal, and even repeated removal is bypassed with encoding. The right rule: do not clean the input; resolve the final path and check it is inside the allowed folder after resolution, and take only the file name.
The root cause
A single-pass strip of a literal segment leaves a hole: a nested segment returns intact after the removal, and the root is the missing final-path check.
How the code is fixed
Cleaning is a blacklist, bypassed by nesting or encoding. Judge the path after resolution, not the text before it.
Vulnerable code
const name = req.query.name.replace(/\.\.\//g, ''); // one pass, "....//" -> "../"
res.send(fs.readFileSync('/var/www/docs/' + name, 'utf8'));
Safe code
const full = path.resolve('/var/www/docs', path.basename(req.query.name));
if (!full.startsWith('/var/www/docs/')) return res.status(400).end();
res.send(fs.readFileSync(full, 'utf8'));
Impact in the real world
Strip filters for climb segments are broken by nesting or encoding, and reading system files stays possible.
How defenders detect it
Defenders resolve the path first then check it is inside the base, instead of stripping text patterns, and alert on repeated climb attempts.