Skip to main content
Injection vulnerabilities occur when untrusted user input is interpreted as code or query logic rather than data. They range from cross-site scripting (XSS) that executes JavaScript in victims’ browsers to database injection that exposes your entire data store.

user-input-not-filtered

High

What it is

Input fields do not sanitize or escape user-provided data before rendering it back to the page, making the application vulnerable to Cross-Site Scripting (XSS) attacks.

Why it matters

XSS allows attackers to inject arbitrary JavaScript into your application’s pages. This can be used to:
  • Steal session cookies (even without HttpOnly bypass via stored XSS)
  • Redirect users to phishing sites
  • Silently exfiltrate form data (keylogging)
  • Deface the application
  • Attack other users who view the infected page

How QAOS detects it

The agent identifies input fields that reflect user content (search boxes, comment forms, profile fields, URL parameters rendered on page) and submits XSS test payloads. It observes whether the payload is executed, rendered unescaped, or stored and displayed to other visitors. Test payloads used:
<script>alert(1)</script>
"><img src=x onerror=alert(1)>
javascript:alert(1)

How to fix

Never trust user input. Apply output encoding appropriate to the context:
// Encode HTML entities (prevent HTML injection)
const encoded = input
  .replace(/&/g, '&amp;')
  .replace(/</g, '&lt;')
  .replace(/>/g, '&gt;')
  .replace(/"/g, '&quot;')

// Use a library like DOMPurify for rich HTML content
import DOMPurify from 'dompurify'
element.innerHTML = DOMPurify.sanitize(userContent)
Use a Content Security Policy (CSP) as a defense-in-depth measure:
Content-Security-Policy: default-src 'self'; script-src 'self'

hostile-data-used-in-query

High

What it is

User-controlled input is used directly in query construction without parameterization, allowing attackers to alter query logic and extract unauthorized records.

Why it matters

A single injectable search field can expose your entire database. SQL injection payloads like ' OR 1=1 -- bypass WHERE clauses. NoSQL injection payloads like {"$ne": null} return all records. This is consistently the #1 cause of large-scale data breaches.

How QAOS detects it

The agent identifies search, filter, and query fields, then submits injection payloads and observes response changes:
Normal: /users?search=alice     → returns 1 user
Attack: /users?search=' OR 1=1--  → returns all users

How to fix

Always use parameterized queries. Never concatenate user input into query strings:
# WRONG — vulnerable to injection
query = f"SELECT * FROM users WHERE name = '{user_input}'"

# CORRECT — parameterized query
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
// MongoDB — avoid direct operator injection
const users = await User.find({ name: req.query.name })  // potentially unsafe
// Use validation + allow-list of operators

untrusted-data-concatenation-dynamic-query

High

What it is

Dynamic queries are built by concatenating multiple untrusted input values, allowing injected fragments like &showAll=true, &fields=password, or ?filter[$gt]=0 to alter query behavior and expose unauthorized data.

Why it matters

Even when individual inputs are partially sanitized, combining multiple user-controlled values into a single query expression creates injection opportunities. Mass assignment vulnerabilities in ORMs fall into this category.

How QAOS detects it

The agent tests filter-based pages by injecting extra query parameters like showAll=true, fields=password,ssn,salary, or filter[$ne]=null to probe whether the application blindly passes these to the data layer.

How to fix

Use an explicit allow-list of accepted parameters and operators. Never pass raw query fragments from user input directly to an ORM or query builder:
// Define allowed filter fields explicitly
const ALLOWED_FILTERS = ['name', 'status', 'createdAt']
const safeFilter = {}
for (const key of ALLOWED_FILTERS) {
  if (req.query[key]) safeFilter[key] = req.query[key]
}
const results = await Model.find(safeFilter)

orm-parameter-extraction-in-url

High

What it is

URL parameters are passed directly to an ORM query without validation, allowing injection of MongoDB-style operators ([$ne], [$gt], [$regex]), SQL fragments, or mass assignment parameters that expose additional records or hidden fields.

Why it matters

ORM injection via URL parameters is particularly common in Node.js applications using Mongoose or Sequelize, where req.query is passed directly to Model.find(). This can bypass all access control and expose every record in the collection.

How QAOS detects it

The agent appends injection suffixes to URL parameters on pages with data listings:
/users?id[$ne]=invalid        → MongoDB: matches all users where id ≠ "invalid"
/products?name[$regex]=.*     → MongoDB: matches all products
/orders?showAll=true          → mass assignment bypass
/users?fields=name,email,ssn  → field injection

How to fix

Sanitize query parameters before passing them to your ORM. Reject any input that contains $ operators or array syntax:
const mongoSanitize = require('express-mongo-sanitize')
app.use(mongoSanitize())  // strips $ from all inputs

// Or manually validate
if (typeof req.query.id !== 'string') throw new Error('Invalid parameter')

orm-parameter-extraction-in-form

High

What it is

The same ORM injection vulnerability as above, but exploited through form submissions (POST body parameters) rather than URL query strings.

Why it matters

POST body parameters often receive less scrutiny than URL parameters, especially in frameworks that use body parsers that automatically convert name[$ne]=x form notation into nested objects { name: { $ne: 'x' } }.

How QAOS detects it

The agent submits forms with modified body parameters containing ORM injection payloads and observes whether the response includes data it should not have access to.

How to fix

Apply the same sanitization to POST body parameters as to query strings. Use express-mongo-sanitize or equivalent for your framework, and validate all inputs against explicit schemas using tools like Zod, Joi, or Pydantic.