mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
0deac976f3
Prior to this commit, `LOCALE_DATA` was initialized as a plain object literal:
```typescript
let LOCALE_DATA: {[localeId: string]: any} = {};
```
While `__proto__` is neutralized by the `replace(/_/g, '-')` sanitization step (becoming `--proto--`), keys like `constructor` and `prototype` pass through unchanged and would modify special properties on `Object.prototype` if used as bracket notation keys on a plain object.
**Example attack through the public API:**
```typescript
// attacker calls the public registerLocaleData API with a crafted localeId
registerLocaleData(data, 'constructor');
// internally becomes:
LOCALE_DATA['constructor'] = data;
// → modifies Object.prototype.constructor for every object in the process
// or with extraData:
registerLocaleData(data, 'constructor', extraData);
// LOCALE_DATA['constructor'][LocaleDataIndex.ExtraData] = extraData;
// → Object.prototype[LocaleDataIndex.ExtraData] = extraData
// → every plain object in the process now has this property
// → affects JSON serialization, property enumeration, and framework internals
// consequence — any subsequent object created in the process is affected:
const user = getUserFromSession();
console.log(user[LocaleDataIndex.ExtraData]); // → attacker-controlled value
```
In a long-running SSR server this pollution persists for the lifetime of the process and affects all subsequent requests from all users.
**The fix** initializes `LOCALE_DATA` with `Object.create(null)`:
```typescript
let LOCALE_DATA: {[localeId: string]: any} = Object.create(null);
```
A null-prototype object has no prototype chain, so any key is treated as a plain string with no special behavior, making prototype pollution impossible regardless of input — without relying on the sanitization step as the sole protection.