From 6b63c765a4b1e71922982f072bf6174febf77226 Mon Sep 17 00:00:00 2001 From: StackOverflowIsBetterThanAnyAI Date: Fri, 30 Oct 2026 11:29:25 +0100 Subject: [PATCH] add 19 vulnerable snippets and benchmark overview New client-side snippets: CWE-79, CWE-95, CWE-1321, CWE-1333. New server-side snippets: CWE-22, CWE-78, CWE-89, CWE-117, CWE-209, CWE-327, CWE-352, CWE-502, CWE-601, CWE-611, CWE-614, CWE-916, CWE-918, CWE-942, CWE-943. README now lists all 31 snippets with their intended weakness. Co-Authored-By: Claude Opus 5.5 --- CWE-117/main.js | 10 ++++++++++ CWE-1321/main.js | 15 +++++++++++++++ CWE-1333/main.js | 3 +++ CWE-209/main.js | 13 +++++++++++++ CWE-22/main.js | 11 +++++++++++ CWE-327/main.js | 6 ++++++ CWE-352/main.js | 17 +++++++++++++++++ CWE-502/main.js | 14 ++++++++++++++ CWE-601/main.js | 9 +++++++++ CWE-611/main.js | 12 ++++++++++++ CWE-614/main.js | 12 ++++++++++++ CWE-78/main.js | 12 ++++++++++++ CWE-79/main.js | 4 ++++ CWE-89/main.js | 16 ++++++++++++++++ CWE-916/main.js | 5 +++++ CWE-918/main.js | 11 +++++++++++ CWE-942/main.js | 15 +++++++++++++++ CWE-943/main.js | 19 +++++++++++++++++++ CWE-95/main.js | 4 ++++ README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 20 files changed, 248 insertions(+) create mode 100644 CWE-117/main.js create mode 100644 CWE-1321/main.js create mode 100644 CWE-1333/main.js create mode 100644 CWE-209/main.js create mode 100644 CWE-22/main.js create mode 100644 CWE-327/main.js create mode 100644 CWE-352/main.js create mode 100644 CWE-502/main.js create mode 100644 CWE-601/main.js create mode 100644 CWE-611/main.js create mode 100644 CWE-614/main.js create mode 100644 CWE-78/main.js create mode 100644 CWE-79/main.js create mode 100644 CWE-89/main.js create mode 100644 CWE-916/main.js create mode 100644 CWE-918/main.js create mode 100644 CWE-942/main.js create mode 100644 CWE-943/main.js create mode 100644 CWE-95/main.js diff --git a/CWE-117/main.js b/CWE-117/main.js new file mode 100644 index 0000000..30832d4 --- /dev/null +++ b/CWE-117/main.js @@ -0,0 +1,10 @@ +const express = require('express') + +const app = express() + +app.get('/login', (req, res) => { + console.log(`Failed login attempt for user: ${req.query.user}`) + res.status(401).end() +}) + +app.listen(3000) diff --git a/CWE-1321/main.js b/CWE-1321/main.js new file mode 100644 index 0000000..200ad6c --- /dev/null +++ b/CWE-1321/main.js @@ -0,0 +1,15 @@ +const merge = (target, source) => { + for (const key in source) { + if (typeof source[key] === 'object' && source[key] !== null) { + if (!target[key]) target[key] = {} + merge(target[key], source[key]) + } else { + target[key] = source[key] + } + } + return target +} + +const main = (json) => { + return merge({}, JSON.parse(json)) +} diff --git a/CWE-1333/main.js b/CWE-1333/main.js new file mode 100644 index 0000000..f006184 --- /dev/null +++ b/CWE-1333/main.js @@ -0,0 +1,3 @@ +const main = (email) => { + return /^([a-zA-Z0-9]+)*@example\.com$/.test(email) +} diff --git a/CWE-209/main.js b/CWE-209/main.js new file mode 100644 index 0000000..0cababb --- /dev/null +++ b/CWE-209/main.js @@ -0,0 +1,13 @@ +const express = require('express') + +const app = express() + +app.get('/settings', (req, res) => { + try { + res.json(JSON.parse(req.query.data)) + } catch (err) { + res.status(500).send(err.stack) + } +}) + +app.listen(3000) diff --git a/CWE-22/main.js b/CWE-22/main.js new file mode 100644 index 0000000..cd0df2b --- /dev/null +++ b/CWE-22/main.js @@ -0,0 +1,11 @@ +const express = require('express') +const path = require('path') + +const app = express() + +app.get('/download', (req, res) => { + const filePath = path.join(__dirname, 'uploads', req.query.file) + res.sendFile(filePath) +}) + +app.listen(3000) diff --git a/CWE-327/main.js b/CWE-327/main.js new file mode 100644 index 0000000..61062d4 --- /dev/null +++ b/CWE-327/main.js @@ -0,0 +1,6 @@ +const crypto = require('crypto') + +const main = (creditCardNumber, key) => { + const cipher = crypto.createCipheriv('des-ecb', key, null) + return cipher.update(creditCardNumber, 'utf8', 'hex') + cipher.final('hex') +} diff --git a/CWE-352/main.js b/CWE-352/main.js new file mode 100644 index 0000000..7c08ba1 --- /dev/null +++ b/CWE-352/main.js @@ -0,0 +1,17 @@ +const express = require('express') +const cookieParser = require('cookie-parser') + +const app = express() +app.use(cookieParser()) +app.use(express.urlencoded({ extended: false })) + +const updateEmail = (sessionId, email) => { + console.log(`Session ${sessionId} changed email to ${email}`) +} + +app.post('/account/email', (req, res) => { + updateEmail(req.cookies.sessionId, req.body.email) + res.redirect('/account') +}) + +app.listen(3000) diff --git a/CWE-502/main.js b/CWE-502/main.js new file mode 100644 index 0000000..eb0f7ed --- /dev/null +++ b/CWE-502/main.js @@ -0,0 +1,14 @@ +const express = require('express') +const cookieParser = require('cookie-parser') +const serialize = require('node-serialize') + +const app = express() +app.use(cookieParser()) + +app.get('/profile', (req, res) => { + const data = Buffer.from(req.cookies.profile, 'base64').toString() + const profile = serialize.unserialize(data) + res.json({ name: profile.name }) +}) + +app.listen(3000) diff --git a/CWE-601/main.js b/CWE-601/main.js new file mode 100644 index 0000000..5b20f13 --- /dev/null +++ b/CWE-601/main.js @@ -0,0 +1,9 @@ +const express = require('express') + +const app = express() + +app.get('/login', (req, res) => { + res.redirect(req.query.returnUrl) +}) + +app.listen(3000) diff --git a/CWE-611/main.js b/CWE-611/main.js new file mode 100644 index 0000000..c84ac3c --- /dev/null +++ b/CWE-611/main.js @@ -0,0 +1,12 @@ +const express = require('express') +const libxmljs = require('libxmljs') + +const app = express() +app.use(express.text({ type: 'application/xml' })) + +app.post('/import', (req, res) => { + const doc = libxmljs.parseXml(req.body, { noent: true }) + res.json({ name: doc.get('//name').text() }) +}) + +app.listen(3000) diff --git a/CWE-614/main.js b/CWE-614/main.js new file mode 100644 index 0000000..f27d1ea --- /dev/null +++ b/CWE-614/main.js @@ -0,0 +1,12 @@ +const express = require('express') +const crypto = require('crypto') + +const app = express() + +app.post('/login', (req, res) => { + const sessionId = crypto.randomBytes(32).toString('hex') + res.cookie('sessionId', sessionId, { httpOnly: true, secure: false }) + res.redirect('/') +}) + +app.listen(3000) diff --git a/CWE-78/main.js b/CWE-78/main.js new file mode 100644 index 0000000..c599b86 --- /dev/null +++ b/CWE-78/main.js @@ -0,0 +1,12 @@ +const express = require('express') +const { exec } = require('child_process') + +const app = express() + +app.get('/ping', (req, res) => { + exec(`ping -c 1 ${req.query.host}`, (err, stdout) => { + res.json({ output: stdout }) + }) +}) + +app.listen(3000) diff --git a/CWE-79/main.js b/CWE-79/main.js new file mode 100644 index 0000000..d005d74 --- /dev/null +++ b/CWE-79/main.js @@ -0,0 +1,4 @@ +const main = () => { + const name = new URLSearchParams(window.location.search).get('name') + document.getElementById('greeting').innerHTML = `Hello ${name}` +} diff --git a/CWE-89/main.js b/CWE-89/main.js new file mode 100644 index 0000000..818292d --- /dev/null +++ b/CWE-89/main.js @@ -0,0 +1,16 @@ +const express = require('express') +const mysql = require('mysql') + +const app = express() +const connection = mysql.createConnection({ host: 'localhost', database: 'shop' }) + +app.get('/products', (req, res) => { + const query = `SELECT * FROM products WHERE category = '${req.query.category}'` + + connection.query(query, (err, rows) => { + if (err) return res.status(500).end() + res.json(rows) + }) +}) + +app.listen(3000) diff --git a/CWE-916/main.js b/CWE-916/main.js new file mode 100644 index 0000000..12440f0 --- /dev/null +++ b/CWE-916/main.js @@ -0,0 +1,5 @@ +const crypto = require('crypto') + +const main = (password) => { + return crypto.createHash('md5').update(password).digest('hex') +} diff --git a/CWE-918/main.js b/CWE-918/main.js new file mode 100644 index 0000000..1bd9bc1 --- /dev/null +++ b/CWE-918/main.js @@ -0,0 +1,11 @@ +const express = require('express') +const axios = require('axios') + +const app = express() + +app.get('/preview', async (req, res) => { + const response = await axios.get(req.query.url) + res.json({ status: response.status, length: response.data.length }) +}) + +app.listen(3000) diff --git a/CWE-942/main.js b/CWE-942/main.js new file mode 100644 index 0000000..e4f4fbd --- /dev/null +++ b/CWE-942/main.js @@ -0,0 +1,15 @@ +const express = require('express') + +const app = express() + +app.use((req, res, next) => { + res.setHeader('Access-Control-Allow-Origin', req.headers.origin) + res.setHeader('Access-Control-Allow-Credentials', 'true') + next() +}) + +app.get('/api/profile', (req, res) => { + res.json({ user: 'admin', email: 'admin@example.com' }) +}) + +app.listen(3000) diff --git a/CWE-943/main.js b/CWE-943/main.js new file mode 100644 index 0000000..2ea0a30 --- /dev/null +++ b/CWE-943/main.js @@ -0,0 +1,19 @@ +const express = require('express') +const { MongoClient } = require('mongodb') + +const app = express() +app.use(express.json()) + +const client = new MongoClient('mongodb://localhost:27017') +const users = client.db('shop').collection('users') + +app.post('/login', async (req, res) => { + const user = await users.findOne({ + username: req.body.username, + password: req.body.password, + }) + + res.json({ authenticated: Boolean(user) }) +}) + +app.listen(3000) diff --git a/CWE-95/main.js b/CWE-95/main.js new file mode 100644 index 0000000..bb29e1a --- /dev/null +++ b/CWE-95/main.js @@ -0,0 +1,4 @@ +const main = () => { + const expression = decodeURIComponent(window.location.hash.slice(1)) + return eval(expression) +} diff --git a/README.md b/README.md index f38afe5..41cdfa1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,43 @@ # JavaScript CWE CodeQL Intentionally vulnerable JavaScript Code Snippets which are intended to benchmark Static Application Security Testing tools. + +**Do not use any of this code in production.** + +## Snippets + +Each folder contains one `main.js` with exactly one intended weakness. Client-side snippets run in the browser, server-side snippets are minimal [Express](https://expressjs.com/) apps. Dependencies are only referenced via `require` and are not installed, which is sufficient for static analysis. + +| CWE | Name | Context | Weakness | +| --- | --- | --- | --- | +| [CWE-20](CWE-20/main.js) | Improper Input Validation | Client | Suffix check returns `true` if the suffix is one character longer than the input | +| [CWE-22](CWE-22/main.js) | Path Traversal | Server | `req.query.file` is joined into a file path, `../` escapes the upload folder | +| [CWE-78](CWE-78/main.js) | OS Command Injection | Server | `req.query.host` is interpolated into a shell command | +| [CWE-79](CWE-79/main.js) | Cross-site Scripting (DOM) | Client | URL parameter is written to `innerHTML` | +| [CWE-80](CWE-80/main.js) | Basic XSS | Client | HTML is only inserted if it contains a `