@stackone/redaction 1.13.0 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/edge/index.d.mts +3 -1
- package/dist/edge/index.mjs +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +3 -1
- package/dist/node/index.d.mts +3 -1
- package/dist/node/index.mjs +1 -1
- package/package.json +1 -1
package/dist/edge/index.d.mts
CHANGED
|
@@ -2,6 +2,8 @@ import { t as __name } from "./chunk-BhWHdk3m.mjs";
|
|
|
2
2
|
import { ILogger } from "@stackone/logger";
|
|
3
3
|
|
|
4
4
|
//#region src/shared/index.d.ts
|
|
5
|
+
declare const KEYS_TO_REDACT: string[];
|
|
6
|
+
declare const PATHS_TO_REDACT: string[];
|
|
5
7
|
declare const REDACT_CENSOR = "**redacted**";
|
|
6
8
|
declare enum CensorType {
|
|
7
9
|
FULL = "FULL",
|
|
@@ -17,4 +19,4 @@ declare const safeClone: <T>(value: T) => T;
|
|
|
17
19
|
declare const redactObject: <T>(obj: T, censorType?: CensorType) => T;
|
|
18
20
|
declare const I_AM_EDGE = true;
|
|
19
21
|
//#endregion
|
|
20
|
-
export { CensorType, I_AM_EDGE, REDACT_CENSOR, redactFields, redactObject, redactPath, redactUrl, safeClone, splitPath };
|
|
22
|
+
export { CensorType, I_AM_EDGE, KEYS_TO_REDACT, PATHS_TO_REDACT, REDACT_CENSOR, redactFields, redactObject, redactPath, redactUrl, safeClone, splitPath };
|
package/dist/edge/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./chunk-BhWHdk3m.mjs";import{isMissing as e}from"@stackone/utils";const t=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`],n=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...t],r=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>t.map(t=>`${e}[${JSON.stringify(t)}]`))],i=`**redacted**`;let a=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>i,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?i:`${i}${e.slice(-5)}`:i,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),o=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||o.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},s={FULL:censorFn,PARTIAL:partialCensorFn},c=getKeysToRedact(n),l=[...getPathsToRedact(r),...Array.from(c).map(asValidPath)],redactUrl=(t,n=`FULL`,r)=>{if(!e(t))try{let e=new URL(t),r=[...e.searchParams].reduce((e,[t,r])=>(e.set(t,
|
|
1
|
+
import"./chunk-BhWHdk3m.mjs";import{isMissing as e}from"@stackone/utils";const t=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`,`klaviyo-api-key`,`x-sn-apikey`],n=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...t],r=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>t.map(t=>`${e}[${JSON.stringify(t)}]`))],i=`**redacted**`;let a=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>i,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?i:`${i}${e.slice(-5)}`:i,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),o=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||o.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},s={FULL:censorFn,PARTIAL:partialCensorFn},c=getKeysToRedact(n),l=new Set(Array.from(c,e=>e.toLowerCase())),matchesRedactedKey=e=>{let t=e.toLowerCase();return l.has(t)?!0:t.includes(`[`)?t.split(/[\[\]]/).some(e=>e&&l.has(e)):!1},u=[...getPathsToRedact(r),...Array.from(c).map(asValidPath)],redactUrl=(t,n=`FULL`,r)=>{if(!e(t))try{let e=new URL(t),r=[...e.searchParams].reduce((e,[t,r])=>(e.set(t,matchesRedactedKey(t)?s[n](r):r),e),new URLSearchParams);return`${e.origin}${e.pathname}${r.toString()?`?`+r:``}${e.hash}`}catch(e){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:t,error:e},category:`redactUrl`}),typeof t==`string`?t:t?.toString()}},redactPath=(t,n=`FULL`,r)=>{if(!e(t))try{let[e,r]=t.split(`?`);return r?`${e}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,matchesRedactedKey(t)?s[n](r):r),e),new URLSearchParams)}`:t}catch(e){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:t,error:e},category:`redactPath`}),t}},redactNode=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(i.has(e))return`**circular**`;if(r>64)return`**max-depth**`;if(Array.isArray(e)){if(!n)return[...e];i.add(e);let a=e.map(e=>typeof e==`object`&&e?redactNode(e,t,n,r+1,i):e);return i.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return`**unreadable**`}if(!a)return e;i.add(e);let o=Object.fromEntries(Object.entries(e).map(([e,a])=>matchesRedactedKey(e)?[e,s[t](a)]:n&&typeof a==`object`&&a?[e,redactNode(a,t,n,r+1,i)]:[e,a]));return i.delete(e),o},redactFields=(e,t=`FULL`,n=!1)=>redactNode(e,t,n,0,new WeakSet);let d;const getRedactors=()=>(e(d)&&(d={FULL:edgeRedact({paths:u,serialize:!1,censor:s.FULL}),PARTIAL:edgeRedact({paths:u,serialize:!1,censor:s.PARTIAL})}),d),splitPath=e=>e.replace(/\[["']?([^[\]"']*)["']?\]/g,`.$1`).split(`.`).filter(Boolean),fallbackCensor=()=>`***`,edgeRedact=e=>{let t=(e.paths??[]).map(splitPath),n=typeof e.censor==`function`?e.censor:fallbackCensor,r=!!e.serialize,redact=e=>{if(typeof e!=`object`||!e)return r?String(e):e;for(let r of t){let t=e;for(let e=0;e<r.length-1&&t&&typeof t==`object`;e++)t=t[r[e]];let i=r[r.length-1];t&&Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=n(t[i]))}return r?JSON.stringify(e):e};return redact.restore=()=>{},redact},safeClone=e=>{let t=globalThis.structuredClone;return typeof t==`function`?t(e):JSON.parse(JSON.stringify(e))},redactObject=(e,t=`FULL`)=>{if(typeof e!=`object`||!e)return e;let n=safeClone(e);return getRedactors()[t](n)},f=!0;export{a as CensorType,f as I_AM_EDGE,n as KEYS_TO_REDACT,r as PATHS_TO_REDACT,i as REDACT_CENSOR,redactFields,redactObject,redactPath,redactUrl,safeClone,splitPath};
|
package/dist/node/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config-BPwtMZw7.cjs");let t=require("@stackone/utils"),n=require("fast-redact");n=e.p(n);const r=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`],i=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...r],a=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>r.map(t=>`${e}[${JSON.stringify(t)}]`))],o=`**redacted**`,s=`**circular**`,c=`**max-depth**`,l=`**unreadable**`;let u=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>o,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?o:`${o}${e.slice(-5)}`:o,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),d=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||d.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},f={FULL:censorFn,PARTIAL:partialCensorFn},p=getKeysToRedact(i),m=[...getPathsToRedact(a),...Array.from(p).map(asValidPath)],redactUrl=(e,n=`FULL`,r)=>{if(!(0,t.isMissing)(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,p.has(t)?f[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,n=`FULL`,r)=>{if(!(0,t.isMissing)(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,p.has(t)?f[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactNode=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(i.has(e))return s;if(r>64)return c;if(Array.isArray(e)){if(!n)return[...e];i.add(e);let a=e.map(e=>typeof e==`object`&&e?redactNode(e,t,n,r+1,i):e);return i.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return l}if(!a)return e;i.add(e);let o=Object.fromEntries(Object.entries(e).map(([e,a])=>p.has(e)?[e,f[t](a)]:n&&typeof a==`object`&&a?[e,redactNode(a,t,n,r+1,i)]:[e,a]));return i.delete(e),o},redactFields=(e,t=`FULL`,n=!1)=>redactNode(e,t,n,0,new WeakSet),defineOwn=(e,t,n)=>{Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0})},walk=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(n.has(e))return s;if(t>64)return c;if(Array.isArray(e)){n.add(e);let a=Array(e.length);return e.forEach((e,o)=>{typeof e==`string`?(a[o]=e,r.push(e),i.push(e=>{a[o]=e})):a[o]=walk(e,t+1,n,r,i)}),n.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return l}if(!a)return e;n.add(e);let o={};for(let[a,s]of Object.entries(e))typeof s==`string`?(defineOwn(o,a,s),r.push(s),i.push(e=>{defineOwn(o,a,e)})):defineOwn(o,a,walk(s,t+1,n,r,i));return n.delete(e),o};async function scrubObjectAsync(e,t){if(typeof e==`string`)return(await t.scrubAsync(e)).scrubbed;let n=[],r=[],i=walk(e,0,new WeakSet,n,r);return n.length>0&&(await t.scrubManyAsync(n)).forEach((e,t)=>r[t](e.scrubbed)),i}function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,r=e.t){let i=e.a(t,r.skipPatterns),a=[],o=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,s=new RegExp(r.candidatePattern.source,o),c;for(;(c=s.exec(t))!==null;){let t=c[0];t.length<r.minLength||e.o(c.index,c.index+t.length,i)||shannonEntropy(t)>=r.threshold&&a.push({start:c.index,end:c.index+t.length,original:t,replacement:n,source:`entropy`})}for(let o of r.piiPatterns??[]){let r=new RegExp(o.source,o.flags.includes(`g`)?o.flags:`${o.flags}g`),s;for(;(s=r.exec(t))!==null;){let t=s.index,r=t+s[0].length;e.o(t,r,i)||a.push({start:t,end:r,original:s[0],replacement:n,source:`entropy`})}}let l=e.s(a);return{scrubbed:e.i(t,l),redactions:l}}var PiiRedaction=class{constructor(t){this.tier2=null,this.tier2LoadPromise=null,this.config=e.r(t),this.enableTier2=t?.enableTier2??!1,this.logger=t?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(t){let n=performance.now();if(!this.enableTier2)return this.scrub(t);let r=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let e=await this.tier2.detectSecrets(t);for(let t of e)i.push({start:t.start,end:t.end,original:t.text,replacement:this.config.redactionToken,source:`model`,label:t.label});r=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(t,this.config.redactionToken,this.config.entropy);i.push(...a);let o=e.s(i);return{scrubbed:e.i(t,o),redactions:o,tier:r?`model+entropy`:`entropy`,modelAvailable:r,latencyMs:performance.now()-n}}async scrubManyAsync(t){if(!this.enableTier2)return t.map(e=>this.scrub(e));let n=null;try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);n=await this.tier2.detectSecretsBatch(t)}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 batch detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}return t.map((t,r)=>{let i=performance.now(),a=[];for(let e of n?.[r]??[])a.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});let{redactions:o}=entropyScrub(t,this.config.redactionToken,this.config.entropy);a.push(...o);let s=e.s(a);return{scrubbed:e.i(t,s),redactions:s,tier:n?`model+entropy`:`entropy`,modelAvailable:n!==null,latencyMs:performance.now()-i}})}async dispose(){let e=this.tier2;this.tier2=null,this.tier2LoadPromise=null,await e?.dispose()}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await Promise.resolve().then(()=>require("./tier2-classifier-CK7UcktD.cjs"));this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed. The model ships bundled with @stackone/redaction — try reinstalling the package, or configure modelPath.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let h;const getRedactors=()=>((0,t.isMissing)(h)&&(h={FULL:(0,n.default)({paths:m,serialize:!1,censor:f.FULL}),PARTIAL:(0,n.default)({paths:m,serialize:!1,censor:f.PARTIAL})}),h),redactObject=(e,n=`FULL`)=>(0,t.isMissing)(e)||typeof e!=`object`||!e?e:getRedactors()[n]((0,t.deepCopy)(e));exports.CensorType=u,exports.I_AM_EDGE=!1,exports.MODEL_FILES=e.c,exports.PiiRedaction=PiiRedaction,exports.REDACT_CENSOR=o,exports.createPiiRedaction=createPiiRedaction,exports.entropyScrub=entropyScrub,exports.getDefaultModelCacheDir=e.u,exports.isModelPresent=e.d,exports.redactFields=redactFields,exports.redactObject=redactObject,exports.redactPath=redactPath,exports.redactUrl=redactUrl,exports.scrubObjectAsync=scrubObjectAsync,exports.shannonEntropy=shannonEntropy;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config-BPwtMZw7.cjs");let t=require("@stackone/utils"),n=require("fast-redact");n=e.p(n);const r=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`,`klaviyo-api-key`,`x-sn-apikey`],i=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...r],a=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>r.map(t=>`${e}[${JSON.stringify(t)}]`))],o=`**redacted**`,s=`**circular**`,c=`**max-depth**`,l=`**unreadable**`;let u=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>o,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?o:`${o}${e.slice(-5)}`:o,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),d=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||d.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},f={FULL:censorFn,PARTIAL:partialCensorFn},p=getKeysToRedact(i),m=new Set(Array.from(p,e=>e.toLowerCase())),matchesRedactedKey=e=>{let t=e.toLowerCase();return m.has(t)?!0:t.includes(`[`)?t.split(/[\[\]]/).some(e=>e&&m.has(e)):!1},h=[...getPathsToRedact(a),...Array.from(p).map(asValidPath)],redactUrl=(e,n=`FULL`,r)=>{if(!(0,t.isMissing)(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,matchesRedactedKey(t)?f[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,n=`FULL`,r)=>{if(!(0,t.isMissing)(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,matchesRedactedKey(t)?f[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactNode=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(i.has(e))return s;if(r>64)return c;if(Array.isArray(e)){if(!n)return[...e];i.add(e);let a=e.map(e=>typeof e==`object`&&e?redactNode(e,t,n,r+1,i):e);return i.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return l}if(!a)return e;i.add(e);let o=Object.fromEntries(Object.entries(e).map(([e,a])=>matchesRedactedKey(e)?[e,f[t](a)]:n&&typeof a==`object`&&a?[e,redactNode(a,t,n,r+1,i)]:[e,a]));return i.delete(e),o},redactFields=(e,t=`FULL`,n=!1)=>redactNode(e,t,n,0,new WeakSet),defineOwn=(e,t,n)=>{Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0})},walk=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(n.has(e))return s;if(t>64)return c;if(Array.isArray(e)){n.add(e);let a=Array(e.length);return e.forEach((e,o)=>{typeof e==`string`?(a[o]=e,r.push(e),i.push(e=>{a[o]=e})):a[o]=walk(e,t+1,n,r,i)}),n.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return l}if(!a)return e;n.add(e);let o={};for(let[a,s]of Object.entries(e))typeof s==`string`?(defineOwn(o,a,s),r.push(s),i.push(e=>{defineOwn(o,a,e)})):defineOwn(o,a,walk(s,t+1,n,r,i));return n.delete(e),o};async function scrubObjectAsync(e,t){if(typeof e==`string`)return(await t.scrubAsync(e)).scrubbed;let n=[],r=[],i=walk(e,0,new WeakSet,n,r);return n.length>0&&(await t.scrubManyAsync(n)).forEach((e,t)=>r[t](e.scrubbed)),i}function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,r=e.t){let i=e.a(t,r.skipPatterns),a=[],o=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,s=new RegExp(r.candidatePattern.source,o),c;for(;(c=s.exec(t))!==null;){let t=c[0];t.length<r.minLength||e.o(c.index,c.index+t.length,i)||shannonEntropy(t)>=r.threshold&&a.push({start:c.index,end:c.index+t.length,original:t,replacement:n,source:`entropy`})}for(let o of r.piiPatterns??[]){let r=new RegExp(o.source,o.flags.includes(`g`)?o.flags:`${o.flags}g`),s;for(;(s=r.exec(t))!==null;){let t=s.index,r=t+s[0].length;e.o(t,r,i)||a.push({start:t,end:r,original:s[0],replacement:n,source:`entropy`})}}let l=e.s(a);return{scrubbed:e.i(t,l),redactions:l}}var PiiRedaction=class{constructor(t){this.tier2=null,this.tier2LoadPromise=null,this.config=e.r(t),this.enableTier2=t?.enableTier2??!1,this.logger=t?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(t){let n=performance.now();if(!this.enableTier2)return this.scrub(t);let r=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let e=await this.tier2.detectSecrets(t);for(let t of e)i.push({start:t.start,end:t.end,original:t.text,replacement:this.config.redactionToken,source:`model`,label:t.label});r=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(t,this.config.redactionToken,this.config.entropy);i.push(...a);let o=e.s(i);return{scrubbed:e.i(t,o),redactions:o,tier:r?`model+entropy`:`entropy`,modelAvailable:r,latencyMs:performance.now()-n}}async scrubManyAsync(t){if(!this.enableTier2)return t.map(e=>this.scrub(e));let n=null;try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);n=await this.tier2.detectSecretsBatch(t)}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 batch detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}return t.map((t,r)=>{let i=performance.now(),a=[];for(let e of n?.[r]??[])a.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});let{redactions:o}=entropyScrub(t,this.config.redactionToken,this.config.entropy);a.push(...o);let s=e.s(a);return{scrubbed:e.i(t,s),redactions:s,tier:n?`model+entropy`:`entropy`,modelAvailable:n!==null,latencyMs:performance.now()-i}})}async dispose(){let e=this.tier2;this.tier2=null,this.tier2LoadPromise=null,await e?.dispose()}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await Promise.resolve().then(()=>require("./tier2-classifier-CK7UcktD.cjs"));this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed. The model ships bundled with @stackone/redaction — try reinstalling the package, or configure modelPath.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let g;const getRedactors=()=>((0,t.isMissing)(g)&&(g={FULL:(0,n.default)({paths:h,serialize:!1,censor:f.FULL}),PARTIAL:(0,n.default)({paths:h,serialize:!1,censor:f.PARTIAL})}),g),redactObject=(e,n=`FULL`)=>(0,t.isMissing)(e)||typeof e!=`object`||!e?e:getRedactors()[n]((0,t.deepCopy)(e));exports.CensorType=u,exports.I_AM_EDGE=!1,exports.KEYS_TO_REDACT=i,exports.MODEL_FILES=e.c,exports.PATHS_TO_REDACT=a,exports.PiiRedaction=PiiRedaction,exports.REDACT_CENSOR=o,exports.createPiiRedaction=createPiiRedaction,exports.entropyScrub=entropyScrub,exports.getDefaultModelCacheDir=e.u,exports.isModelPresent=e.d,exports.redactFields=redactFields,exports.redactObject=redactObject,exports.redactPath=redactPath,exports.redactUrl=redactUrl,exports.scrubObjectAsync=scrubObjectAsync,exports.shannonEntropy=shannonEntropy;
|
package/dist/node/index.d.cts
CHANGED
|
@@ -3,6 +3,8 @@ import { ILogger } from "@stackone/logger";
|
|
|
3
3
|
//#region \0rolldown/runtime.js
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region src/shared/index.d.ts
|
|
6
|
+
declare const KEYS_TO_REDACT: string[];
|
|
7
|
+
declare const PATHS_TO_REDACT: string[];
|
|
6
8
|
declare const REDACT_CENSOR = "**redacted**";
|
|
7
9
|
declare enum CensorType {
|
|
8
10
|
FULL = "FULL",
|
|
@@ -97,4 +99,4 @@ declare function entropyScrub(text: string, redactionToken?: string, config?: En
|
|
|
97
99
|
declare const redactObject: <T>(obj: T, censorType?: CensorType) => T;
|
|
98
100
|
declare const I_AM_EDGE = false;
|
|
99
101
|
//#endregion
|
|
100
|
-
export { CensorType, type EntropyConfig, type EntropyScrubResult, I_AM_EDGE, MODEL_FILES, type ModelConfig, type ModelDetection, PiiRedaction, type PiiRedactionConfig, type PiiRedactionOptions, REDACT_CENSOR, type RedactionResult, type RedactionSpan, createPiiRedaction, entropyScrub, getDefaultModelCacheDir, isModelPresent, redactFields, redactObject, redactPath, redactUrl, scrubObjectAsync, shannonEntropy };
|
|
102
|
+
export { CensorType, type EntropyConfig, type EntropyScrubResult, I_AM_EDGE, KEYS_TO_REDACT, MODEL_FILES, type ModelConfig, type ModelDetection, PATHS_TO_REDACT, PiiRedaction, type PiiRedactionConfig, type PiiRedactionOptions, REDACT_CENSOR, type RedactionResult, type RedactionSpan, createPiiRedaction, entropyScrub, getDefaultModelCacheDir, isModelPresent, redactFields, redactObject, redactPath, redactUrl, scrubObjectAsync, shannonEntropy };
|
package/dist/node/index.d.mts
CHANGED
|
@@ -2,6 +2,8 @@ import { t as __name } from "./chunk-BhWHdk3m.mjs";
|
|
|
2
2
|
import { ILogger } from "@stackone/logger";
|
|
3
3
|
|
|
4
4
|
//#region src/shared/index.d.ts
|
|
5
|
+
declare const KEYS_TO_REDACT: string[];
|
|
6
|
+
declare const PATHS_TO_REDACT: string[];
|
|
5
7
|
declare const REDACT_CENSOR = "**redacted**";
|
|
6
8
|
declare enum CensorType {
|
|
7
9
|
FULL = "FULL",
|
|
@@ -96,4 +98,4 @@ declare function entropyScrub(text: string, redactionToken?: string, config?: En
|
|
|
96
98
|
declare const redactObject: <T>(obj: T, censorType?: CensorType) => T;
|
|
97
99
|
declare const I_AM_EDGE = false;
|
|
98
100
|
//#endregion
|
|
99
|
-
export { CensorType, type EntropyConfig, type EntropyScrubResult, I_AM_EDGE, MODEL_FILES, type ModelConfig, type ModelDetection, PiiRedaction, type PiiRedactionConfig, type PiiRedactionOptions, REDACT_CENSOR, type RedactionResult, type RedactionSpan, createPiiRedaction, entropyScrub, getDefaultModelCacheDir, isModelPresent, redactFields, redactObject, redactPath, redactUrl, scrubObjectAsync, shannonEntropy };
|
|
101
|
+
export { CensorType, type EntropyConfig, type EntropyScrubResult, I_AM_EDGE, KEYS_TO_REDACT, MODEL_FILES, type ModelConfig, type ModelDetection, PATHS_TO_REDACT, PiiRedaction, type PiiRedactionConfig, type PiiRedactionOptions, REDACT_CENSOR, type RedactionResult, type RedactionSpan, createPiiRedaction, entropyScrub, getDefaultModelCacheDir, isModelPresent, redactFields, redactObject, redactPath, redactUrl, scrubObjectAsync, shannonEntropy };
|
package/dist/node/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./chunk-BhWHdk3m.mjs";import{a as e,c as t,d as n,i as r,o as i,r as a,s as o,t as s,u as c}from"./config-BgN6jr5v.mjs";import{deepCopy as l,isMissing as u}from"@stackone/utils";import d from"fast-redact";const f=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`],p=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...f],m=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>f.map(t=>`${e}[${JSON.stringify(t)}]`))],h=`**redacted**`,g=`**circular**`,_=`**max-depth**`,v=`**unreadable**`;let y=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>h,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?h:`${h}${e.slice(-5)}`:h,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),b=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||b.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},x={FULL:censorFn,PARTIAL:partialCensorFn},S=getKeysToRedact(p),C=[...getPathsToRedact(m),...Array.from(S).map(asValidPath)],redactUrl=(e,t=`FULL`,n)=>{if(!u(e))try{let n=new URL(e),r=[...n.searchParams].reduce((e,[n,r])=>(e.set(n,S.has(n)?x[t](r):r),e),new URLSearchParams);return`${n.origin}${n.pathname}${r.toString()?`?`+r:``}${n.hash}`}catch(t){return n?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,t=`FULL`,n)=>{if(!u(e))try{let[n,r]=e.split(`?`);return r?`${n}?${[...new URLSearchParams(r)].reduce((e,[n,r])=>(e.set(n,S.has(n)?x[t](r):r),e),new URLSearchParams)}`:e}catch(t){return n?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactNode=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(i.has(e))return g;if(r>64)return _;if(Array.isArray(e)){if(!n)return[...e];i.add(e);let a=e.map(e=>typeof e==`object`&&e?redactNode(e,t,n,r+1,i):e);return i.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return v}if(!a)return e;i.add(e);let o=Object.fromEntries(Object.entries(e).map(([e,a])=>S.has(e)?[e,x[t](a)]:n&&typeof a==`object`&&a?[e,redactNode(a,t,n,r+1,i)]:[e,a]));return i.delete(e),o},redactFields=(e,t=`FULL`,n=!1)=>redactNode(e,t,n,0,new WeakSet),defineOwn=(e,t,n)=>{Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0})},walk=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(n.has(e))return g;if(t>64)return _;if(Array.isArray(e)){n.add(e);let a=Array(e.length);return e.forEach((e,o)=>{typeof e==`string`?(a[o]=e,r.push(e),i.push(e=>{a[o]=e})):a[o]=walk(e,t+1,n,r,i)}),n.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return v}if(!a)return e;n.add(e);let o={};for(let[a,s]of Object.entries(e))typeof s==`string`?(defineOwn(o,a,s),r.push(s),i.push(e=>{defineOwn(o,a,e)})):defineOwn(o,a,walk(s,t+1,n,r,i));return n.delete(e),o};async function scrubObjectAsync(e,t){if(typeof e==`string`)return(await t.scrubAsync(e)).scrubbed;let n=[],r=[],i=walk(e,0,new WeakSet,n,r);return n.length>0&&(await t.scrubManyAsync(n)).forEach((e,t)=>r[t](e.scrubbed)),i}function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,a=s){let c=e(t,a.skipPatterns),l=[],u=a.candidatePattern.flags.includes(`g`)?a.candidatePattern.flags:`${a.candidatePattern.flags}g`,d=new RegExp(a.candidatePattern.source,u),f;for(;(f=d.exec(t))!==null;){let e=f[0];e.length<a.minLength||i(f.index,f.index+e.length,c)||shannonEntropy(e)>=a.threshold&&l.push({start:f.index,end:f.index+e.length,original:e,replacement:n,source:`entropy`})}for(let e of a.piiPatterns??[]){let r=new RegExp(e.source,e.flags.includes(`g`)?e.flags:`${e.flags}g`),a;for(;(a=r.exec(t))!==null;){let e=a.index,t=e+a[0].length;i(e,t,c)||l.push({start:e,end:t,original:a[0],replacement:n,source:`entropy`})}}let p=o(l);return{scrubbed:r(t,p),redactions:p}}var PiiRedaction=class{constructor(e){this.tier2=null,this.tier2LoadPromise=null,this.config=a(e),this.enableTier2=e?.enableTier2??!1,this.logger=e?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(e){let t=performance.now();if(!this.enableTier2)return this.scrub(e);let n=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let t=await this.tier2.detectSecrets(e);for(let e of t)i.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});n=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(e,this.config.redactionToken,this.config.entropy);i.push(...a);let s=o(i);return{scrubbed:r(e,s),redactions:s,tier:n?`model+entropy`:`entropy`,modelAvailable:n,latencyMs:performance.now()-t}}async scrubManyAsync(e){if(!this.enableTier2)return e.map(e=>this.scrub(e));let t=null;try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);t=await this.tier2.detectSecretsBatch(e)}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 batch detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}return e.map((e,n)=>{let i=performance.now(),a=[];for(let e of t?.[n]??[])a.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});let{redactions:s}=entropyScrub(e,this.config.redactionToken,this.config.entropy);a.push(...s);let c=o(a);return{scrubbed:r(e,c),redactions:c,tier:t?`model+entropy`:`entropy`,modelAvailable:t!==null,latencyMs:performance.now()-i}})}async dispose(){let e=this.tier2;this.tier2=null,this.tier2LoadPromise=null,await e?.dispose()}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await import(`./tier2-classifier-CY0XZ85t.mjs`);this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed. The model ships bundled with @stackone/redaction — try reinstalling the package, or configure modelPath.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let w;const getRedactors=()=>(u(w)&&(w={FULL:d({paths:C,serialize:!1,censor:x.FULL}),PARTIAL:d({paths:C,serialize:!1,censor:x.PARTIAL})}),w),redactObject=(e,t=`FULL`)=>u(e)||typeof e!=`object`||!e?e:getRedactors()[t](l(e)),T=!1;export{y as CensorType,T as I_AM_EDGE,t as MODEL_FILES,PiiRedaction,h as REDACT_CENSOR,createPiiRedaction,entropyScrub,c as getDefaultModelCacheDir,n as isModelPresent,redactFields,redactObject,redactPath,redactUrl,scrubObjectAsync,shannonEntropy};
|
|
1
|
+
import"./chunk-BhWHdk3m.mjs";import{a as e,c as t,d as n,i as r,o as i,r as a,s as o,t as s,u as c}from"./config-BgN6jr5v.mjs";import{deepCopy as l,isMissing as u}from"@stackone/utils";import d from"fast-redact";const f=[`x-api-key`,`x-connect-token`,`x-signature`,`x-idp-session-token`,`us-customer-api-key`,`x-stackone-external-trigger-token`,`klaviyo-api-key`,`x-sn-apikey`],p=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`,`secret`,`secrets`,`credentials`,`setup_information`,`setup_fields`,`authentication_config_key`,`cookie`,`set-cookie`,`bearer`,`apikey`,...f],m=[`req.headers.authorization`,`req.headers.cookie`,`req.headers.cookies`,`req.headers["set-cookie"]`,`req.headers["set-cookies"]`,`req.headers.httpsAgent.options.cert`,`req.headers.httpsAgent.options.key`,`req.headers["x-stackone-external-trigger-token"]`,`error.config.headers.authorization`,`error.config.data`,`error.config.headers.cookie`,`error.config.headers.cookies`,`error.config.headers["set-cookie"]`,`error.config.headers["set-cookies"]`,`error.config.httpsAgent.options.cert`,`error.config.httpsAgent.options.key`,`err.config.headers.authorization`,`err.config.data`,`err.config.headers.cookie`,`err.config.headers.cookies`,`err.config.headers["set-cookie"]`,`err.config.headers["set-cookies"]`,`err.config.httpsAgent.options.cert`,`err.config.httpsAgent.options.key`,`res.headers.authorization`,`res.headers.cookie`,`res.headers.cookies`,`res.headers["set-cookie"]`,`res.headers["set-cookies"]`,`res.headers.httpsAgent.options.cert`,`res.headers.httpsAgent.options.key`,`context.credentials`,...[`req.headers`,`res.headers`,`error.config.headers`,`err.config.headers`].flatMap(e=>f.map(t=>`${e}[${JSON.stringify(t)}]`))],h=`**redacted**`,g=`**circular**`,_=`**max-depth**`,v=`**unreadable**`;let y=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>h,partialCensorFn=e=>typeof e==`string`?e.startsWith(`**redacted**`)?e:e.length<=10?h:`${h}${e.slice(-5)}`:h,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),b=/^[A-Za-z_$][\w$]*$/,asValidPath=e=>e.includes(`.`)||e.includes(`[`)||b.test(e)?e:`[${JSON.stringify(e)}]`,getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>asValidPath(e)),r=n.map(e=>capitalizeKey(e));return[...n,...r]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},x={FULL:censorFn,PARTIAL:partialCensorFn},S=getKeysToRedact(p),C=new Set(Array.from(S,e=>e.toLowerCase())),matchesRedactedKey=e=>{let t=e.toLowerCase();return C.has(t)?!0:t.includes(`[`)?t.split(/[\[\]]/).some(e=>e&&C.has(e)):!1},w=[...getPathsToRedact(m),...Array.from(S).map(asValidPath)],redactUrl=(e,t=`FULL`,n)=>{if(!u(e))try{let n=new URL(e),r=[...n.searchParams].reduce((e,[n,r])=>(e.set(n,matchesRedactedKey(n)?x[t](r):r),e),new URLSearchParams);return`${n.origin}${n.pathname}${r.toString()?`?`+r:``}${n.hash}`}catch(t){return n?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,t=`FULL`,n)=>{if(!u(e))try{let[n,r]=e.split(`?`);return r?`${n}?${[...new URLSearchParams(r)].reduce((e,[n,r])=>(e.set(n,matchesRedactedKey(n)?x[t](r):r),e),new URLSearchParams)}`:e}catch(t){return n?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactNode=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(i.has(e))return g;if(r>64)return _;if(Array.isArray(e)){if(!n)return[...e];i.add(e);let a=e.map(e=>typeof e==`object`&&e?redactNode(e,t,n,r+1,i):e);return i.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return v}if(!a)return e;i.add(e);let o=Object.fromEntries(Object.entries(e).map(([e,a])=>matchesRedactedKey(e)?[e,x[t](a)]:n&&typeof a==`object`&&a?[e,redactNode(a,t,n,r+1,i)]:[e,a]));return i.delete(e),o},redactFields=(e,t=`FULL`,n=!1)=>redactNode(e,t,n,0,new WeakSet),defineOwn=(e,t,n)=>{Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0})},walk=(e,t,n,r,i)=>{if(typeof e!=`object`||!e)return e;if(n.has(e))return g;if(t>64)return _;if(Array.isArray(e)){n.add(e);let a=Array(e.length);return e.forEach((e,o)=>{typeof e==`string`?(a[o]=e,r.push(e),i.push(e=>{a[o]=e})):a[o]=walk(e,t+1,n,r,i)}),n.delete(e),a}let a;try{let t=Object.getPrototypeOf(e);a=t===null||Object.getPrototypeOf(t)===null}catch{return v}if(!a)return e;n.add(e);let o={};for(let[a,s]of Object.entries(e))typeof s==`string`?(defineOwn(o,a,s),r.push(s),i.push(e=>{defineOwn(o,a,e)})):defineOwn(o,a,walk(s,t+1,n,r,i));return n.delete(e),o};async function scrubObjectAsync(e,t){if(typeof e==`string`)return(await t.scrubAsync(e)).scrubbed;let n=[],r=[],i=walk(e,0,new WeakSet,n,r);return n.length>0&&(await t.scrubManyAsync(n)).forEach((e,t)=>r[t](e.scrubbed)),i}function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,a=s){let c=e(t,a.skipPatterns),l=[],u=a.candidatePattern.flags.includes(`g`)?a.candidatePattern.flags:`${a.candidatePattern.flags}g`,d=new RegExp(a.candidatePattern.source,u),f;for(;(f=d.exec(t))!==null;){let e=f[0];e.length<a.minLength||i(f.index,f.index+e.length,c)||shannonEntropy(e)>=a.threshold&&l.push({start:f.index,end:f.index+e.length,original:e,replacement:n,source:`entropy`})}for(let e of a.piiPatterns??[]){let r=new RegExp(e.source,e.flags.includes(`g`)?e.flags:`${e.flags}g`),a;for(;(a=r.exec(t))!==null;){let e=a.index,t=e+a[0].length;i(e,t,c)||l.push({start:e,end:t,original:a[0],replacement:n,source:`entropy`})}}let p=o(l);return{scrubbed:r(t,p),redactions:p}}var PiiRedaction=class{constructor(e){this.tier2=null,this.tier2LoadPromise=null,this.config=a(e),this.enableTier2=e?.enableTier2??!1,this.logger=e?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(e){let t=performance.now();if(!this.enableTier2)return this.scrub(e);let n=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let t=await this.tier2.detectSecrets(e);for(let e of t)i.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});n=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(e,this.config.redactionToken,this.config.entropy);i.push(...a);let s=o(i);return{scrubbed:r(e,s),redactions:s,tier:n?`model+entropy`:`entropy`,modelAvailable:n,latencyMs:performance.now()-t}}async scrubManyAsync(e){if(!this.enableTier2)return e.map(e=>this.scrub(e));let t=null;try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);t=await this.tier2.detectSecretsBatch(e)}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 batch detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}return e.map((e,n)=>{let i=performance.now(),a=[];for(let e of t?.[n]??[])a.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});let{redactions:s}=entropyScrub(e,this.config.redactionToken,this.config.entropy);a.push(...s);let c=o(a);return{scrubbed:r(e,c),redactions:c,tier:t?`model+entropy`:`entropy`,modelAvailable:t!==null,latencyMs:performance.now()-i}})}async dispose(){let e=this.tier2;this.tier2=null,this.tier2LoadPromise=null,await e?.dispose()}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await import(`./tier2-classifier-CY0XZ85t.mjs`);this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed. The model ships bundled with @stackone/redaction — try reinstalling the package, or configure modelPath.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let T;const getRedactors=()=>(u(T)&&(T={FULL:d({paths:w,serialize:!1,censor:x.FULL}),PARTIAL:d({paths:w,serialize:!1,censor:x.PARTIAL})}),T),redactObject=(e,t=`FULL`)=>u(e)||typeof e!=`object`||!e?e:getRedactors()[t](l(e)),E=!1;export{y as CensorType,E as I_AM_EDGE,p as KEYS_TO_REDACT,t as MODEL_FILES,m as PATHS_TO_REDACT,PiiRedaction,h as REDACT_CENSOR,createPiiRedaction,entropyScrub,c as getDefaultModelCacheDir,n as isModelPresent,redactFields,redactObject,redactPath,redactUrl,scrubObjectAsync,shannonEntropy};
|