diff --git a/lib/sb3.js b/lib/sb3.js
index 811bfd5..2002ff2 100644
--- a/lib/sb3.js
+++ b/lib/sb3.js
@@ -52,7 +52,15 @@ const extract = function (targets, attribute, id, hash) {
             const asset = targets[t][attribute][a];
             occurrences++;
             if (typeof id !== 'undefined') idList.push(asset[id]);
-            if (typeof hash !== 'undefined') hashList.push(asset[hash]);
+            if (typeof hash !== 'undefined') {
+                if (asset[hash]) {
+                    hashList.push(asset[hash]);
+                } else if (hash === 'md5ext') {
+                    // Some projects don't have an md5ext field for some reason,
+                    // extract that data from the assetId and dataFormat
+                    hashList.push(asset.assetId + '.' + asset.dataFormat);
+                }
+            }
         }
     }
 
diff --git a/test/fixtures/699953650.json b/test/fixtures/699953650.json
new file mode 100644
index 0000000..4a4a86d
--- /dev/null
+++ b/test/fixtures/699953650.json
@@ -0,0 +1 @@
+{"targets":[{"isStage":true,"name":"Stage","variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":["my variable",0]},"lists":{},"broadcasts":{},"blocks":{},"comments":{},"currentCostume":4,"costumes":[{"name":"backdrop1","dataFormat":"svg","assetId":"cd21514d0531fdffb22204e0ec5ed84a","md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg","rotationCenterX":240,"rotationCenterY":180},{"name":"Blue Sky","bitmapResolution":1,"dataFormat":"svg","assetId":"e7c147730f19d284bcd7b3f00af19bb6","rotationCenterX":240,"rotationCenterY":180},{"name":"Refrigerator","bitmapResolution":1,"dataFormat":"svg","assetId":"98f053f9681e872f34fafd783ce72205","rotationCenterX":240,"rotationCenterY":180},{"name":"Neon Tunnel","bitmapResolution":2,"dataFormat":"png","assetId":"57d2b13b2f73d3d878c72810c137b0d6","rotationCenterX":480,"rotationCenterY":360},{"name":"Nebula","bitmapResolution":2,"dataFormat":"png","assetId":"9b5cdbd596da1b6149f56b794b6394f4","rotationCenterX":480,"rotationCenterY":360}],"sounds":[{"name":"pop","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","dataFormat":"wav","format":"","rate":48000,"sampleCount":1123,"md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav"}],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"on","textToSpeechLanguage":null},{"isStage":false,"name":"Champ99","variables":{},"lists":{},"broadcasts":{},"blocks":{"m+g,ch+@:#uIX6HQasdr":{"opcode":"event_whenflagclicked","next":"vuD1}/+AoTGn^QY9$N5u","parent":null,"inputs":{},"fields":{},"shadow":false,"topLevel":true,"x":237,"y":201},"vuD1}/+AoTGn^QY9$N5u":{"opcode":"sensing_askandwait","next":null,"parent":"m+g,ch+@:#uIX6HQasdr","inputs":{"QUESTION":[1,[10,"What's your name?"]]},"fields":{},"shadow":false,"topLevel":false}},"comments":{},"currentCostume":0,"costumes":[{"name":"champ99-a","bitmapResolution":2,"dataFormat":"png","assetId":"7b073f47fbd9421e0d60daacc157f506","md5ext":"7b073f47fbd9421e0d60daacc157f506.png","rotationCenterX":248,"rotationCenterY":306},{"name":"champ99-b","bitmapResolution":2,"dataFormat":"png","assetId":"d6ae13605610aa008d48b0c8b25a57d3","md5ext":"d6ae13605610aa008d48b0c8b25a57d3.png","rotationCenterX":164,"rotationCenterY":290},{"name":"champ99-c","bitmapResolution":2,"dataFormat":"png","assetId":"26fdff424232926001d20041c3d5673b","md5ext":"26fdff424232926001d20041c3d5673b.png","rotationCenterX":152,"rotationCenterY":270},{"name":"champ99-d","bitmapResolution":2,"dataFormat":"png","assetId":"a28ffc2b129fb359ff22c79c48341267","md5ext":"a28ffc2b129fb359ff22c79c48341267.png","rotationCenterX":188,"rotationCenterY":260},{"name":"champ99-e","bitmapResolution":2,"dataFormat":"png","assetId":"56f3220fa82d99dcfc7d27d433ed01e4","md5ext":"56f3220fa82d99dcfc7d27d433ed01e4.png","rotationCenterX":190,"rotationCenterY":248},{"name":"champ99-f","bitmapResolution":2,"dataFormat":"png","assetId":"68453506ae4b6b60a3fc6817ba39d492","md5ext":"68453506ae4b6b60a3fc6817ba39d492.png","rotationCenterX":114,"rotationCenterY":250},{"name":"champ99-g","bitmapResolution":2,"dataFormat":"png","assetId":"20318b14a332fd618ec91e7c1de8be9a","md5ext":"20318b14a332fd618ec91e7c1de8be9a.png","rotationCenterX":132,"rotationCenterY":258}],"sounds":[{"name":"dance celebrate","assetId":"0edb8fb88af19e6e17d0f8cf64c1d136","dataFormat":"wav","format":"adpcm","rate":22050,"sampleCount":176785,"md5ext":"0edb8fb88af19e6e17d0f8cf64c1d136.wav"}],"volume":100,"layerOrder":1,"visible":true,"x":21,"y":-50,"size":100,"direction":90,"draggable":false,"rotationStyle":"all around"}],"monitors":[],"extensions":[],"meta":{"semver":"3.0.0","vm":"0.2.0-prerelease.20220525223828","agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53"}}
\ No newline at end of file
diff --git a/test/unit/missing_md5ext.js b/test/unit/missing_md5ext.js
new file mode 100644
index 0000000..13132af
--- /dev/null
+++ b/test/unit/missing_md5ext.js
@@ -0,0 +1,34 @@
+const fs = require('fs');
+const path = require('path');
+const test = require('tap').test;
+const analysis = require('../../lib/index');
+
+// Test project with missing 'md5ext' field
+const defaultObject = fs.readFileSync(
+    path.resolve(__dirname, '../fixtures/699953650.json')
+);
+
+test('Project with missing "md5ext" property can be analyzed correctly', t => {
+    analysis(defaultObject, (err, result) => {
+        t.not(err);
+        t.ok(result);
+
+        // Test that all the costume and sound hashes are not falsey
+        t.equal(result.costumes.count, result.costumes.hash.length);
+        t.equal(result.sounds.count, result.sounds.hash.length);
+
+        for (let i = 0; i < result.costumes.count; i++) {
+            const costumeHash = result.costumes.hash[i];
+            t.type(costumeHash, 'string');
+            t.ok(costumeHash);
+        }
+
+        for (let i = 0; i < result.sounds.count; i++) {
+            const soundHash = result.sounds.hash[i];
+            t.type(soundHash, 'string');
+            t.ok(soundHash);
+        }
+
+        t.end();
+    });
+});