New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 394296 link

Starred by 63 users

Issue metadata

Status: Fixed
Closed: Sep 17
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac , Fuchsia
Pri: 1
Type: Bug

Blocked on:
issue 672370

Show other hotlists

Hotlists containing this issue:

Sign in to add a comment

Hang bug in history.pushState()

Reported by, Jul 16 2014

Issue description

You can hang the browser immediately. Potential for heap spray, I am not a pro in buffer overflows so I don't know.
TL;DR: Hang browser, 50% cpu, ram filling up 7mb/s.

Chrome Version: 35.0.1916.153 m + stable
Operating System: Windows 8.1

Full attack included, Simplest case:

for(var i = 0; i<1000000; i++){

Type of crash: Browser
Crash State: (Doesn't technically crash, just hang)
Client ID (if relevant): [see statement above]

249 bytes View Download
Showing comments 2 - 101 of 101 Older
Labels: OS-All Pri-2 M-38 Cr-UI-Browser-Navigation Security_Impact-Stable Security_Severity-Low
Status: Available
nasko: Assigning to you as content/browser/frame_host/OWNERS; please re-assign if appropriate.

Comment 3 by, Jul 17 2014

Labels: -Restrict-View-SecurityTeam -Type-Bug-Security -Security_Impact-Stable -Security_Severity-Low Type-Bug
Owner: ----
Summary: Hang bug in history.pushState() (was: Security: Crash/Hang bug in history.pushState())
Removing security bits from the bug. As per, this is not a security bug.

Since this is just a generic DoS in the browser due to huge amount of IPC messages coming in, I'm unassigning myself from it for anyone interested in tackling this problem.

Comment 4 Deleted

Comment 5 by Deleted ...@, Nov 5 2014

I found another case where this occurs:

If you write an endless recursion like following you will get the error 'RangeError: Maximum call stack size exceeded ':

var endless = function() {

But not if you change this recursion to something with history.pushState:

var endless = function() {
	history.pushState(undefined, undefined, window.location.toString().split('#')[0]);

Comment 6 by, Feb 20 2015

 Issue 460291  has been merged into this issue.

Comment 7 by, Feb 23 2015

Nasko: Having 1M history items in a session isn't realistic, would it be possible/reasonable to add a hard limit to the number of history entries?

Comment 8 by, Feb 23 2015

meacer@ - the problem isn't history limit, it doesn't actually go above 50. The underlying issue is that the IPC queue doesn't have a limit, so we have a TON of IPCs queued up because of the pushState call in a loop. It just takes lots of CPU and time to process through the messages.

Comment 9 by, Feb 24 2015

Ah I see, so it's irrelevant of the API accepting/rejecting the input. Good to know, thanks!

Comment 10 by, Nov 18 2015

 Issue 544132  has been merged into this issue.

Comment 11 by, Nov 18 2015

 Issue 544132  was the same thing with a reload instead of pushState.  Agreed that there's not much that can be done without having a rate limiting mechanism for IPC.
 Issue 581237  has been merged into this issue.

Comment 13 by, Jan 27 2016

This bug was turned into a tool for trolls. They post links (, everywhere, from Twitter to Facebook.
Some even clone the JS code and/or obfuscate with URL shortening services.

Comment 14 by, Jan 27 2016

Is it there any form to fix it? I can't use Chrome for more than 45 seconds. I tried erasing my history and that and it isn't possible because Chrome crashes before it erases everything.

Comment 15 by, Jan 27 2016

If Chrome crashes when it restarts, you can delete file "Current Tabs" in your profile folder, or you can disconnect/disable the network.
Just tried it on Windows stable (32-bit)...Looks like it caused an OOM crash in the browser process, after hanging for a bit.
Reported Jul 16, 2014

so google, you had to wait one and a half until this turned into abuse. "Thank you" for not giving a damn about it. now I've lost all my history because of this.

Comment 18 by, Apr 27 2016

is this fixed in Chrome 50?

Comment 19 by, May 17 2016

It's a shame :( Apple fix Safari in iOS 9.3.1 so it doesn't crash anymore.
But Chrome still doesn't fix this issue.
You still risk crashing Chrome anytime you visit a website.
kinuko@, maybe the IPC batching project you are looking into could be extended to enable rate limiting?

How general will the system be?
We're aiming for making it general at least in the loading field, if we're sending too many IPC requests at once that's causing the system frozen I think we could certainly alleviate this issue by batching.

Comment 22 by, May 23 2016

It's great to see some progress in this issue.
I hope that this will landed in Chrome 53.
Project Member

Comment 23 by ClusterFuzz, Jun 14 2016

Labels: ClusterFuzz-Verified
Status: Verified (was: Available)
ClusterFuzz testcase is verified as fixed, closing issue.

If this is incorrect, please add ClusterFuzz-Wrong label and re-open the issue.
Labels: -ClusterFuzz-Verified
Status: Assigned (was: Verified)
Sorry for the incorrect ClusterFuzz update, please ignore it. Reopening bug.

Comment 25 by, Jun 27 2016

It looks like we have some progress on this nasty issue.

Comment 26 by, Aug 10 2016

 Issue 627688  has been merged into this issue.
Status: Untriaged (was: Assigned)
Labels: -M-38
 Issue 645706  has been merged into this issue.
Issue 627922 has been merged into this issue.
Components: Internals>Core
kinuko@: Are you still working on the IPC batching project mentioned in comments 20-21?  Can you mark this as blocked on that?

There's not much navigation folks can do about this-- it would work with any flood of IPCs.
Owner: ----
kinuko@ has been exploring batching IPC for loading

Unfortunately I don't think there is any plan for a general system for rate limiting IPC, as of now. Possibly mojo team could help with this with the new system? Moving kinuko to cc.
Labels: -Type-Bug Type-Bug-Security
Changing to bug-security, @sherriff, could you take a look?
Components: Internals>Mojo
Labels: -Pri-2 Security_Impact-Stable Security_Severity-Medium Pri-1
Status: Available (was: Untriaged)
csharrison/creis -- Can you recommend someone from Mojo that might be able to address this?

While it is a DoS, I think it qualifies as a security bug since it completely blocks the users' ability to close a social engineering site, and now it's being actively exploited. It prevents the user from interacting with any security UX.
until we have the IPC throttling, we could just put some rate limiting in place for the pushState API in the renderer, no?
Status: Assigned (was: Available)
I can take a look at this one (or reassign to someone else if there's more appropriate person)
Project Member

Comment 39 by, Nov 4 2016

Labels: M-55
#c37, we could, but what is to stop the attackers to move over to replaceState, fragment navigations, localStorage, possibly a handful other ways that I'm missing? We could rely on them giving up since they only know of it by scanning our bug database, but that would be nasty cat/mouse game to be playing.
Excellent, thanks kinuko.

FYI the abuse of this bug is showing up on several security blogs, starting at

nasko -- Agreed, #c37 only fixes the currently-abused method, but it might give us time to be able to address the others.
yeah, I expect that it's going to be easier to backmerge and quicker to implement
Comment 37, 40-42: I do not think we should get into a game of whack-a-mole (by rate limiting pushState), because there are plenty of IPCs the renderer could send to cause DoS in the browser.  Finding some general approach seems required, and Safe Browsing should help block known cases in the meantime.

I agree that we should try to do something about this-- thanks kinuko@ for taking a look!

However, I don't understand why this is rated as a medium severity security bug according to our guidelines.  That's not what our documentation says (because the architecture was never designed to prevent it):
creis--  Re: security-medium, I commented on this in #c35, specifically that this prevents the user from inspecting page-info or interacting with any other security UI. Something like a data:url that's semi-spoofing a legit domain would be impossible to investigate w/o that UI. If the consensus is that that's not sufficient, let's mark it as a regular bug but still push for a merge. I'm fine with that.
Labels: -Type-Bug-Security -Security_Impact-Stable -Security_Severity-Medium Restrict-View-EditIssue Type-Bug
The abuse of this bug for phishing purposes is certainly not a good thing, but the fact that the attack is phishing also clearly underscores that this is not a security vulnerability as defined in our threat model. It's a DoS, and DoS is outside of our threat model because it's unpreventable (particularly this class of DoS), doesn't violate any trust boundaries, and doesn't lead to direct exposure or compromise of user or site data.

I agree that we should try to fix this quickly to prevent further abuse, but we can't ad hoc change our classifications.

I was curious if there are *persistent* effects of a flood of pushState (I agree with comments above that abusing *transient* CPU/memory/IPCs and hanging the browser is not really a security issue).  I found that:

1. There is indeed no limit on the number of history entries that can be created (as long as the URIs of the entries are unique).

2. After creating 50000 history entries (*) and restarting the browser, I didn't observe zny severe impact to the browser performance:

2a. No change to start-up time.
2b. Some slow-down of the omnibox, but nothing severe.
2c. Search and scrolling on chrome://history (the new, material UI) worked fine.

3. I also tried killing the browser process while it was being flooded with pushState calls.  I didn't see any issues (e.g. no corruption of history state) after restarting the browser.

var start = 1;
var count = 1000;
for (i = 0; i < count; i++) {
  var index = start + i;
  history.pushState(index, "test" + index, location.origin + "/" + index);
+gab@ - I wonder if the new, redesigned task scheduler might help prevent one renderer from flooding the message loop and starving other renderers + starving more important browser tasks.  Maybe we could have a TaskTrait that says whether a particular message loop task / callback originated from a renderer (OTOH, I guess that propagating that bit as a callback spawns other callbacks might be challenging).  Is it worth opening a separate bug to track task scheduler considerations around starvation-by-misbehaving-renderer?  FWIW, I've also left a comment/question in
#47 - There're things that can be better throttled / controlled at task level and others that are not (i.e. one single task could screw up things), but yep in general it'd be good to consider how we should handle tasks from misbehaving renderers.
Labels: -M-55 M-57
Sorry for slow updates, I got distracted by other misc stuff / ooo schedule etc.  Now I have a wip patch that does:

* applies basic rate limiting for both traditional and mojo IPC from renderer
* triggers throttling once the renderer starts to send messages more than the given limit for a certain period

This allows the browser and other tabs to continue to just work while loading http://localhost:8000/crash.html or similar other pages.  Current throttling algorithm is not ideal though (naturally), as it's heuristics-based and not getting much signals that might be useful to make better decisions, which could be hopefully done in follow-up changes.  I'll make a short write-up and will start to hear opinion from more people (while the timing may not be quite great as many people will be ooo)

Blockedon: 672370
 Issue 671879  has been merged into this issue.
 Issue 688246  has been merged into this issue.
Issue 648333 has been merged into this issue.
 Issue 412114  has been merged into this issue.
 Issue 702415  has been merged into this issue.
 Issue 710189  has been merged into this issue.
@kinuko, do you have any update on this bug? it would be great to have a plan to attack this as reports keep rolling in about this behavior.
 Issue 716414  has been merged into this issue.
Issue 721477 has been merged into this issue.
 Issue 738470  has been merged into this issue.
Labels: -OS-All -Restrict-View-EditIssue -M-57 allpublic M-61 OS-Android OS-Chrome OS-Fuchsia OS-Linux OS-Mac OS-Windows
I have a mitigation (not solution) CL in progress that will hopefully land in time for M61.

This bug is basically public; opening it up.
We may also want to set a limit on how large the state object can get, and/or find a way to better serialize large objects at the Mojo layer (such as by automatically turning them into shared memory segments when they cross a threshold, or something). The CL as it currently stands helps, but the 'attack' PoC does still make the browser sluggish and a bit unpredictable.
is this about my  issue ??

waiting for your replay as soon as possible .

Thanks in advance .

2017-07-07 23:53 GMT+03:00 pal… via monorail <>:
Project Member

Comment 64 by, Jul 11 2017

The following revision refers to this bug:

commit 95558ee76640b366e8b775bd93483b99af379f55
Author: palmer <>
Date: Tue Jul 11 02:33:43 2017

Mitigate the pushState IPC storm DoS.

This is nothing like what the ultimate, true solution should look like. It does
seem to work for the narrow problem of calling history.pushState in a tight
loop, however.

BUG= 394296 

Cr-Commit-Position: refs/heads/master@{#485498}


Issue 651066 has been merged into this issue.
Will this issue started by me and owned by me cause am the first one who reported about it ,So i wish i get a replay for that ,i wanna know what happened to my report ??????


mohacker182:  This doesn't look to have anything to do with any of the bug reports you filed.
no i think it does cause i didn't get any replay about what happened to my report about the vulnerability which is has this Number   Issue 394296 ???
Labels: Restrict-AddIssueComment-EditIssue
That's this issue, and you weren't the reporter of this issue.  Anyhow, not worth wasting developer time figuring out if this was "your" bug or not.
Labels: -Restrict-AddIssueComment-EditIssue
My last post on this bug set the wrong tone - I apologize. I am still having a hard time understanding exactly what you are asking for, and which bug you are referring to. It appears that this bug was reported by someone else, and I don't see any other similar bugs. Please help clear this up.

It looks to me like the only two bugs you filed were  and , neither of which look to me to be related to this issue.
Hi mohacker182@ - I'm a Chrome TPM and help wrangle bugs. If you could mail me a summary of your question to I'll help chase down some answers :-)  Thanks!
Status: Started (was: Assigned)
This has been set to P1+M61, so this bug needs an active owner.

palmer@: I'm tentatively assigning to you since you landed a CL. Is there more to do? Can you continue to own this bug?

Comment 74 Deleted

There is more to do, but I don't volunteer to do it because I have my own backlog of bugs to handle. :) Sorry. :)

I volunteered to land the quick hack to be friendly, and I think the hack does somewhat mitigate the {push,replace}State problem. For what it's worth.

We know the long-term fix must be in the IPC-receiver-side, and must be generic to all floods (probably including transparently handling huge messages as well as ridiculously frequent messages). (There's been some talk about transparently serializing huge messages as shared memory segments, without making the programmer do it themselves?)

If kinuko doesn't have time to dig into it in the short term, maybe we should raise this issue to the Mojo Gurus?

Comment 76 by, Jul 15 2017

Labels: -OS-Fuchsia

Comment 77 by, Aug 25 2017

 Issue 757023  has been merged into this issue.

Comment 78 by, Aug 25 2017

 Issue 759074  has been merged into this issue.

Comment 79 by, Aug 28 2017

 Issue 759368  has been merged into this issue.
 Issue 761843  has been merged into this issue.

Comment 81 by, Sep 15 2017

Issue 144450 has been merged into this issue.
 Issue 765379  has been merged into this issue.
Hi all, looks like the changes related to this issue are impacting our test suite as we have a url state management lib with a bunch of fast test cases that use history.replaceState.

So there are two asks:
1. When it fails it would be nice to have feedback given (maybe something logged to the console). Currently, history.replaceState just no-ops without explaining why.
2. Some mechanism to work around this. Maybe a flag that can be used to disable the throttling/limit? We don't expect to ever hit this in production, just in our test cases, so it would be reasonable to run Chromium with a flag.

For reference, original Twitter convo:

Comment 85 by, Sep 28 2017

Comment 84: That seems like a reasonable proposal.  I've filed  issue 769592  to track it.

Comment 86 by, Nov 30 2017

Status: Fixed (was: Started)
The bug was fixed and pushed out in m61 which went to users in early September, so marking the specific bug about pushstate as fixed.

We can discuss other generic solutions separately.
Hi, i think the fix for this issue made my silly snake game unusable on Chrome ( The game can be played fine for a couple of seconds, but then the UI (the adress-bar) stops refreshing and a "Throttling history state changes to prevent the browser from hanging" message is logged to the console.

The game calls history.replaceState on every tick (which is around 10 times per second). I understand that this throttling is needed to avoid bad-intended code from crashing or hanging the browser, but those attacks were making thousands or millions of calls. Could the limit be raised up a notch, so that history.replaceState can be called a bit more frequently? :)

And, in case it's not possible to raise the limit, may i ask: what are the numbers for this throttling policy? I might be able to adapt the code to make it run more smoothly on Chrome.

(BTW, the game is playable on Firefox and *gasps* IE!)

#87: Hello, and sorry about that. We are tracking the problem you describe in issue

The limit is 50 updates per 10 seconds, as implemented in
#88 Thanks for the update Palmer, and thanks for the work that you've been doing to fix that issue! It's definitely appreciated :D
#89: Thanks. :)
#88, Palmer, it seems the fix was reverted, right? :(

Is there something i could do to help?
#91: Well, it was reverted because it turned out to not be a fix (alas). (

We could increase `kStateUpdateLimit` in `History::ShouldThrottleStateObjectChanges` fairly easily.
>We could increase `kStateUpdateLimit` in `History::ShouldThrottleStateObjectChanges` fairly easily.

Yeah, or decrease kStateUpdateLimitResetInterval. If 60fps updates are wanted (as i understood your first patch intended to implement), then having kStateUpdateLimitResetInterval=1sec and kStateUpdateLimit=60 should be enough. Do you think that falls under the risky side of flood prevention? If you're busy, i can try to submit a patch :)
#93: With, I was able to run the game for a minute or 3 without getting any console warnings.

My high score is 2.
#94 Thanks a lot Palmer! :D

I hope that change doesn't screw the test suite and gets merged ^_^

I'm sure you can beat that score btw ;)
Labels: OS-Fuchsia
Status: Started (was: Fixed)
Testing shows that 8 FPS is enough to still run the snake game without console warnings, so I'm going with that as the like most History-API-intensive caller that is not malicious. We can bump it up higher than 8 if necessary, but for now this seems good.

My high score is now 11. Soon I will rule the galaxy.
Project Member

Comment 97 by, Sep 14

The following revision refers to this bug:

commit 5a152048408bb6995bbee8e06dab1026de00e1c5
Author: Chris Palmer <>
Date: Fri Sep 14 23:14:03 2018

Increase the history state rate limit to 8 FPS.

This somewhat relaxes the limitation, enabling more legitimate use-cases while
still seemingly being low enough to contain abuse. Also, expressing the
limitation in terms of FPS makes the limit less arbitrary. 8 FPS for history
modification comports with other performance and functionality goals (like 60
FPS for graphics).

Bug:  394296 
Change-Id: Ic8edd8c3af57dc4436c71f9c03fb26face4114d7
Commit-Queue: Chris Palmer <>
Reviewed-by: Kinuko Yasuda <>
Cr-Commit-Position: refs/heads/master@{#591518}

Thanks so much for taking care of this, Chris :D

I noticed you tightened the restriction from 60 updates per second to 8 (or 80/10s). I'm curious about why was that. Do you reckon 60 updates per second (or 600/10s) would be prone to abuse?

About the limit itself and the particular use case of my silly game, it would cause some frame drops at some point, because the speed steadily increases[1] (14 "fps" would cover it), but i think it's completely understandable if the stability of a browser would be compromised otherwise :) 

I'd just wish for not having to worry about the limit (that's why i thought a 60-updates per second limit was awesome), imagine the possibilities for addressbar-interactive applications! :P


Labels: Needs-Feedback
Tried to reproduce this issue on Windows 10 on the build without fix 68.0.3397.0 and unable to reproduce the issue by following the below steps.

1. Launched Chrome and opened the given html page in Comment #0.
2. Couldn't observe any hang, crash on Chrome and no increase in CPU in Chrome task manager is also observed.

palmer@ / Reporters@ -  Request you to check and confirm if anything is missed from our end in verifying the issue and help us in verifying the fix on the latest Canary(71.0.3554.0) build.

Status: Fixed (was: Started)
#98: I do think 60/s would be OK, but 600/10s would allow for 600 right away, and there is potentially some risk there. And, I had to crank it up to N*10/10, because some tests do work by storming IPC real fast and then (because they aren't attacks) stopping. This whole approach to the problem is inherently hacky and these arbitrary limitations are a bummer.

#99: The browser hang problem is covered by a previous fix to this bug (See #64). I reopened the bug because I was loosening the restrictions in the previous fix.
palmer@ -- As we are not able to reproduce the issue from our end to verify the fix. Could you please verify the fix from you end and provide comments. Or let us know if we can verify the fix by following any steps from TE's end, so that we can verify and add TE-Verified labels.

Showing comments 2 - 101 of 101 Older

Sign in to add a comment