Skip to content

fix(extension): stop leaking Object.getPropertyDescriptor/getPropertyNames on the page-world Object#1191

Draft
vringar wants to merge 1 commit into
masterfrom
harden/legacy-object-globals
Draft

fix(extension): stop leaking Object.getPropertyDescriptor/getPropertyNames on the page-world Object#1191
vringar wants to merge 1 commit into
masterfrom
harden/legacy-object-globals

Conversation

@vringar

@vringar vringar commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

The tell

Closes #1187 (quick win).

The legacy JavaScript instrument (Extension/src/lib/js-instruments.ts) assigned two non-standard helpers onto the page-world Object and never removed them:

Object.getPropertyDescriptor = function (subject, name) { ... };
Object.getPropertyNames = function (subject) { ... };

Because the instrument is injected via a <script> element and runs in the page's principal, these assignments stay visible to page scripts. A one-liner

typeof Object.getPropertyDescriptor === "function"

detects OpenWPM instrumentation even with empty settings — a config-independent tell, named as a leaked-globals detection vector in Krumnow, Jonker & Karsch (arXiv:2205.08890, §4.1).

The fix (zero capture cost)

Pure refactor: both helpers are now module-local functions inside getInstrumentJS instead of being assigned onto the global Object, and the two call sites (the property-descriptor lookup and the property-name enumeration) call the locals. The implementations are byte-for-byte unchanged; only their location and how they're referenced changed. The declare global augmentation of Object is removed accordingly.

No behavior or capture change.

Verification

  • grep -rn "Object.getPropertyDescriptor\|Object.getPropertyNames" Extension/src returns only the new module-local definitions — no Object.X = assignment and no Object.X( call remain.
  • The built content.js bundle contains no Object.getProperty* = assignment while still bundling both helper functions.
  • Extension build clean; ESLint reports no issues.
  • test/test_js_instrument.py::TestJSInstrument::test_instrument_object passes, confirming instrumentation capture is unchanged.

Follow-up

A browser-side regression test asserting the page-world Object no longer carries these properties would need new test-page/harness wiring; left as a follow-up rather than over-building here.

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.14%. Comparing base (315e667) to head (ff12f77).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1191   +/-   ##
=======================================
  Coverage   62.14%   62.14%           
=======================================
  Files          40       40           
  Lines        3918     3918           
=======================================
  Hits         2435     2435           
  Misses       1483     1483           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…Names on the page-world Object [#1187]

The legacy JS instrument assigned getPropertyDescriptor and
getPropertyNames onto the page-world Object and never removed them.
Because the instrument runs in the page's principal, these stay
visible to page scripts, so a one-liner like
  typeof Object.getPropertyDescriptor === "function"
detects OpenWPM instrumentation even with empty settings -- a
config-independent tell named as a leaked-global detection vector
in Krumnow et al. (arXiv:2205.08890).

Move both helpers to module-local functions and update their two
call sites to call the locals. Pure refactor: implementations are
unchanged and no capture behavior changes; only the page-world
Object assignment is removed.
@vringar vringar force-pushed the harden/legacy-object-globals branch from 8e53924 to ff12f77 Compare June 17, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden legacy JS instrument: it leaks a detectable footprint independent of configured APIs

1 participant