Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@webblackbox/protocol

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@webblackbox/protocol - npm Package Compare versions

Comparing version
0.4.5
to
0.5.0
+354
-37
dist/index.js

@@ -45,2 +45,3 @@ // src/blob.ts

"meta.config",
"privacy.violation",
"sys.debugger.attach",

@@ -117,2 +118,79 @@ "sys.debugger.detach",

// src/defaults.ts
var DEFAULT_REDACTION_PROFILE = {
redactHeaders: [
"authorization",
"cookie",
"set-cookie",
"proxy-authorization",
"x-api-key",
"x-auth-token",
"x-csrf-token",
"x-xsrf-token"
],
redactCookieNames: ["token", "session", "auth", "jwt", "refresh_token", "csrf", "xsrf"],
redactBodyPatterns: [
"password",
"token",
"secret",
"otp",
"credential",
"api_key",
"apikey",
"private_key",
"refresh_token"
],
blockedSelectors: [
".secret",
"[data-sensitive]",
"[data-webblackbox-redact]",
"input[type='password']",
"input[name*='token']",
"input[name*='secret']",
"input[autocomplete='cc-number']"
],
hashSensitiveValues: true
};
var DEFAULT_CAPTURE_POLICY = {
schemaVersion: 2,
mode: "private",
captureContext: "real-user",
consent: {
id: "default-private-consent",
provenance: "self-recording",
purpose: "debugging",
grantedAt: "1970-01-01T00:00:00.000Z"
},
unmaskPolicySource: "none",
scope: {
tabId: 0,
origin: "",
allowedOrigins: [],
deniedOrigins: [],
includeSubframes: false,
stopOnOriginChange: true,
excludedUrlPatterns: []
},
categories: {
actions: "metadata",
inputs: "length-only",
dom: "masked",
screenshots: "off",
console: "metadata",
network: "metadata",
storage: "counts-only",
indexedDb: "counts-only",
cookies: "count-only",
cdp: "off",
heapProfiles: "off"
},
redaction: DEFAULT_REDACTION_PROFILE,
encryption: {
localAtRest: "required",
archive: "required",
archiveKeyEnvelope: "passphrase"
},
retention: {
localTtlMs: 24 * 60 * 60 * 1e3
}
};
var DEFAULT_RECORDER_CONFIG = {

@@ -128,45 +206,13 @@ mode: "lite",

domFlushMs: 100,
screenshotIdleMs: 8e3,
screenshotIdleMs: 0,
snapshotIntervalMs: 2e4,
actionWindowMs: 1500,
bodyCaptureMaxBytes: 262144
bodyCaptureMaxBytes: 0
},
redaction: {
redactHeaders: [
"authorization",
"cookie",
"set-cookie",
"proxy-authorization",
"x-api-key",
"x-auth-token",
"x-csrf-token",
"x-xsrf-token"
],
redactCookieNames: ["token", "session", "auth", "jwt", "refresh_token", "csrf", "xsrf"],
redactBodyPatterns: [
"password",
"token",
"secret",
"otp",
"credential",
"api_key",
"apikey",
"private_key",
"refresh_token"
],
blockedSelectors: [
".secret",
"[data-sensitive]",
"[data-webblackbox-redact]",
"input[type='password']",
"input[name*='token']",
"input[name*='secret']",
"input[autocomplete='cc-number']"
],
hashSensitiveValues: true
},
redaction: DEFAULT_REDACTION_PROFILE,
capturePolicy: DEFAULT_CAPTURE_POLICY,
sitePolicies: []
};
var DEFAULT_EXPORT_POLICY = {
includeScreenshots: true,
includeScreenshots: false,
maxArchiveBytes: 100 * 1024 * 1024,

@@ -229,2 +275,17 @@ recentWindowMs: 20 * 60 * 1e3

}).strict();
var privacyClassificationSchema = z.object({
category: z.enum([
"actions",
"inputs",
"dom",
"screenshots",
"console",
"network",
"storage",
"performance",
"system"
]),
sensitivity: z.enum(["low", "medium", "high"]),
redacted: z.boolean()
}).strict();
var eventEnvelopeSchema = z.object({

@@ -245,2 +306,3 @@ v: z.literal(WEBBLACKBOX_PROTOCOL_VERSION),

ref: eventReferenceSchema.optional(),
privacy: privacyClassificationSchema.optional(),
data: z.unknown()

@@ -273,2 +335,58 @@ }).strict();

}).strict();
var captureConsentSchema = z.object({
id: z.string().min(1),
provenance: z.enum(["self-recording", "support-assisted", "enterprise-admin-policy"]),
purpose: z.enum(["debugging", "support", "qa", "incident-response", "other"]),
grantedBy: z.string().min(1).optional(),
grantedAt: z.string().datetime(),
expiresAt: z.string().datetime().optional(),
revocationRef: z.string().min(1).optional()
}).strict();
var captureScopeSchema = z.object({
tabId: z.number().int().nonnegative(),
origin: z.string(),
allowedOrigins: stringArray,
deniedOrigins: stringArray,
includeSubframes: z.boolean(),
stopOnOriginChange: z.boolean(),
excludedUrlPatterns: stringArray
}).strict();
var capturePolicySchema = z.object({
schemaVersion: z.literal(2),
mode: z.enum(["private", "debug", "lab"]),
captureContext: z.enum(["real-user", "synthetic", "local-debug"]),
captureContextEvidenceRef: z.string().min(1).optional(),
consent: captureConsentSchema,
unmaskPolicySource: z.enum(["none", "extension-managed", "enterprise", "signed-site-owner"]),
scope: captureScopeSchema,
categories: z.object({
actions: z.enum(["metadata", "masked", "allow"]),
inputs: z.enum(["none", "length-only", "masked", "allow"]),
dom: z.enum(["off", "wireframe", "masked", "allow"]),
screenshots: z.enum(["off", "masked", "allow"]),
console: z.enum(["off", "metadata", "sanitized", "allow"]),
network: z.enum(["metadata", "headers-allowlist", "body-allowlist"]),
storage: z.enum(["off", "counts-only", "names-only", "lengths-only", "allow"]),
indexedDb: z.enum(["off", "counts-only", "names-only"]),
cookies: z.enum(["off", "count-only", "names-only"]),
cdp: z.enum(["off", "safe-subset", "full"]),
heapProfiles: z.enum(["off", "lab-only"])
}).strict(),
redaction: redactionProfileSchema,
encryption: z.object({
localAtRest: z.literal("required"),
archive: z.enum(["required", "synthetic-local-debug-exempt", "explicit-low-risk-override"]),
archiveKeyEnvelope: z.enum([
"passphrase",
"enterprise-managed",
"client-side-share-fragment",
"none"
]),
overrideReasonRef: z.string().min(1).optional()
}).strict(),
retention: z.object({
localTtlMs: z.number().int().positive(),
shareTtlMs: z.number().int().positive().optional()
}).strict()
}).strict();
var recorderConfigSchema = z.object({

@@ -282,2 +400,3 @@ mode: captureModeSchema,

redaction: redactionProfileSchema,
capturePolicy: capturePolicySchema.optional(),
sitePolicies: z.array(siteCapturePolicySchema)

@@ -341,2 +460,73 @@ }).strict();

}).strict();
var privacyScannerFindingSchema = z.object({
kind: z.enum([
"jwt",
"bearer-token",
"api-key",
"oauth-code",
"session-cookie",
"email",
"phone",
"credit-card",
"ssn",
"private-key",
"long-secret"
]),
severity: z.literal("high"),
path: z.string().min(1),
matchCount: z.number().int().positive(),
sampleSha256: z.string().regex(/^[a-f0-9]{64}$/)
}).strict();
var privacyScannerResultSchema = z.object({
scannedAt: z.string().datetime(),
preEncryption: z.boolean(),
status: z.enum(["passed", "blocked"]),
findings: z.array(privacyScannerFindingSchema)
}).strict();
var privacyManifestCategorySummarySchema = z.object({
category: privacyClassificationSchema.shape.category,
events: z.number().int().nonnegative(),
low: z.number().int().nonnegative(),
medium: z.number().int().nonnegative(),
high: z.number().int().nonnegative(),
redacted: z.number().int().nonnegative(),
unredacted: z.number().int().nonnegative()
}).strict();
var privacyManifestSchema = z.object({
schemaVersion: z.literal(1),
generatedAt: z.string().datetime(),
effectivePolicy: capturePolicySchema.optional(),
consent: captureConsentSchema.optional(),
transfer: z.object({
destination: z.enum([
"local-download",
"public-cloud-share",
"support-upload",
"enterprise-upload"
]),
archiveKeyEnvelope: z.enum([
"passphrase",
"enterprise-managed",
"client-side-share-fragment",
"none"
]),
encrypted: z.boolean(),
includeScreenshots: z.boolean(),
maxArchiveBytes: z.number().int().positive().nullable(),
recentWindowMs: z.number().int().positive().nullable(),
shareEligible: z.boolean(),
computedAt: z.string().datetime()
}).strict().optional(),
categories: z.array(privacyManifestCategorySummarySchema),
scanner: privacyScannerResultSchema,
encryption: z.object({
archive: z.enum(["encrypted", "plaintext"]),
algorithm: z.literal("AES-GCM").optional()
}).strict(),
totals: z.object({
events: z.number().int().nonnegative(),
blobs: z.number().int().nonnegative(),
privacyViolations: z.number().int().nonnegative()
}).strict()
}).strict();
var exportManifestSchema = z.object({

@@ -608,7 +798,124 @@ protocolVersion: z.literal(WEBBLACKBOX_PROTOCOL_VERSION),

}
// src/privacy.ts
var ABSOLUTE_URL_PATTERN = /^[a-z][a-z\d+.-]*:/i;
var UUID_SEGMENT_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
var HEX_SEGMENT_PATTERN = /^[0-9a-f]{8,}$/i;
var BASE64URL_SEGMENT_PATTERN = /^[a-z\d_-]{16,}$/i;
var EMAIL_LIKE_PATTERN = /^[^\s/@]+@[^\s/@]+\.[^\s/@]+$/;
var SECRET_PREFIX_SEGMENT_PATTERN = /^(?:sk|pk)_(?:live|test)_[a-z\d_-]{8,}$|^gh[pousr]_[a-z\d_]{8,}$|^github_pat_[a-z\d_]{8,}$/i;
var SENSITIVE_SEGMENT_WORDS = [
"token",
"secret",
"session",
"jwt",
"oauth",
"code",
"key",
"reset",
"invite"
];
function sanitizeUrlForPrivacy(value) {
const trimmed = value.trim();
if (!trimmed) {
return trimmed;
}
if (trimmed.startsWith("#")) {
return "";
}
if (ABSOLUTE_URL_PATTERN.test(trimmed)) {
return sanitizeAbsoluteUrl(trimmed);
}
return sanitizeRelativeUrl(trimmed);
}
function routeTemplatePath(pathname) {
const hasLeadingSlash = pathname.startsWith("/");
const hasTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
const segments = pathname.split("/").map((segment) => templatePathSegment(segment));
let output = segments.join("/");
if (hasLeadingSlash && !output.startsWith("/")) {
output = `/${output}`;
}
if (hasTrailingSlash && !output.endsWith("/")) {
output = `${output}/`;
}
return output || (hasLeadingSlash ? "/" : "");
}
function sanitizeAbsoluteUrl(value) {
let url;
try {
url = new URL(value);
} catch {
return sanitizeRelativeUrl(value);
}
if (url.protocol === "http:" || url.protocol === "https:") {
return `${url.origin}${routeTemplatePath(url.pathname)}`;
}
if (url.protocol === "about:") {
return `${url.protocol}${routeTemplatePath(url.pathname)}`;
}
if (url.protocol === "chrome-extension:") {
return `${url.protocol}${routeTemplatePath(url.pathname)}`;
}
if (url.protocol === "file:") {
return `${url.protocol}[redacted]`;
}
return `${url.protocol}[redacted]`;
}
function sanitizeRelativeUrl(value) {
const hashIndex = value.indexOf("#");
const withoutHash = hashIndex >= 0 ? value.slice(0, hashIndex) : value;
const queryIndex = withoutHash.indexOf("?");
const withoutQuery = queryIndex >= 0 ? withoutHash.slice(0, queryIndex) : withoutHash;
if (!withoutQuery) {
return "";
}
return routeTemplatePath(withoutQuery);
}
function templatePathSegment(segment) {
if (!segment) {
return segment;
}
const decoded = safeDecodeURIComponent(segment);
const normalized = decoded.trim().toLowerCase();
if (!normalized) {
return segment;
}
if (/^\d+$/.test(normalized)) {
return ":id";
}
if (EMAIL_LIKE_PATTERN.test(normalized)) {
return ":id";
}
if (UUID_SEGMENT_PATTERN.test(normalized) || HEX_SEGMENT_PATTERN.test(normalized)) {
return ":id";
}
if (SECRET_PREFIX_SEGMENT_PATTERN.test(normalized)) {
return ":token";
}
if (SENSITIVE_SEGMENT_WORDS.some((word) => normalized !== word && normalized.includes(word))) {
return ":token";
}
if (BASE64URL_SEGMENT_PATTERN.test(normalized) && /[a-z]/i.test(normalized) && /\d/.test(normalized)) {
return ":token";
}
if (normalized.length >= 6 && /[a-z]/i.test(normalized) && /\d/.test(normalized)) {
return ":id";
}
return segment;
}
function safeDecodeURIComponent(value) {
try {
return decodeURIComponent(value);
} catch {
return value;
}
}
export {
CAPTURE_MODES,
CHUNK_CODECS,
DEFAULT_CAPTURE_POLICY,
DEFAULT_EXPORT_POLICY,
DEFAULT_RECORDER_CONFIG,
DEFAULT_REDACTION_PROFILE,
EVENT_LEVELS,

@@ -623,3 +930,6 @@ EventIdFactory,

buildIndexMessageSchema,
captureConsentSchema,
captureModeSchema,
capturePolicySchema,
captureScopeSchema,
chunkCodecSchema,

@@ -652,2 +962,7 @@ chunkPutMessageSchema,

networkBodyCaptureRuleSchema,
privacyClassificationSchema,
privacyManifestCategorySummarySchema,
privacyManifestSchema,
privacyScannerFindingSchema,
privacyScannerResultSchema,
recorderConfigSchema,

@@ -657,3 +972,5 @@ redactionProfileSchema,

requestIndexSchema,
routeTemplatePath,
samplingProfileSchema,
sanitizeUrlForPrivacy,
sessionMetadataSchema,

@@ -660,0 +977,0 @@ siteCapturePolicySchema,

+1
-1
{
"name": "@webblackbox/protocol",
"description": "Shared event types, schemas, IDs, and configuration defaults for the WebBlackbox ecosystem.",
"version": "0.4.5",
"version": "0.5.0",
"type": "module",

@@ -6,0 +6,0 @@ "main": "./dist/index.js",

@@ -249,4 +249,4 @@ <p align="center">

// - mousemoveHz: 20, scrollHz: 15
// - screenshotIdleMs: 8000
// - bodyCaptureMaxBytes: 262144 (256 KiB base profile)
// - screenshotIdleMs: 0 (screenshots disabled unless explicitly enabled)
// - bodyCaptureMaxBytes: 0 (response bodies disabled unless explicitly enabled)
// - Redacts: authorization, cookie, set-cookie, proxy auth, API key, auth token, CSRF/XSRF headers

@@ -257,3 +257,3 @@ // - Redacts cookie names such as token, session, auth, jwt, refresh_token, csrf, xsrf

// Export policy defaults:
// - includeScreenshots: true
// - includeScreenshots: false
// - maxArchiveBytes: 100 * 1024 * 1024

@@ -260,0 +260,0 @@ // - recentWindowMs: 20 * 60 * 1000

Sorry, the diff of this file is too big to display