T09 · Insecure Skill Coding Practices
- Location
index.js:48- Finding
Prototype-Key Collision Allows Denial of Service Through Crafted Message Categories
- Content
View full analysis
c / total); } ``` ```js function jointDistribution(msgsA, msgsB, allCategories) { const n = allCategories.length; const catIndex = {}; allCategories.forEach((c, i) => { catIndex[c] = i; }); // Initialize joint count matrix const jointCounts = Array.from({ length: n }, () => new Array(n).fill(0)); const countA = new Array(n).fill(0); const countB = new Array(n).fill(0); const minLen = Math.min(msgsA.length, msgsB.length); for (let i = 0; i < minLen; i++) { const idxA = catIndex[msgsA[i]]; const idxB = catIndex[msgsB[i]]; if (idxA !== undefined && idxB !== undefined) { jointCounts[idxA][idxB]++; countA[idxA]++; countB[idxB]++; } } ``` ### Technical Analysis The implementation uses ordinary JavaScript objects as dictionaries for message categories. Ordinary objects inherit properties from `Object.prototype`. Consequently, attacker-controlled category names such as `__proto__`, `constructor`, or `toString` can resolve to inherited values rather than the numeric values expected by the code. In `jointDistribution()`, an inherited value obtained through `catIndex[msgsA[i]]` or `catIndex[msgsB[i]]` is not `undefined`, so it passes the existing validation. The value is then used as an array index: ```js jointCounts[idxA][idxB]++; ``` Because the inherited value is not a valid numeric matrix index, `jointCounts[idxA]` can be `undefined`, resulting in a `TypeError` when the second index is accessed. The exception is not handled by `j ...[truncated 1643 chars]- Remediation
View remediation
count / total); } ``` ```js const categoryIndex = new Map(); allCategories.forEach((category, index) => { categoryIndex.set(category, index); }); const idxA = categoryIndex.get(msgsA[i]); const idxB = categoryIndex.get(msgsB[i]); if (Number.isInteger(idxA) && Number.isInteger(idxB)) { jointCounts[idxA][idxB]++; countA[idxA]++; countB[idxB]++; } ``` 2. If plain objects must be retained, create dictionaries with `Object.create(null)` and verify keys with `Object.hasOwn()` before using retrieved values. 3. Validate that `msgsA`, `msgsB`, and `allCategories` are arrays and that every category is an accepted primitive type, preferably a string. 4. Confirm that every resolved category index is an integer in the range `0 <= index < allCategories.length` before indexing matrices. 5. Add defensive exception handling at the application boundary so malformed analysis input cannot terminate the hosting process. 6. Add regression tests covering at least: - `__proto__` - `constructor` - `prototype` - `toString` - empty category arrays - non-string categories - categories absent from `allCategories` ]]>
