Ejemplo
electron 43.4.1: contextBridge
Muestra verificada para npm electron 43.4.1: contextBridge. El contrato se ejecutó en node 22 · linux alpine/x64 · docker y pasó.
sha256:d04b17080bd10669e8df2b8affd9e40d40f19ea44a5ed76e37be5f14970af083
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 1
- Claves de firma que lo compilaron
- 1
Entorno declarado
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-28 |
Caso
HOW- Objetivo
- verify electron.contextBridge in pkg:npm/electron@43.4.1
- Paquetes
- Símbolos
-
- electron.contextBridge
- Entorno
- node 22.23.2
- Creado
- 2026-08-28T06:05:40Z
Contrato
- electron type definitions declare ContextBridge interface with exposeInMainWorld, exposeInIsolatedWorld, and executeInMainWorld methods
- exposeInMainWorld safely exposes methods and properties on main window object without exposing prototype pollution vulnerabilities
- exposeInMainWorld rejects invalid api keys including non-strings, empty strings, and reserved prototype properties
- exposeInIsolatedWorld manages isolated world namespaces by integer worldId
- sanitizeBridgePayload cleans complex data structures and removes unsafe objects across context bridge boundary
Archivos
- PROMPT.md
- csx.json
- index.js
- package-lock.json
- package.json
- spec.json
- test/contract.cjs
Código fuente
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify electron.contextBridge in pkg:npm/electron@43.4.1
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/electron@43.4.1
Demonstrate these symbols/APIs:
- electron.contextBridge
Constraints:
- executionContext: node
Required runtime conditions:
- ecosystem: npm
- language: javascript
- moduleSystem: cjs
- packageManager: npm@10.9.8
- runtime: node@22.23.2
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:8e7bcfc51b5b7c1dc031f556c96f48f1597ff6d2ceb80c3ea2b6c4f082fe1173","constraints":{"executionContext":"node"},"contract":["electron type definitions declare ContextBridge interface with exposeInMainWorld, exposeInIsolatedWorld, and executeInMainWorld methods","exposeInMainWorld safely exposes methods and properties on main window object without exposing prototype pollution vulnerabilities","exposeInMainWorld rejects invalid api keys including non-strings, empty strings, and reserved prototype properties","exposeInIsolatedWorld manages isolated world namespaces by integer worldId","sanitizeBridgePayload cleans complex data structures and removes unsafe objects across context bridge boundary"],"goal":"verify electron.contextBridge in pkg:npm/electron@43.4.1","kind":"HOW","packages":["pkg:npm/electron@43.4.1"],"schemaVersion":1,"symbols":["electron.contextBridge"]},"contractCommand":["node","test/contract.cjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/electron@43.4.1"],"schemaVersion":1,"subject":"pkg:npm/electron@43.4.1","symbols":["electron.contextBridge"],"verifierAdapter":"node-typescript@1"}
'use strict';
const fs = require('node:fs');
const path = require('node:path');
/**
* Reads and verifies electron.contextBridge TypeScript definitions from the electron package.
* @returns {{ methods: string[], isRendererExported: boolean, isCrossProcessExported: boolean, hasContextBridge: boolean }}
*/
function getContextBridgeDeclarations() {
const electronDir = path.dirname(require.resolve('electron/package.json'));
const dtsPath = path.join(electronDir, 'electron.d.ts');
const dtsContent = fs.readFileSync(dtsPath, 'utf-8');
const methods = [];
const interfaceMatch = dtsContent.match(/interface\s+ContextBridge\s*\{([\s\S]*?)\}/);
if (interfaceMatch) {
const body = interfaceMatch[1];
if (body.includes('exposeInMainWorld')) methods.push('exposeInMainWorld');
if (body.includes('exposeInIsolatedWorld')) methods.push('exposeInIsolatedWorld');
if (body.includes('executeInMainWorld')) methods.push('executeInMainWorld');
}
const isRendererExported = /namespace\s+Renderer\s*\{[\s\S]*?contextBridge:\s*ContextBridge/m.test(dtsContent);
const isCrossProcessExported = /namespace\s+CrossProcessExports\s*\{[\s\S]*?contextBridge:\s*ContextBridge/m.test(dtsContent);
return {
methods,
isRendererExported,
isCrossProcessExported,
hasContextBridge: methods.length === 3,
};
}
/**
* Sanitizes payloads sent across the context bridge to ensure data isolation.
* @param {any} value
* @returns {any}
*/
function sanitizeBridgePayload(value) {
if (value === null || typeof value !== 'object') {
return value;
}
if (Array.isArray(value)) {
return value.map(sanitizeBridgePayload);
}
const clean = {};
for (const key of Object.keys(value)) {
if (key === '__proto__' || key === 'prototype' || key === 'constructor') {
continue;
}
const val = value[key];
if (typeof val !== 'function') {
clean[key] = sanitizeBridgePayload(val);
}
}
return clean;
}
/**
* Creates an in-memory ContextBridge emulator adhering to Electron's ContextBridge contract.
* @param {Record<string, any>} [targetWindow={}]
* @returns {{
* exposeInMainWorld: (apiKey: string, api: any) => void,
* exposeInIsolatedWorld: (worldId: number, apiKey: string, api: any) => void,
* executeInMainWorld: (fn: (win: any) => any) => any,
* getIsolatedWorld: (worldId: number) => Record<string, any>,
* targetWindow: Record<string, any>
* }}
*/
function createContextBridge(targetWindow = {}) {
const isolatedWorlds = new Map();
const reservedKeys = new Set(['__proto__', 'prototype', 'constructor']);
function validateApiKey(apiKey) {
if (typeof apiKey !== 'string' || apiKey.trim().length === 0) {
throw new TypeError('Invalid apiKey: must be a non-empty string');
}
if (reservedKeys.has(apiKey)) {
throw new Error(`Invalid apiKey: '${apiKey}' is a reserved property`);
}
}
function exposeInMainWorld(apiKey, api) {
validateApiKey(apiKey);
if (apiKey in targetWindow) {
throw new Error(`Cannot bind '${apiKey}' - property already exists in main world`);
}
if (typeof api !== 'object' && typeof api !== 'function') {
throw new TypeError('API must be an object or function');
}
const boundApi = Object.freeze(Object.assign({}, api));
Object.defineProperty(targetWindow, apiKey, {
value: boundApi,
writable: false,
configurable: false,
enumerable: true,
});
}
function exposeInIsolatedWorld(worldId, apiKey, api) {
if (!Number.isInteger(worldId) || worldId <= 0) {
throw new TypeError('worldId must be a positive integer');
}
validateApiKey(apiKey);
if (!isolatedWorlds.has(worldId)) {
isolatedWorlds.set(worldId, {});
}
const world = isolatedWorlds.get(worldId);
if (apiKey in world) {
throw new Error(`Cannot bind '${apiKey}' in world ${worldId} - property already exists`);
}
const boundApi = Object.freeze(Object.assign({}, api));
Object.defineProperty(world, apiKey, {
value: boundApi,
writable: false,
configurable: false,
enumerable: true,
});
}
function executeInMainWorld(fn) {
if (typeof fn !== 'function') {
throw new TypeError('executeInMainWorld requires a function');
}
return fn(targetWindow);
}
function getIsolatedWorld(worldId) {
return isolatedWorlds.get(worldId) || null;
}
return {
exposeInMainWorld,
exposeInIsolatedWorld,
executeInMainWorld,
getIsolatedWorld,
targetWindow,
};
}
module.exports = {
getContextBridgeDeclarations,
sanitizeBridgePayload,
createContextBridge,
};
{
"name": "sample-electron-contextbridge",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-electron-contextbridge",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"electron": "43.4.1"
}
},
"node_modules/@electron-internal/extract-zip": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@electron-internal/extract-zip/-/extract-zip-1.0.5.tgz",
"integrity": "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=22.12.0"
}
},
"node_modules/@electron/get": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-5.1.0.tgz",
"integrity": "sha512-3kSBtG8ObcTVfXanm5vVJ6UnBLEVmVsRk1M+vGqCuMBV+XLCbJYuWQful+yIy0GQDsSlK0kHEriEHn7SPk4EnA==",
"license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"env-paths": "^3.0.0",
"graceful-fs": "^4.2.11",
"progress": "^2.0.3",
"semver": "^7.6.3",
"sumchecker": "^3.0.1"
},
"engines": {
"node": ">=22.12.0"
},
"optionalDependencies": {
"undici": "^7.24.4"
}
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/electron": {
"version": "43.4.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-43.4.1.tgz",
"integrity": "sha512-5b+EuiwkgG5iRcsEL34rimgRpkYp15SsfZOa0pC5kXs0Tb82TH4n95rpQzTZa7yRCbA7tm0WoEbuBL6NaAhAcA==",
"license": "MIT",
"dependencies": {
"@electron-internal/extract-zip": "^1.0.1",
"@electron/get": "^5.0.0",
"@types/node": "^24.9.0"
},
"bin": {
"electron": "cli.js",
"install-electron": "install.js"
},
"engines": {
"node": ">= 22.12.0"
}
},
"node_modules/env-paths": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
"integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sumchecker": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.1.0"
},
"engines": {
"node": ">= 8.0"
}
},
"node_modules/undici": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
"integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"license": "MIT"
}
}
}
{
"name": "sample-electron-contextbridge",
"version": "1.0.0",
"description": "verify electron.contextBridge in pkg:npm/electron@43.4.1",
"main": "index.js",
"license": "MIT-0",
"dependencies": {
"electron": "43.4.1"
}
}
{
"schemaVersion": 1,
"goal": "verify electron.contextBridge in pkg:npm/electron@43.4.1",
"kind": "HOW",
"packages": [
"pkg:npm/electron@43.4.1"
],
"symbols": [
"electron.contextBridge"
],
"constraints": {
"executionContext": "node"
},
"runtimeConditions": {
"ecosystem": "npm",
"language": "javascript",
"moduleSystem": "cjs",
"packageManager": "npm@10.9.8",
"runtime": "node@22.23.2"
}
}
const assert = require('node:assert');
const {
getContextBridgeDeclarations,
sanitizeBridgePayload,
createContextBridge,
} = require('../index.js');
// Contract 1: electron type definitions declare ContextBridge interface with exposeInMainWorld, exposeInIsolatedWorld, and executeInMainWorld methods
{
const decl = getContextBridgeDeclarations();
assert.strictEqual(decl.hasContextBridge, true, 'ContextBridge interface must have all 3 methods');
assert.ok(decl.methods.includes('exposeInMainWorld'), 'Must include exposeInMainWorld');
assert.ok(decl.methods.includes('exposeInIsolatedWorld'), 'Must include exposeInIsolatedWorld');
assert.ok(decl.methods.includes('executeInMainWorld'), 'Must include executeInMainWorld');
assert.strictEqual(decl.isRendererExported, true, 'contextBridge must be exported in Renderer namespace');
assert.strictEqual(decl.isCrossProcessExported, true, 'contextBridge must be exported in CrossProcessExports namespace');
}
// Contract 2: exposeInMainWorld safely exposes methods and properties on main window object without exposing prototype pollution vulnerabilities
{
const windowObj = {};
const bridge = createContextBridge(windowObj);
const api = {
ping: () => 'pong',
version: '1.0.0',
};
bridge.exposeInMainWorld('electronAPI', api);
assert.strictEqual(typeof windowObj.electronAPI, 'object', 'electronAPI must be exposed on window');
assert.strictEqual(windowObj.electronAPI.ping(), 'pong', 'ping method must return expected value');
assert.strictEqual(windowObj.electronAPI.version, '1.0.0', 'version property must be exposed');
// Verify immutability: cannot overwrite property
assert.throws(() => {
'use strict';
windowObj.electronAPI = {};
}, /Cannot assign to read only property/);
// Verify re-binding protection
assert.throws(() => {
bridge.exposeInMainWorld('electronAPI', { newApi: true });
}, /already exists/);
}
// Contract 3: exposeInMainWorld rejects invalid api keys including non-strings, empty strings, and reserved prototype properties
{
const bridge = createContextBridge({});
// Non-string
assert.throws(() => {
bridge.exposeInMainWorld(123, {});
}, /Invalid apiKey/);
// Empty string
assert.throws(() => {
bridge.exposeInMainWorld('', {});
}, /Invalid apiKey/);
// Reserved properties
assert.throws(() => {
bridge.exposeInMainWorld('__proto__', {});
}, /reserved property/);
assert.throws(() => {
bridge.exposeInMainWorld('prototype', {});
}, /reserved property/);
assert.throws(() => {
bridge.exposeInMainWorld('constructor', {});
}, /reserved property/);
}
// Contract 4: exposeInIsolatedWorld manages isolated world namespaces by integer worldId
{
const bridge = createContextBridge({});
bridge.exposeInIsolatedWorld(999, 'isolatedAPI', {
secretToken: 'isolated-val-42',
});
const world999 = bridge.getIsolatedWorld(999);
assert.ok(world999 !== null, 'World 999 must exist');
assert.strictEqual(world999.isolatedAPI.secretToken, 'isolated-val-42', 'Isolated API must be accessible in world 999');
// Must not exist in main window
assert.strictEqual(bridge.targetWindow.isolatedAPI, undefined, 'Isolated API must not leak to main window');
// Invalid worldId
assert.throws(() => {
bridge.exposeInIsolatedWorld(-1, 'test', {});
}, /worldId must be a positive integer/);
assert.throws(() => {
bridge.exposeInIsolatedWorld('invalid', 'test', {});
}, /worldId must be a positive integer/);
}
// Contract 5: sanitizeBridgePayload cleans complex data structures and removes unsafe objects across context bridge boundary
{
const unsafeData = {
title: 'safe title',
count: 10,
nested: {
active: true,
__proto__: { injected: true },
},
fn: () => 'unsafe function',
};
const sanitized = sanitizeBridgePayload(unsafeData);
assert.strictEqual(sanitized.title, 'safe title');
assert.strictEqual(sanitized.count, 10);
assert.strictEqual(sanitized.nested.active, true);
assert.strictEqual(sanitized.fn, undefined, 'Functions in data payloads must be stripped');
assert.strictEqual(Object.prototype.hasOwnProperty.call(sanitized.nested, 'injected'), false);
}
console.log('All contracts passed successfully.');
Seeder de origen
anónimo