[GH-ISSUE #6585] [Bug] IndexedDB content fingerprints include optional debugger descriptions #3975

Closed
opened 2026-10-31 00:45:43 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6585

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

Source-only finding; runtime reproduction was not run. inspect_web_page hashes the entire CDP Runtime.RemoteObject wrapper when creating an IndexedDB record's content fingerprint. Two valid wrappers for the same stored primitive, { "type": "number", "value": 7 } and { "type": "number", "value": 7, "description": "7" }, are both accepted as complete but contribute different canonical hash inputs. With identical keys, compare_web_captures consequently classifies the record as modified even though its stored value is unchanged. Optional debugger presentation metadata also enters the key and primary-key identity hashes.

Reproduction

No browser or REA reproduction was executed for this finding. The following is a concrete source-derived trigger, suitable for a controlled CDP fixture; it is not a claimed live-browser transcript.

Use the public inspect_web_page request { "cdp_endpoint": "http://127.0.0.1:9222", "allowed_origins": ["https://example.test"], "target_id": "page", "include_storage_keys": true, "include_storage_fingerprints": true } with an admitted, stable page and otherwise complete unchanged observations. Both storage selections are true, satisfying the request refinement. For storage commands, return the following successful replies in both observations, except for the indicated IndexedDB.requestData value.

{
  "Storage.getUsageAndQuota": {"usage": 0, "quota": 1000},
  "DOMStorage.getDOMStorageItems": {"entries": []},
  "IndexedDB.requestDatabaseNames": {"databaseNames": ["db"]},
  "CacheStorage.requestCacheNames": {"caches": []},
  "Network.getCookies": {"cookies": []},
  "IndexedDB.requestDatabase": {
    "databaseWithObjectStores": {
      "name": "db", "version": 1,
      "objectStores": [{"name": "records", "keyPath": {"type": "null"}, "autoIncrement": false, "indexes": []}]
    }
  },
  "IndexedDB.requestData": {
    "objectStoreDataEntries": [{
      "key": {"type": "number", "value": 1},
      "primaryKey": {"type": "number", "value": 1},
      "value": {"type": "number", "value": 7}
    }],
    "hasMore": false
  }
}

The DOM storage reply applies to both local and session storage reads. In the second observation, add only "description": "7" to the record's value wrapper. Submit the two complete inspection results to compare_web_captures as { "before": { "inspection": BEFORE }, "after": { "inspection": AFTER } }. Source reasoning predicts a storage modification, rather than equality. description is optional protocol metadata, not a change to value; the pinned Playwright protocol types model it that way, and the official Runtime protocol schema declares it optional.

Expected behavior

Equivalent complete IndexedDB primitive values and keys should retain equal content and identity fingerprints when only optional debugger descriptions differ. The documented stable content fingerprint contract concerns storage contents, and the comparison implementation's stated contract compares redacted content through complete fingerprints.

Impact and scope

The supported effect is a false storage-content difference for the valid protocol-response pair above; changing optional metadata on a key instead can change record identity. This affects evidence used to compare passive browser captures with storage fingerprints selected. Live-browser frequency, the browser versions that vary this metadata, and historical regression bounds are NOT_ENOUGH_INFO: none were observed in this source-only investigation. No security impact is alleged.

REA version

6.7.0; source revision 46111dd091f2ae01baab9eb119b53b9bd309a05b.

Runtime and platform

Runtime was not run for this finding. Static source inspection used the locked playwright-core 1.58.2 protocol types, where IndexedDB.DataEntry.value is a Runtime.RemoteObject and RemoteObject.description is optional. A real browser version/platform exhibiting both encodings is NOT_ENOUGH_INFO.

Target and artifact context

A stable page on an approved origin with one IndexedDB database, one object store, and one primitive numeric value; all other selected storage inventories are complete and empty.

Interface

MCP

Earliest failure stage

Capture or observation

Relevant output or evidence

Typed outcome or recovery expected

The affected record should have the same complete content fingerprint, and storage comparison should report no record modification for the stated metadata-only variation. A control changing the actual numeric value from 7 to 8 must still produce a content modification.

Analysis or suspected cause

Source-derived cause: the fingerprint boundary canonicalizes a protocol envelope rather than the represented primitive. The same wrapper-based projection is used for key, primary key, and value. This report concerns that one producing representation rule; it does not request broader IndexedDB support.

Additional context

NOT_ENOUGH_INFO for a last-known-good version or a live Chromium release pair producing the two valid encodings. No tests, browser sessions, or capture probes were run for this finding. Searched open and closed issues for IndexedDB/description, IndexedDB/fingerprint, IndexedDB/modified, fingerprint/description, and RemoteObject, plus open storage/metadata reports. Related closed #2554 concerns an omitted value incorrectly marked complete; this finding supplies a complete primitive and concerns presentation metadata entering its fingerprint.

Triage assessment

  • Impact level: P2
  • Assessment status: provisional
  • Impact basis: The complete static path supports a false content-change fact for valid protocol inputs, affecting passive storage comparison; live-browser frequency has not been established.
  • Workaround status: unverified
  • Workaround basis: Using observations with identical debugger metadata could avoid this trigger, but no practical way for an affected caller to control that metadata was verified.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6585 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction ## Observed behavior Source-only finding; runtime reproduction was not run. `inspect_web_page` hashes the entire CDP `Runtime.RemoteObject` wrapper when creating an IndexedDB record's content fingerprint. Two valid wrappers for the same stored primitive, `{ "type": "number", "value": 7 }` and `{ "type": "number", "value": 7, "description": "7" }`, are both accepted as complete but contribute different canonical hash inputs. With identical keys, `compare_web_captures` consequently classifies the record as modified even though its stored value is unchanged. Optional debugger presentation metadata also enters the key and primary-key identity hashes. ## Reproduction No browser or REA reproduction was executed for this finding. The following is a concrete source-derived trigger, suitable for a controlled CDP fixture; it is not a claimed live-browser transcript. Use the public `inspect_web_page` request `{ "cdp_endpoint": "http://127.0.0.1:9222", "allowed_origins": ["https://example.test"], "target_id": "page", "include_storage_keys": true, "include_storage_fingerprints": true }` with an admitted, stable page and otherwise complete unchanged observations. Both storage selections are true, satisfying the request refinement. For storage commands, return the following successful replies in both observations, except for the indicated `IndexedDB.requestData` value. ```json { "Storage.getUsageAndQuota": {"usage": 0, "quota": 1000}, "DOMStorage.getDOMStorageItems": {"entries": []}, "IndexedDB.requestDatabaseNames": {"databaseNames": ["db"]}, "CacheStorage.requestCacheNames": {"caches": []}, "Network.getCookies": {"cookies": []}, "IndexedDB.requestDatabase": { "databaseWithObjectStores": { "name": "db", "version": 1, "objectStores": [{"name": "records", "keyPath": {"type": "null"}, "autoIncrement": false, "indexes": []}] } }, "IndexedDB.requestData": { "objectStoreDataEntries": [{ "key": {"type": "number", "value": 1}, "primaryKey": {"type": "number", "value": 1}, "value": {"type": "number", "value": 7} }], "hasMore": false } } ``` The DOM storage reply applies to both local and session storage reads. In the second observation, add only `"description": "7"` to the record's `value` wrapper. Submit the two complete inspection results to `compare_web_captures` as `{ "before": { "inspection": BEFORE }, "after": { "inspection": AFTER } }`. Source reasoning predicts a storage modification, rather than equality. `description` is optional protocol metadata, not a change to `value`; the pinned Playwright protocol types model it that way, and the [official Runtime protocol schema](https://github.com/ChromeDevTools/devtools-protocol/blob/master/json/js_protocol.json) declares it optional. ## Expected behavior Equivalent complete IndexedDB primitive values and keys should retain equal content and identity fingerprints when only optional debugger descriptions differ. The [documented stable content fingerprint contract](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/docs/browser-observation.md#L372-L373) concerns storage contents, and the [comparison implementation's stated contract](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/domain/webCaptureDiff.ts#L43-L47) compares redacted content through complete fingerprints. ## Impact and scope The supported effect is a false storage-content difference for the valid protocol-response pair above; changing optional metadata on a key instead can change record identity. This affects evidence used to compare passive browser captures with storage fingerprints selected. Live-browser frequency, the browser versions that vary this metadata, and historical regression bounds are NOT_ENOUGH_INFO: none were observed in this source-only investigation. No security impact is alleged. ## REA version 6.7.0; source revision `46111dd091f2ae01baab9eb119b53b9bd309a05b`. ## Runtime and platform Runtime was not run for this finding. Static source inspection used the locked `playwright-core` 1.58.2 protocol types, where `IndexedDB.DataEntry.value` is a `Runtime.RemoteObject` and `RemoteObject.description` is optional. A real browser version/platform exhibiting both encodings is NOT_ENOUGH_INFO. ## Target and artifact context A stable page on an approved origin with one IndexedDB database, one object store, and one primitive numeric value; all other selected storage inventories are complete and empty. ## Interface MCP ## Earliest failure stage Capture or observation ## Relevant output or evidence - Evidence provenance: static. - Local verification: static-proof; runtime reproduction was not run. - Reproduction completeness: complete for the source-derived valid CDP-response trigger; live producer frequency is unknown. - Public reachability: [named inspection contract](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/contracts/browserToolContracts.ts#L170-L176), [selection and refinement](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/domain/browserObservation.ts#L194-L229), [page capture calls storage capture](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpPageCapture.ts#L154-L165), and [selected fingerprint capture](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpCaptureStorage.ts#L41-L109). - Guard coverage: the fixture supplies all enumerations, the matching database name, a valid null key path, Boolean `autoIncrement`, an empty indexes array, and `hasMore: false`. [Database/schema checks](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpCaptureStorageFingerprints.ts#L165-L261) accept these facts. [Remote-object completeness](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpCaptureStorageFingerprints.ts#L499-L527) accepts both finite numeric wrappers: neither has an object ID, preview, custom preview, or unserializable value. - Contrary source evidence: [record projection](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpCaptureStorageFingerprints.ts#L302-L321) passes the whole wrapper as `value`; [hashing and normalization](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/browser/CdpCaptureStorageFingerprints.ts#L428-L476) remove `objectId` and `customPreview` but retain `description`. Thus the canonical inputs are `{"type":"number","value":7}` versus `{"description":"7","type":"number","value":7}`. Exact digest outputs were not executed or measured. - Incorrect downstream classification: [complete fingerprint selection and value projection](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/domain/webCaptureDiff.ts#L967-L1002) retain this shared record identity; [unequal fingerprints become a modification](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/domain/webCaptureDiff.ts#L52-L62), and [a retained modification yields changed](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/domain/webCaptureDiff.ts#L72-L99). ## Typed outcome or recovery expected The affected record should have the same complete content fingerprint, and storage comparison should report no record modification for the stated metadata-only variation. A control changing the actual numeric value from 7 to 8 must still produce a content modification. ## Analysis or suspected cause Source-derived cause: the fingerprint boundary canonicalizes a protocol envelope rather than the represented primitive. The same wrapper-based projection is used for key, primary key, and value. This report concerns that one producing representation rule; it does not request broader IndexedDB support. ## Additional context NOT_ENOUGH_INFO for a last-known-good version or a live Chromium release pair producing the two valid encodings. No tests, browser sessions, or capture probes were run for this finding. Searched open and closed issues for IndexedDB/description, IndexedDB/fingerprint, IndexedDB/modified, fingerprint/description, and RemoteObject, plus open storage/metadata reports. Related closed #2554 concerns an omitted value incorrectly marked complete; this finding supplies a complete primitive and concerns presentation metadata entering its fingerprint. ## Triage assessment - Impact level: P2 - Assessment status: provisional - Impact basis: The complete static path supports a false content-change fact for valid protocol inputs, affecting passive storage comparison; live-browser frequency has not been established. - Workaround status: unverified - Workaround basis: Using observations with identical debugger metadata could avoid this trigger, but no practical way for an affected caller to control that metadata was verified.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3975
No description provided.