You've forgotten to begin a new path each time using .beginPath()
(prevents the event stacking issue you're witnessing):
bufCanvas.addEventListener('mousedown', function (e) { ctx.clearRect(0, 0, 500, 500); buf.clearRect(0, 0, 500, 500); img.src = bufCanvas.toDataURL(); buf.beginPath(); // < begin a new path buf.fillStyle = 'hsl('+ ~~(Math.random()*360) +', 100%, 70%)'; buf.rect(Math.random()*w, Math.random()*h, 20, 20); buf.fill(); ctx.drawImage(bufCanvas, 0, 0);});