Is the treatment of __proto__ different in the fetch API compared to manual assignment?

When using fetch to retrieve a payload containing a __proto__, it seems that the Object prototype is not affected in the same way as when directly assigning to an object.

This behavior is beneficial as it ensures that the Object prototype remains unaffected by any API calls. However, I am curious about the mechanics behind this and why it happens?

For instance, considering a payload.json file:

{
  "__proto__": { "toString": "foobar" }
}

If we fetch this data:

 fetch("payload.json")
      .then(function(response) {
        return response.json();
      })
      .then(function(json) {
        console.log("--JSON from a fetch payload--");
        console.log("payload.toString():", json.toString()); // [object Object]
        console.log("json.__proto__:", json.__proto__); // {toString: "foobar"}
        console.log("{}.toString()", {}.toString()); //[object Object]

        console.log("--New object with __proto__ set--");
        const x = { __proto__: { toString: () => "hacked" } };
        console.log("x.toString(): ", x.toString());
        console.log("{}.toString(): ", {}.toString());
        console.log(
          "JSON.parse('{}').toString(): ",
          JSON.parse("{}").toString()
        );

        console.log("--Set proto with assignment--");
        const y = {};
        y.__proto__.toString = () => "polluted";
        console.log("y.toString(): ", y.toString());
        console.log("x.toString(): ", x.toString());
        console.log("{}.toString(): ", {}.toString());
        console.log(
          "JSON.parse('{}').toString(): ",
          JSON.parse("{}").toString()
        );
      });

The output will be:

--JSON from a fetch payload-- 
payload.toString(): [object Object] 
json.__proto__: 
Object {toString: "foobar"}
{}.toString() [object Object] 
--New object with __proto__ set-- 
x.toString():  *** hacked *** 
{}.toString():  [object Object] 
JSON.parse('{}').toString():  [object Object] 
--Set proto with assignment-- 
y.toString():  *** polluted *** 
x.toString():  *** hacked *** 
{}.toString():  *** polluted *** 
JSON.parse('{}').toString():  *** polluted *** 

I understand how the last example pollutes the object prototype, but I'm intrigued as to why json.__proto__ behaves differently when obtained through a fetch call.

You can view the above example on codesandbox.io

Answer №1

It's important to note that the behavior of fetch API is not related to this issue.

The property __proto__ is a special getter/setter on the Object.prototype, converting operations like [[Get]] and [[Set]] to [[GetPrototypeOf]] and [[SetPrototypeOf]].

When fetching and parsing data as JSON, it operates similarly to JSON.parse: parsing the JSON and creating an empty JavaScript object with the properties added.

However, instead of simply setting the properties using [[Set]], they are defined using [[Define]], which means they won't trigger the setter, resulting in a standard property named __proto__ pointing to a different object than its [[Prototype]]:

Consider the example below:

// Using [[Set]], as initially thought
const obj1 = {}
obj1.__proto__ = {}
console.log(obj1.hasOwnProperty('__proto__')) // false, because it's inherited
console.log(obj1.__proto__ === Object.getPrototypeOf(obj1)) // true

// Using [[Define]], similar to JSON.parse
const obj2 = {}
Object.defineProperty(obj2, '__proto__', {
  value: {},
  enumerable: true,
  configurable: true,
  writable: true
})
console.log(obj2.hasOwnProperty('__proto__')) // true, it is own property
console.log(obj.__proto__ === Object.getPrototypeOf(obj)) // false

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The source 'http://localhost:3000' is not authorized to access the Twitter API

I am working on a web application that utilizes the Twitter API REST. On one of my pages, I have a list of Twitter accounts and a button to add a new account. When this button is clicked, it triggers a function in the Angular controller: // Function to ...

Determine the total cost based on the quantity purchased

