Skip to content

0xBassia/security-research

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 

Repository files navigation

Security Research

A running list of bugs I've found and reported. Each one was disclosed privately first and only written up here after the maintainer shipped a fix.

Most of what I've reported lately is prototype pollution in small npm packages that turn user input into objects. The rest is a mix: an access-control bug in NocoDB, two unauthenticated file-upload bugs in WordPress plugins (one straight to RCE), and a pair of unauthenticated SSRFs in another plugin. Ten CVEs so far.

Credited advisories CVEs

The list

CVE Where Severity Bug Advisory
CVE-2026-47378 nocodb Medium Hidden columns leak through public shared views GHSA
CVE-2026-46510 form-data-objectizer High (8.2) Prototype pollution GHSA
CVE-2026-46509 @ranfdev/deepobj High (8.2) Prototype pollution GHSA
CVE-2026-45325 @tmlmobilidade/utils High (8.2) Prototype pollution GHSA
CVE-2026-45302 parse-nested-form-data High (8.2) Prototype pollution GHSA
CVE-2026-44483 @rvf/set-get High (8.2) Prototype pollution GHSA
CVE-2026-9815 MagicForm (<= 0.1.3) High Unauthenticated file upload to RCE WPScan
CVE-2026-12516 Fediverse Embeds (< 1.5.8) High (7.5) Unauthenticated SSRF via media proxy WPScan
CVE-2026-12517 Fediverse Embeds (< 1.5.8) Medium (5.3) Unauthenticated SSRF via site-info endpoint WPScan
CVE-2026-9067 Schema & Structured Data for WP & AMP (< 1.60) High Unauthenticated media upload WPScan

Why so many of these are prototype pollution

A surprising number of small libraries take a key path from the user, something like user[name] or a.b.c, and write it straight into an object without ever asking whether that path is trying to reach the prototype. If you can sneak __proto__ into the path, you end up assigning to Object.prototype, and after that every plain object in the process quietly carries your value.

The bug almost always looks like this:

function setPath(obj, path, value) {
  const keys = path.split('.');     // path comes from the request
  let cur = obj;
  for (let i = 0; i < keys.length - 1; i++) {
    cur = cur[keys[i]] ??= {};      // walking "__proto__" lands you on Object.prototype
  }
  cur[keys.at(-1)] = value;         // and now you've written to the prototype
}

setPath({}, '__proto__.polluted', 'yes');
({}).polluted; // 'yes' (a brand new object already has the property)

On its own this rarely does anything dramatic. It gets dangerous when something downstream reads one of those polluted properties: a config flag that was supposed to be undefined and is now true, a missing isAdmin that suddenly answers yes, a template that renders a value it never should have. In all six cases below the vulnerable function could be driven straight from HTTP form data, so there was no login step and nothing unusual to configure. A plain POST was enough to reach it.

The fix is boring and the same every time: reject __proto__, constructor and prototype while walking the path, or build the object with Object.create(null) so there's no prototype to poison.

Notes on each one

CVE-2026-46510: form-data-objectizer (prototype pollution)

The objectizer expanded bracket-notation form keys into nested objects. Feed it a key like field[__proto__][x] and it walked right onto the prototype. Reachable from a normal multipart form submission. CVSS 8.2.

Advisory

CVE-2026-45302: parse-nested-form-data (prototype pollution)

parseFormData() turns bracket and dot notation field names into nested objects. A field name that starts with __proto__, or has .__proto__. somewhere in the middle, walks onto Object.prototype and assigns there. One request pollutes every plain object in the process. CVSS 8.2.

Advisory

CVE-2026-45325: @tmlmobilidade/utils (prototype pollution)

Same class, different sink. The setValueAtPath() helper assigned object-type path segments without filtering reserved keys, so a crafted path reached the prototype. CVSS 8.2.

Advisory

CVE-2026-46509: @ranfdev/deepobj (prototype pollution)

The deep-object helper let dot-notation paths modify prototype attributes. No guard on the reserved keys while traversing. CVSS 8.2.

Advisory

CVE-2026-44483: @rvf/set-get (prototype pollution)

The interesting part here is the reach. The set/get helper itself was vulnerable, and @rvf/core's preprocessFormData wired it directly to form data in apps that used the validation library. So the sink wasn't buried in some utility nobody calls, it sat on the request path. CVSS 8.2.

Advisory

CVE-2026-47378: nocodb (broken access control)

Not prototype pollution this time. Columns a creator had hidden from a public shared view were still being returned by the API behind that view. The UI hid them, the endpoint didn't, so anyone with the share link could read data that was meant to stay hidden. Medium.

Advisory

CVE-2026-9815: MagicForm, <= 0.1.3 (unauthenticated upload to RCE)

The strongest one in this list. MagicForm exposes an unauthenticated AJAX upload action, and when a form leaves a field's extension allowlist empty the plugin stops validating the file type at all. So you can upload a PHP file and run code on the server, no login required. Reported through WPScan and credited to me. High.

WPScan

CVE-2026-12516: Fediverse Embeds, < 1.5.8 (unauthenticated SSRF via media proxy)

The plugin has a media-proxying endpoint that fetches a URL server-side and hands you back the response body, but it never checks where that URL points. No auth needed. So you can aim it at internal services or private-network addresses (cloud metadata, localhost admin panels, anything the server can reach) and read the response. Full-read SSRF, effectively an open proxy too. CVSS 7.5.

WPScan

CVE-2026-12517: Fediverse Embeds, < 1.5.8 (unauthenticated SSRF via site-info endpoint)

Same plugin, second sink. The site-info endpoint fetches a remote page server-side and returns the parsed metadata. The gating nonce is printed on any public page that carries an embed, so it isn't really a barrier, and again the destination isn't validated. You get back parsed page metadata rather than the raw body, so it leaks a bit less than the media proxy, hence the lower score. CVSS 5.3.

WPScan

CVE-2026-9067: Schema & Structured Data for WP & AMP, < 1.60 (unauthenticated upload)

A WordPress plugin one. An upload path was missing both the authentication check and proper file-type validation, which let an unauthenticated visitor drop arbitrary media onto the server. Reported through WPScan / Automattic rather than GitHub, which is why it doesn't show up under my GitHub advisory credits. High.

WPScan

A note on disclosure

Everything here went through the project's private reporting channel first (GitHub Security Advisories, or WPScan for the WordPress ones) and stayed quiet until a patch was out. I'm not publishing working exploits, just the root cause and enough detail to understand the class.

If you maintain a package and want another set of eyes on it, turn on private vulnerability reporting and send me a note at 0xbassia@gmail.com. Happy to help.

About

Vulnerability disclosures and root-cause analysis. 10 published CVEs across npm and WordPress: prototype pollution, broken access control, unauthenticated upload to RCE, and SSRF.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors