Add GamepadAPI, WebGL readPixels noise, auto-prune, import/export, badge

New fingerprint vectors:
- Gamepad API: getGamepads() returns empty (prevents controller fingerprinting)
- WebGL readPixels: seeded pixel noise on framebuffer reads

New features:
- Auto-prune: configurable automatic removal of inactive containers
- Import/export: backup and restore all settings from options page
- Toolbar badge: shows active container count
- CHANGELOG.md: version history

Bumped to v0.5.0 with 20 spoofed fingerprint vectors.
This commit is contained in:
sal
2026-03-04 21:08:45 -06:00
parent bbe40f87dc
commit d6dabb2646
9 changed files with 352 additions and 4 deletions

View File

@@ -675,6 +675,46 @@
patchWebGLExtensions("WebGLRenderingContext");
patchWebGLExtensions("WebGL2RenderingContext");
// --- readPixels noise ---
// Like canvas noise, adds tiny seeded perturbation to WebGL framebuffer reads
function patchWebGLReadPixels(protoName) {
const pageProto = pageWindow[protoName];
if (!pageProto) return;
const origProto = window[protoName];
if (!origProto) return;
const origReadPixels = origProto.prototype.readPixels;
exportFunction(function(x, y, width, height, format, type, pixels) {
origReadPixels.call(this, x, y, width, height, format, type, pixels);
if (pixels && pixels.length > 0 && CONFIG.canvasSeed) {
const rng = mulberry32(CONFIG.canvasSeed);
for (let i = 0; i < pixels.length; i += 4) {
if (rng() < 0.1) {
const ch = (rng() * 3) | 0;
const delta = rng() < 0.5 ? -1 : 1;
pixels[i + ch] = Math.max(0, Math.min(255, pixels[i + ch] + delta));
}
}
}
}, pageProto.prototype, { defineAs: "readPixels" });
}
patchWebGLReadPixels("WebGLRenderingContext");
patchWebGLReadPixels("WebGL2RenderingContext");
}
// =========================================================================
// GAMEPAD API PROTECTION
// =========================================================================
// navigator.getGamepads() reveals connected game controllers (count, IDs)
if (vectorEnabled("navigator") && pageWindow.navigator.getGamepads) {
try {
exportFunction(function() {
return cloneInto([null, null, null, null], pageWindow);
}, pageWindow.Navigator.prototype, { defineAs: "getGamepads" });
} catch(e) {}
}
// =========================================================================