VYPR
Critical severityNVD Advisory· Published Feb 4, 2026· Updated Feb 5, 2026

Locutus is vulnerable to Prototype Pollution

CVE-2026-25521

Description

Locutus brings stdlibs of other programming languages to JavaScript for educational purposes. In versions from 2.0.12 to before 2.0.39, a prototype pollution vulnerability exists in locutus. Despite a previous fix that attempted to mitigate prototype pollution by checking whether user input contained a forbidden key, it is still possible to pollute Object.prototype via a crafted input using String.prototype. This issue has been patched in version 2.0.39.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
locutusnpm
>= 2.0.12, < 2.0.392.0.39

Affected products

1

Patches

1
042af9ca7fde

fix: Harden parse_str prototype pollution guard against includes() bypass (#533)

https://github.com/locutusjs/locutusKevin van ZonneveldFeb 2, 2026via ghsa
3 files changed · +52 1
  • CHANGELOG.md+3 0 modified
    @@ -64,6 +64,9 @@ Ideas that will be planned and find their way into a release at one point
     
     Released: TBA. [Diff](https://github.com/locutusjs/locutus/compare/v2.0.38...main).
     
    +### Security
    +- Fix prototype pollution bypass in `parse_str` where overriding `String.prototype.includes` could defeat the guard ([GHSA-rxrv-835q-v5mh](https://github.com/locutusjs/locutus/security/advisories/GHSA-rxrv-835q-v5mh))
    +
     ## v2.0.38
     
     Released: 2026-01-19. [Diff](https://github.com/locutusjs/locutus/compare/v2.0.37...v2.0.38).
    
  • src/php/strings/parse_str.js+1 1 modified
    @@ -74,7 +74,7 @@ module.exports = function parse_str(str, array) {
         key = _fixStr(tmp[0])
         value = tmp.length < 2 ? '' : _fixStr(tmp[1])
     
    -    if (key.includes('__proto__') || key.includes('constructor') || key.includes('prototype')) {
    +    if (/__proto__|constructor|prototype/.test(key)) {
           break
         }
     
    
  • test/custom/parse_str-prototype-pollution.vitest.ts+48 0 added
    @@ -0,0 +1,48 @@
    +/**
    + * Tests that parse_str resists prototype pollution even when
    + * String.prototype.includes has been tampered with.
    + *
    + * See: https://github.com/locutusjs/locutus/issues/...
    + */
    +
    +import { afterEach, describe, expect, it } from 'vitest'
    +// @ts-expect-error - CJS module
    +import parse_str from '../../src/php/strings/parse_str.js'
    +
    +describe('parse_str prototype pollution resistance', () => {
    +  const originalIncludes = String.prototype.includes
    +
    +  afterEach(() => {
    +    // Restore includes so other tests aren't affected
    +    String.prototype.includes = originalIncludes
    +    // Clean up any pollution that occurred
    +    // @ts-expect-error - cleaning up pollution
    +    delete Object.prototype.polluted
    +  })
    +
    +  it('should block __proto__ pollution even when String.prototype.includes is overridden', () => {
    +    String.prototype.includes = () => false
    +    const arr = {} as Record<string, unknown>
    +    parse_str('__proto__[polluted]=yes', arr)
    +    expect(({} as Record<string, unknown>).polluted).toBeUndefined()
    +  })
    +
    +  it('should block constructor.prototype pollution even when String.prototype.includes is overridden', () => {
    +    String.prototype.includes = () => false
    +    const arr = {} as Record<string, unknown>
    +    parse_str('constructor[prototype][polluted]=yes', arr)
    +    expect(({} as Record<string, unknown>).polluted).toBeUndefined()
    +  })
    +
    +  it('should still block __proto__ pollution with native includes intact', () => {
    +    const arr = {} as Record<string, unknown>
    +    parse_str('__proto__[polluted]=yes', arr)
    +    expect(({} as Record<string, unknown>).polluted).toBeUndefined()
    +  })
    +
    +  it('should still block constructor.prototype pollution with native includes intact', () => {
    +    const arr = {} as Record<string, unknown>
    +    parse_str('constructor[prototype][polluted]=yes', arr)
    +    expect(({} as Record<string, unknown>).polluted).toBeUndefined()
    +  })
    +})
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.