From harness-claude
Prevents SQL, NoSQL, and command injection by enforcing parameterized queries, input validation, and safe shell execution patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:owasp-injection-preventionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Eliminate SQL, NoSQL, and command injection by never concatenating untrusted input into queries or commands
Eliminate SQL, NoSQL, and command injection by never concatenating untrusted input into queries or commands
Never build queries with string concatenation. Always use parameterized queries or a query builder.
// BAD — direct interpolation
const query = `SELECT * FROM users WHERE id = ${userId}`;
// GOOD — parameterized (node-postgres)
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
// GOOD — TypeORM query builder
const user = await userRepo
.createQueryBuilder('user')
.where('user.id = :id', { id: userId })
.getOne();
// GOOD — Prisma (always parameterized)
const user = await prisma.user.findUnique({ where: { id: userId } });
For raw SQL that must be dynamic (table/column names), use an allowlist — never accept these from user input:
const ALLOWED_SORT_COLUMNS = ['name', 'created_at', 'email'] as const;
type SortColumn = (typeof ALLOWED_SORT_COLUMNS)[number];
function buildSortedQuery(column: SortColumn) {
// column is validated at the type level AND runtime
if (!ALLOWED_SORT_COLUMNS.includes(column)) throw new Error('Invalid column');
return `SELECT * FROM users ORDER BY ${column}`;
}
MongoDB operators like $where, $gt, $regex can be injected through JSON body parsing. Validate and sanitize all operator keys.
// BAD — passes user object directly to find
app.post('/login', async (req, res) => {
const user = await User.findOne({ username: req.body.username, password: req.body.password });
// Attacker sends: { "username": "admin", "password": { "$gt": "" } }
});
// GOOD — extract and validate specific string fields
app.post('/login', async (req, res) => {
const username = String(req.body.username ?? '');
const password = String(req.body.password ?? '');
const user = await User.findOne({ username, password });
});
// GOOD — use express-mongo-sanitize middleware to strip $ keys
import mongoSanitize from 'express-mongo-sanitize';
app.use(mongoSanitize());
Never pass user input to exec, execSync, or shell: true spawns.
import { execFile, spawn } from 'child_process';
import { promisify } from 'util';
const execFileAsync = promisify(execFile);
// BAD
exec(`convert ${userFilename} output.png`);
// GOOD — execFile does NOT invoke a shell; args are passed directly
await execFileAsync('convert', [userFilename, 'output.png']);
// GOOD — spawn with shell: false (default)
const proc = spawn('convert', [userFilename, 'output.png']);
Validate all external input at system boundaries before it reaches any query or command:
import { z } from 'zod';
const SearchSchema = z.object({
query: z
.string()
.max(100)
.regex(/^[\w\s]+$/),
page: z.number().int().min(1).max(1000),
sortBy: z.enum(['name', 'date', 'score']),
});
app.get('/search', async (req, res) => {
const params = SearchSchema.parse(req.query); // throws ZodError on invalid input
const results = await db.search(params.query, params.page, params.sortBy);
res.json(results);
});
OWASP consistently ranks injection as a top-3 vulnerability. The root cause is always the same: user-controlled data is interpreted as code or a query operator rather than data.
Defense layers:
Common bypasses to watch for:
%27 → ', -- URL-encoded as %2D%2DORMs do NOT automatically protect you if you use raw query escape hatches (Prisma.$queryRaw without template literals, TypeORM query(), etc.).
// STILL vulnerable with Prisma if you concatenate
const bad = await prisma.$queryRaw(`SELECT * FROM users WHERE id = ${id}`);
// SAFE — template literal version uses parameterization automatically
const good = await prisma.$queryRaw`SELECT * FROM users WHERE id = ${id}`;
https://owasp.org/www-project-top-ten/
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudePrevents SQL injection by enforcing parameterized queries and ORM usage over string concatenation. Useful when constructing database queries from user input, API params, or external data.
Refuses SQL, NoSQL, LDAP, and XPath queries that concatenate user input. Suggests parameterized replacements for PostgreSQL, MySQL, Prisma, SQLAlchemy, and more.
Detects SQL, command, and template injection caused by user input reaching an interpreter without parameterization. Checks concatenated query strings, shell commands, eval/exec calls, and unsafe template usage.