I created a webpage for employees to select an item from a dropdown menu, and it will automatically display the price of that item. Check out my code below: <script> $(document).ready(function() { $('#price_input').on('change' ...

I am encountering an issue while attempting to set up admob for my react native application, as I am facing

Encountering an error The file "/BuildProductsPath/Release-iphoneos/XCFrameworkIntermediates/GoogleAppMeasurement/WithoutAdIdSupport/GoogleAppMeasurement.framework/GoogleAppMeasurement(APMAdExposureReporter.o)" does not have bitcode. Suggestions include r ...

Exploring ways to pass props in functional components in React Native

I am currently exploring how to create an API in React Native with TypeScript without using the class extends component. However, I am struggling to figure out how to access and send props from one const view to another function: App.tsx import React, {us ...

What is the most efficient method for managing axios errors in Laravel and Vue.js?

Currently, I am developing spa web applications using Laravel as the backend and Vue.js as the frontend framework. For authentication with API, I am utilizing Laravel Passport, and for managing my application state, I am using Vuex. Initially, I created A ...

What makes styling a success button in @material-ui so challenging?

I am currently utilizing the user interface framework found at https://material-ui.com/ My primary aim is to obtain a success Button and Chip. Can anyone provide insight on achieving this goal without resorting to less-than-ideal methods like those discus ...

React - The issue with my form lies in submitting blank data due to the declaration of variables 'e' and 'data' which are ultimately left unused

Currently, I'm working on incorporating a form using the react-hook-form library. Despite following the documentation and utilizing the handleSubmit function along with a custom Axios post for the onSubmit parameter like this: onSubmit={handleSubmit( ...

Illustrative demonstration of AngularJS

One way to showcase data using AngularJS is by triggering a function with a button click. Here's an example: <!DOCTYPE html> <html ng-app> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"& ...

Navigating through the nested object values of an Axios request's response can be achieved in React JS by using the proper

I am attempting to extract the category_name from my project_category object within the Axios response of my project. This is a singular record, so I do not need to map through an array, but rather access the entire object stored in my state. Here is an ex ...

The event listener for the custom cursor in Nuxt.js is failing to work properly when the route

I am currently in the process of constructing a new website for our studio, but am encountering difficulties with getting the custom cursor to function correctly. I implemented a custom cursor using gsap, and it worked perfectly; however, once I navigate t ...

Deleting a nested object from an array within another object

Recently, I delved into the world of Redux and have found it quite fascinating. However, I am currently facing a dilemma where my new reducer function inadvertently changes the type of a state variable, which is not what I intended. The desired structure ...

Tips for sending a form and showing results without the need to refresh the page

I am currently working on developing a basic calculator that takes a user input number and displays the calculated output without redirecting or reloading the page. However, since I have no experience with JavaScript (js) and Ajax, I am seeking assistance ...

"An ng-repeat directive with a filter applied results in an empty

After successfully implementing the ng-repeat loop below: <div ng-repeat="einschItem in einschaetzungen.alldata | filter: { savedatum: lolatage[tagarrayindex].tagestring } | orderBy : '-savetimestamp'"> I wanted to check if the filtered r ...

What is causing the issue with transmitting the server datetime to my local jQuery script?

I am facing an issue with my timeoftheserver.php page setup. The PHP code is quite simple: <?php echo date('D, d M y H:i:s'); ?> Similarly, the script on my local machine is also straightforward: var today; try { today = new Date($. ...

Utilize filtering techniques on a nested system

After creating an Angular app to display a hierarchy, I am now attempting to add a text box on top of the hierarchy for data filtering purposes. Despite trying various filter examples, I have not achieved much success. My goal is to implement Angular bind ...

Displaying the information fetched using axios on the screen using node.js

Is there a way to display the information from the input boxes in the image on the screen using node js? ...

Why isn't the background-image displaying with the use of the url() function?

I've been attempting to set an image as the background using background-img:url(imageLing), but it's not working properly. When I inspect the element, it shows me background-image: url(assets/backgrounds/5.jpg);. What could be causing this issue? ...

Obtain an item from an array by utilizing the property with Lodash _.find

I currently have an array of objects called memberToChange.checkboxes: ICheckbox[] structured like this: https://i.stack.imgur.com/LyKVv.png Within this setup, there is also a variable named internalNumber with the value "3419". My objective is to locate ...

The typescript error TS2339 is triggered by the property 'webkitURL' not being found on the 'Window' type

Currently utilizing Angular 2 in a project that is compiled with TypeScript. Encountering an issue when attempting to generate a blob image: Error TS2339: Property 'webkitURL' does not exist on type 'Window' The TypeScript code causi ...

Is jQuery capable of appropriately escaping my quotes?

Currently, I am utilizing $.cookie() to retrieve all the values from a cookie which are stored in JSON format: var properties = $.cookie('params'); The output of properties is: {"distinct_id": "13f97d6600b42e-000e6293c-6b1b2e75-232800-13f97d66 ...