diff --git a/packages/scratch-vm/src/serialization/deserialize-assets.js b/packages/scratch-vm/src/serialization/deserialize-assets.js
index 568614c3dc..c1e85c6d4a 100644
--- a/packages/scratch-vm/src/serialization/deserialize-assets.js
+++ b/packages/scratch-vm/src/serialization/deserialize-assets.js
@@ -1,5 +1,6 @@
 const JSZip = require('jszip');
 const log = require('../util/log');
+const {sanitizeSvg} = require('@scratch/scratch-svg-renderer');
 
 /**
  * Deserializes sound from file into storage cache so that it can
@@ -156,6 +157,11 @@ const deserializeCostume = function (costume, runtime, zip, assetFileName, textL
 
     return Promise.all([textLayerFilePromise,
         costumeFile.async('uint8array')
+            .then(data =>
+                (costumeFormat === 'svg' ?
+                    sanitizeSvg.sanitizeByteStream(data) :
+                    data)
+            )
             .then(data => storage.createAsset(
                 assetType,
                 // TODO eventually we want to map non-png's to their actual file types?
diff --git a/packages/scratch-vm/test/fixtures/corrupt_svg.sb2 b/packages/scratch-vm/test/fixtures/corrupt_svg.sb2
index 4290c1bfcd..065f7127a7 100644
Binary files a/packages/scratch-vm/test/fixtures/corrupt_svg.sb2 and b/packages/scratch-vm/test/fixtures/corrupt_svg.sb2 differ
diff --git a/packages/scratch-vm/test/fixtures/corrupt_svg.sb3 b/packages/scratch-vm/test/fixtures/corrupt_svg.sb3
index 52fb93096f..5a7914ada1 100644
Binary files a/packages/scratch-vm/test/fixtures/corrupt_svg.sb3 and b/packages/scratch-vm/test/fixtures/corrupt_svg.sb3 differ
diff --git a/packages/scratch-vm/test/fixtures/corrupt_svg.sprite2 b/packages/scratch-vm/test/fixtures/corrupt_svg.sprite2
index 0db0dd70b9..ed846d00e9 100644
Binary files a/packages/scratch-vm/test/fixtures/corrupt_svg.sprite2 and b/packages/scratch-vm/test/fixtures/corrupt_svg.sprite2 differ
diff --git a/packages/scratch-vm/test/fixtures/corrupt_svg.sprite3 b/packages/scratch-vm/test/fixtures/corrupt_svg.sprite3
index 1d9dd0b3dd..5be5353d9e 100644
Binary files a/packages/scratch-vm/test/fixtures/corrupt_svg.sprite3 and b/packages/scratch-vm/test/fixtures/corrupt_svg.sprite3 differ
diff --git a/packages/scratch-vm/test/integration/monitors_sb2_to_sb3.js b/packages/scratch-vm/test/integration/monitors_sb2_to_sb3.js
index 77b67bce85..ffd52399af 100644
--- a/packages/scratch-vm/test/integration/monitors_sb2_to_sb3.js
+++ b/packages/scratch-vm/test/integration/monitors_sb2_to_sb3.js
@@ -4,40 +4,25 @@ const makeTestStorage = require('../fixtures/make-test-storage');
 const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer;
 const VirtualMachine = require('../../src/index');
 
-let vm;
+const projectUri = path.resolve(__dirname, '../fixtures/monitors.sb2');
+const project = readFileToBuffer(projectUri);
 
-tap.beforeEach(() => {
-    const projectUri = path.resolve(__dirname, '../fixtures/monitors.sb2');
-    const project = readFileToBuffer(projectUri);
-
-    vm = new VirtualMachine();
-    vm.attachStorage(makeTestStorage());
-
-    // TODO figure out why running threads doesn't work in this test
-    // vm.start();
-    vm.clear();
-    vm.setCompatibilityMode(false);
-    vm.setTurboMode(false);
-
-    return vm.loadProject(project);
-});
 const test = tap.test;
 
 test('saving and loading sb2 project with monitors preserves sliderMin and sliderMax', t => {
+    const vm = new VirtualMachine();
+    vm.attachStorage(makeTestStorage());
 
     vm.on('playgroundData', e /* eslint-disable-line no-unused-vars */ => {
-        // TODO related to above TODO, comment these back in when we figure out
-        // why running threads doesn't work with this test
-
-        // const threads = JSON.parse(e.threads);
+        const threads = JSON.parse(e.threads);
         // All monitors should create threads that finish during the step and
         // are revoved from runtime.threads.
-        // t.equal(threads.length, 0);
+        t.equal(threads.length, 0);
 
         // we care that the last step updated the right number of monitors
         // we don't care whether the last step ran other threads or not
-        // const lastStepUpdatedMonitorThreads = vm.runtime._lastStepDoneThreads.filter(thread => thread.updateMonitor);
-        // t.equal(lastStepUpdatedMonitorThreads.length, 8);
+        const lastStepUpdatedMonitorThreads = vm.runtime._lastStepDoneThreads.filter(thread => thread.updateMonitor);
+        t.equal(lastStepUpdatedMonitorThreads.length, 8);
 
         // There should be one additional hidden monitor that is in the monitorState but
         // does not start a thread.
@@ -139,13 +124,18 @@ test('saving and loading sb2 project with monitors preserves sliderMin and slide
         t.equal(monitorRecord.spriteName, null);
         t.equal(monitorRecord.targetId, null);
 
+        vm.quit();
         t.end();
     });
 
     // Start VM, load project, and run
     t.doesNotThrow(() => {
-        const sb3ProjectJson = vm.toJSON();
-        return vm.loadProject(sb3ProjectJson).then(() => {
+        vm.start();
+        vm.clear();
+        vm.setCompatibilityMode(false);
+        vm.setTurboMode(false);
+        return vm.loadProject(project).then(() => {
+            vm.greenFlag();
             setTimeout(() => {
                 vm.getPlaygroundData();
                 vm.stopAll();
diff --git a/packages/scratch-vm/test/integration/offline-custom-assets.js b/packages/scratch-vm/test/integration/offline-custom-assets.js
index d52dda6d61..42d890a73c 100644
--- a/packages/scratch-vm/test/integration/offline-custom-assets.js
+++ b/packages/scratch-vm/test/integration/offline-custom-assets.js
@@ -10,6 +10,7 @@ const test = require('tap').test;
 const AdmZip = require('adm-zip');
 const ScratchStorage = require('scratch-storage').ScratchStorage;
 const VirtualMachine = require('../../src/index');
+const {sanitizeByteStream} = require('../../../scratch-svg-renderer/src/sanitize-svg');
 
 const projectUri = path.resolve(__dirname, '../fixtures/offline-custom-assets.sb2');
 const projectZip = AdmZip(projectUri);
@@ -54,7 +55,7 @@ test('offline-custom-assets', t => {
 
             const storedCostume = customCostume.asset;
             t.type(storedCostume, 'object');
-            t.deepEquals(storedCostume.data, costumeData);
+            t.same(storedCostume.data, sanitizeByteStream(costumeData));
 
             const sounds = vm.runtime.targets[1].sprite.sounds;
             t.equals(sounds.length, 1);
diff --git a/packages/scratch-vm/test/integration/sb2_corrupted_svg.js b/packages/scratch-vm/test/integration/sb2_corrupted_svg.js
index 5ad71fa17c..672a6cf1fb 100644
--- a/packages/scratch-vm/test/integration/sb2_corrupted_svg.js
+++ b/packages/scratch-vm/test/integration/sb2_corrupted_svg.js
@@ -15,6 +15,7 @@ const FakeBitmapAdapter = require('../fixtures/fake-bitmap-adapter');
 const {extractAsset, readFileToBuffer} = require('../fixtures/readProjectFile');
 const VirtualMachine = require('../../src/index');
 const {serializeCostumes} = require('../../src/serialization/serialize-assets');
+const {sanitizeByteStream} = require('../../../scratch-svg-renderer/src/sanitize-svg');
 
 const projectUri = path.resolve(__dirname, '../fixtures/corrupt_svg.sb2');
 const project = readFileToBuffer(projectUri);
@@ -23,7 +24,7 @@ const originalCostume = extractAsset(projectUri, costumeFileName);
 // We need to get the actual md5 because we hand modified the svg to corrupt it
 // after we downloaded the project from Scratch
 // Loading the project back into the VM will correct the assetId and md5
-const brokenCostumeMd5 = md5(originalCostume);
+const brokenCostumeMd5 = md5(sanitizeByteStream(originalCostume));
 
 global.Image = function () {
     const image = {
@@ -57,7 +58,7 @@ tap.beforeEach(() => {
     // Mock renderer breaking on loading a corrupt costume
     FakeRenderer.prototype.createSVGSkin = function (svgString) {
         // Look for text added to costume to make it a corrupt svg
-        if (svgString.includes('<here is some')) {
+        if (svgString.includes('<rect width="100 height=100 fill=">')) {
             throw new Error('mock createSVGSkin broke');
         }
         return FakeRenderer._nextSkinId++;
diff --git a/packages/scratch-vm/test/integration/sb3_corrupted_svg.js b/packages/scratch-vm/test/integration/sb3_corrupted_svg.js
index d4efe3653d..f8c8e4b268 100644
--- a/packages/scratch-vm/test/integration/sb3_corrupted_svg.js
+++ b/packages/scratch-vm/test/integration/sb3_corrupted_svg.js
@@ -14,6 +14,7 @@ const FakeRenderer = require('../fixtures/fake-renderer');
 const {extractAsset, readFileToBuffer} = require('../fixtures/readProjectFile');
 const VirtualMachine = require('../../src/index');
 const {serializeCostumes} = require('../../src/serialization/serialize-assets');
+const {sanitizeByteStream} = require('../../../scratch-svg-renderer/src/sanitize-svg');
 
 const projectUri = path.resolve(__dirname, '../fixtures/corrupt_svg.sb3');
 const project = readFileToBuffer(projectUri);
@@ -22,7 +23,7 @@ const originalCostume = extractAsset(projectUri, costumeFileName);
 // We need to get the actual md5 because we hand modified the svg to corrupt it
 // after we downloaded the project from Scratch
 // Loading the project back into the VM will correct the assetId and md5
-const brokenCostumeMd5 = md5(originalCostume);
+const brokenCostumeMd5 = md5(sanitizeByteStream(originalCostume));
 
 let vm;
 let defaultVectorAssetId;
@@ -37,7 +38,7 @@ tap.beforeEach(() => {
     // Mock renderer breaking on loading a corrupt costume
     FakeRenderer.prototype.createSVGSkin = function (svgString) {
         // Look for text added to costume to make it a corrupt svg
-        if (svgString.includes('<here is some')) {
+        if (svgString.includes('<rect width="100 height=100 fill=">')) {
             throw new Error('mock createSVGSkin broke');
         }
         return FakeRenderer._nextSkinId++;
diff --git a/packages/scratch-vm/test/integration/sprite2_corrupted_svg.js b/packages/scratch-vm/test/integration/sprite2_corrupted_svg.js
index 866448d797..b7776435d2 100644
--- a/packages/scratch-vm/test/integration/sprite2_corrupted_svg.js
+++ b/packages/scratch-vm/test/integration/sprite2_corrupted_svg.js
@@ -16,6 +16,7 @@ const FakeBitmapAdapter = require('../fixtures/fake-bitmap-adapter');
 const {extractAsset, readFileToBuffer} = require('../fixtures/readProjectFile');
 const VirtualMachine = require('../../src/index');
 const {serializeCostumes} = require('../../src/serialization/serialize-assets');
+const {sanitizeByteStream} = require('../../../scratch-svg-renderer/src/sanitize-svg');
 
 const projectUri = path.resolve(__dirname, '../fixtures/default.sb3');
 const project = readFileToBuffer(projectUri);
@@ -28,7 +29,7 @@ const originalCostume = extractAsset(spriteUri, costumeFileName);
 // We need to get the actual md5 because we hand modified the svg to corrupt it
 // after we downloaded the project from Scratch
 // Loading the project back into the VM will correct the assetId and md5
-const brokenCostumeMd5 = md5(originalCostume);
+const brokenCostumeMd5 = md5(sanitizeByteStream(originalCostume));
 
 global.Image = function () {
     const image = {
@@ -61,7 +62,7 @@ tap.beforeEach(() => {
     // Mock renderer breaking on loading a corrupt costume
     FakeRenderer.prototype.createSVGSkin = function (svgString) {
         // Look for text added to costume to make it a corrupt svg
-        if (svgString.includes('<here is some')) {
+        if (svgString.includes('<rect width="100 height=100 fill=">')) {
             throw new Error('mock createSVGSkin broke');
         }
         return FakeRenderer.prototype._nextSkinId++;
diff --git a/packages/scratch-vm/test/integration/sprite3_corrupted_svg.js b/packages/scratch-vm/test/integration/sprite3_corrupted_svg.js
index f78f468a06..6d2da371dd 100644
--- a/packages/scratch-vm/test/integration/sprite3_corrupted_svg.js
+++ b/packages/scratch-vm/test/integration/sprite3_corrupted_svg.js
@@ -15,6 +15,7 @@ const FakeRenderer = require('../fixtures/fake-renderer');
 const {extractAsset, readFileToBuffer} = require('../fixtures/readProjectFile');
 const VirtualMachine = require('../../src/index');
 const {serializeCostumes} = require('../../src/serialization/serialize-assets');
+const {sanitizeByteStream} = require('../../../scratch-svg-renderer/src/sanitize-svg');
 
 const projectUri = path.resolve(__dirname, '../fixtures/default.sb3');
 const project = readFileToBuffer(projectUri);
@@ -27,7 +28,7 @@ const originalCostume = extractAsset(spriteUri, costumeFileName);
 // We need to get the actual md5 because we hand modified the svg to corrupt it
 // after we downloaded the project from Scratch
 // Loading the project back into the VM will correct the assetId and md5
-const brokenCostumeMd5 = md5(originalCostume);
+const brokenCostumeMd5 = md5(sanitizeByteStream(originalCostume));
 
 let vm;
 let defaultVectorAssetId;
@@ -42,7 +43,7 @@ tap.beforeEach(() => {
     // Mock renderer breaking on loading a corrupt costume
     FakeRenderer.prototype.createSVGSkin = function (svgString) {
         // Look for text added to costume to make it a corrupt svg
-        if (svgString.includes('<here is some')) {
+        if (svgString.includes('<rect width="100 height=100 fill=">')) {
             throw new Error('mock createSVGSkin broke');
         }
         return FakeRenderer.prototype._nextSkinId++;