Bug 182097
Summary: | Built-in types read from IndexedDB have corrupt prototype chain and fail instanceof checks | ||
---|---|---|---|
Product: | WebKit | Reporter: | Stefan Sechelmann <stefan> |
Component: | JavaScriptCore | Assignee: | WebKit Security Group <webkit-security-unassigned> |
Status: | RESOLVED DUPLICATE | ||
Severity: | Normal | CC: | bfulgham, product-security, sihui_liu, stefan, webkit-bug-importer, webkit |
Priority: | P2 | Keywords: | InRadar |
Version: | Safari Technology Preview | ||
Hardware: | Mac | ||
OS: | macOS 10.12 | ||
URL: | https://fiddle.jshell.net/sechel/zg0dnx3t/ |
Stefan Sechelmann
In a same-origin iframe, the prototype chain of built-in types such as Object,
Array, CryptoKey, and so on is corrupt when an object is returned from IndexedDB.
Note that, if run in top level context all types are correct. The reason why we
think this is security related is that WebCrypto keys are also affected. For a key
read from IDB `key instanceof CryptoKey` will yield false. At the same time it is
perfectly usable with the `crypto.subtle` API.
See https://fiddle.jshell.net/sechel/zg0dnx3t/ for a demonstration:
QUnit.test('safari indexeddb issue, Native', async assert => {
// check types before insert
assert.ok(data instanceof Object);
assert.ok(data.key instanceof CryptoKey);
assert.ok(data.array instanceof Array);
assert.ok(data.map instanceof Map);
assert.ok(data.set instanceof Set);
// put and get from db
let req = indexedDB.open(dbName, 1);
req.onupgradeneeded = function() {
const db = this.result;
const store = db.createObjectStore(
'test', { autoIncrement: true, keyPath: 'id' }
);
store.createIndex('id', 'id', { unique: true });
};
await new Promise(r => req.onsuccess = r);
const db = req.result;
let tx = db.transaction(['test'], 'readwrite');
let store = tx.objectStore('test');
store.add(data);
await new Promise(r => tx.oncomplete = r);
tx = db.transaction(['test'], 'readonly');
store = tx.objectStore('test');
req = store.get(1);
await new Promise(r => req.onsuccess = r);
const result = req.result;
// check types of result
assert.ok(result instanceof Object);
assert.ok(result.key instanceof CryptoKey);
assert.ok(result.array instanceof Array);
assert.ok(result.map instanceof Map);
assert.ok(result.set instanceof Set);
// workaround, fix prototypes:
result.__proto__ = Object.prototype;
result.key.__proto__ = CryptoKey.prototype;
result.array.__proto__ = Array.prototype;
result.map.__proto__ = Map.prototype;
result.set.__proto__ = Set.prototype;
assert.ok(result instanceof Object);
assert.ok(result.key instanceof CryptoKey);
assert.ok(result.array instanceof Array);
assert.ok(result.map instanceof Map);
assert.ok(result.set instanceof Set);
});
```
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Radar WebKit Bug Importer
<rdar://problem/36864862>
Sihui Liu
*** This bug has been marked as a duplicate of bug 185906 ***