cc-safety-net 2.0.7 → 2.0.8

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.
@@ -1,5 +1,5 @@
1
1
  import{randomBytes as EX}from"node:crypto";import{closeSync as p3,constants as k$,fstatSync as l3,fsyncSync as TX,lstatSync as V0,mkdirSync as OZ,openSync as LZ,readdirSync as c3,readFileSync as SX,realpathSync as T0,renameSync as yX,rmdirSync as wX,statSync as m3,unlinkSync as d3,writeFileSync as vX}from"node:fs";import{isAbsolute as MZ,join as Q$,normalize as uX,parse as FZ,relative as i3,resolve as s3,sep as l$}from"node:path";var hX=Symbol("PolicyFilesystemScope"),gX=Symbol("PolicyFilesystemTarget"),NZ=k$.O_NOFOLLOW??0;class h extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function z1($,Z){return{[hX]:!0,root:s3($),label:Z}}function m$($,Z){let J=uX(Z);if(Z===""||MZ(Z)||J===".."||J.startsWith(`..${l$}`))throw new h($.label);return{[gX]:!0,scope:$,relativePath:J,path:Q$($.root,J)}}function X1($,Z){let J=i3($.root,s3(Z));return m$($,J)}function k2($,Z="rules policy"){let J=s3($),Q=FZ(J).dir;return m$(z1(Q,Z),i3(Q,J))}function K0($){try{if(!B1($,!1).exists)return null;let J=LZ($.path,k$.O_RDONLY|NZ);try{let Q=l3(J);if(!Q.isFile())throw new h($.scope.label);let X=SX(J,"utf-8"),W=V0($.path);if(!W.isFile()||W.isSymbolicLink()||Q.dev!==W.dev||Q.ino!==W.ino)throw new h($.scope.label);return B1($,!1),X}finally{p3(J)}}catch(Z){R0($.scope.label,Z)}}function VZ($,Z,J=384,Q){let X=`${$.path}.${EX(8).toString("hex")}.tmp`,W=null;try{lX($),B1($,!0),W=LZ(X,k$.O_CREAT|k$.O_EXCL|k$.O_WRONLY|NZ,J);let K=l3(W);if(!K.isFile())throw new h($.scope.label);vX(W,Z,"utf-8"),TX(W);let Y=l3(W);if(!Y.isFile()||Y.dev!==K.dev||Y.ino!==K.ino)throw new h($.scope.label);p3(W),W=null,B1($,!0),pX($,X,Y.dev,Y.ino),yX(X,$.path),Q?.($.path),B1($,!1)}catch(K){if(W!==null)dX(W);iX(X),R0($.scope.label,K)}}function RZ($,Z){if($.path===Z.path)return!0;try{if(!B1($,!1).exists||!B1(Z,!1).exists)return!1;return T0($.path)===T0(Z.path)}catch(J){if(J instanceof h)throw J;throw new h($.scope.label)}}function kX($){try{if(!B1($,!1,"directory").exists)return null;let J=c3($.path);return B1($,!1,"directory"),J}catch(Z){R0($.scope.label,Z)}}function OM($){let Z=kX($);if(!Z)return null;try{let J=Z.map((Q)=>{let X=m$($.scope,Q$($.relativePath,Q)),W=V0(X.path);if(W.isSymbolicLink()||!W.isFile()&&!W.isDirectory())throw new h($.scope.label);return x2(bZ($.scope),T0(X.path),$.scope.label),{name:Q,kind:W.isDirectory()?"directory":"file"}});return B1($,!1,"directory"),J}catch(J){R0($.scope.label,J)}}function LM($){try{if(!B1($,!0).exists)return;d3($.path),B1($,!0)}catch(Z){R0($.scope.label,Z)}}function MM($){try{IZ($,$.relativePath.split(l$))}catch(Z){R0($.scope.label,Z)}}function FM($){try{if(!xX($))return;zZ($),B1($,!0,"directory")}catch(Z){R0($.scope.label,Z)}}function xX($){try{if(!B1($,!0,"directory").exists)return!1;return DZ($),!0}catch(Z){R0($.scope.label,Z)}}function B1($,Z,J="file"){let Q=r3($.scope);if(!Q)return{exists:!1};let X=$.relativePath.split(l$);for(let W of X.keys()){let K=Q$($.scope.root,...X.slice(0,W+1)),Y=x$(K);if(!Y){if(W===X.length-1&&Z)return{exists:!1};return{exists:!1}}if(Y.isSymbolicLink())throw new h($.scope.label);if(W<X.length-1&&!Y.isDirectory())throw new h($.scope.label);if(W===X.length-1&&(J==="file"?!Y.isFile():!Y.isDirectory()))throw new h($.scope.label);x2(Q,T0(K),$.scope.label)}return{exists:!0}}function DZ($){for(let Z of c3($.path)){let J=m$($.scope,Q$($.relativePath,Z)),Q=V0(J.path);if(Q.isSymbolicLink()||!Q.isDirectory()&&!Q.isFile())throw new h($.scope.label);if(Q.isDirectory())DZ(J)}B1($,!1,"directory")}function zZ($){for(let Z of c3($.path)){let J=m$($.scope,Q$($.relativePath,Z)),Q=V0(J.path);if(Q.isSymbolicLink())throw new h($.scope.label);if(Q.isDirectory()){zZ(J);continue}if(!Q.isFile())throw new h($.scope.label);d3(J.path)}wX($.path)}function lX($){IZ($,$.relativePath.split(l$).slice(0,-1))}function IZ($,Z){mX($.scope);let J=bZ($.scope);for(let Q of Z.keys()){let X=Q$($.scope.root,...Z.slice(0,Q+1));if(!x$(X))OZ(X,{mode:448});let K=V0(X);if(!K.isDirectory()||K.isSymbolicLink())throw new h($.scope.label);x2(J,T0(X),$.scope.label)}}function mX($){if(x$($.root)){if(!m3($.root).isDirectory())throw new h($.label);return}let Z=[],J=$.root;while(!x$(J)){Z.unshift(J);let Q=FZ(J).dir;if(Q===J)throw new h($.label);J=Q}if(!m3(J).isDirectory())throw new h($.label);for(let Q of Z){OZ(Q,{mode:448});let X=V0(Q);if(!X.isDirectory()||X.isSymbolicLink())throw new h($.label)}}function r3($){if(!x$($.root))return null;if(!m3($.root).isDirectory())throw new h($.label);return T0($.root)}function bZ($){let Z=r3($);if(!Z)throw new h($.label);return Z}function pX($,Z,J,Q){let X=V0(Z);if(!X.isFile()||X.isSymbolicLink()||X.dev!==J||X.ino!==Q)throw new h($.scope.label);let W=r3($.scope);if(!W)throw new h($.scope.label);x2(W,T0(Z),$.scope.label)}function x2($,Z,J){let Q=i3($,Z);if(Q===".."||Q.startsWith(`..${l$}`)||MZ(Q))throw new h(J)}function x$($){try{return V0($)}catch(Z){if(cX(Z)&&Z.code==="ENOENT")return null;throw Z}}function R0($,Z){if(Z instanceof h)throw Z;throw new h($)}function cX($){return $ instanceof Error&&"code"in $}function dX($){try{p3($)}catch{}}function iX($){try{d3($)}catch{}}import{homedir as oX}from"node:os";import{dirname as i1,isAbsolute as tX,join as y1,relative as eX,resolve as s1,sep as $W}from"node:path";var I1=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,l2="rulebook.json",m2=".cc-safety-net/rules";var fZ=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/,sX=/^[A-Za-z0-9][A-Za-z0-9_.-]*\/[A-Za-z0-9_.-]+$/,rX=/^[A-Za-z0-9._-]+$/,nX=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),aX="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n3=new RegExp(`^${nX}/(${I1.source.slice(1,-1)})/${aX}$`);function PZ($){return`.cc-safety-net/rules/${$}/rulebook.json`}function p$($){if(W$($))try{return X$($),null}catch(Z){return Z instanceof Error?Z.message:String(Z)}return I1.test($)?null:`Local rulebook sources must be bare names matching ${I1}: ${$}`}function X$($){if($.startsWith("github:"))throw Error(`Invalid rulebook source: ${$}`);let Z=$.match(fZ);if(!Z?.[1]||!Z[2]||!Z[3])throw Error(`Invalid GitHub rulebook source: ${$}`);let[J,Q,...X]=Z[3].split("/");if(!J||!rX.test(J))throw Error(`GitHub rulebook refs must be a single path segment: ${$}`);if(!Q||X.length>0||!I1.test(Q))throw Error(`GitHub rulebook sources must be owner/repo#ref/<rulebook-name>: ${$}`);return{owner:Z[1],repo:Z[2],ref:J,path:PZ(Q),name:Q}}function CZ($){return sX.test($)}function W$($){return fZ.test($)}function a3($){if(!I1.test($))throw Error(`Local rulebook sources must be bare names matching ${I1}: ${$}`)}var EZ="rule.json",p2="policy.json",TZ="rule.lock",ZW="config.json",SZ=".cc-safety-net",JW="rules",AZ="cache",QW="CC_SAFETY_NET_HOME",w1="`cc-safety-net rule sync`";function XW($){return s1($??process.cwd(),m2)}function yZ($){return y1(XW($),EZ)}function Y0($){return $?.userConfigDir??($?.userConfigPath?i1($.userConfigPath):y1(WW(),JW))}function WW(){let $=process.env[QW];return $?s1($):y1(oX(),SZ)}function wZ($){return y1(Y0($),EZ)}function fM($){return y1(Y0($),TZ)}function S0($){return y1(i1($),TZ)}function PM($={}){return y1(i1(Y0($)),ZW)}function CM($={}){return s1($.cwd??process.cwd(),".safety-net.json")}function vZ($){let Z=$.userConfigPath??wZ($),J=$.projectConfigPath??yZ($.cwd),Q=uZ(Z,$),X=hZ(J,$);return{userConfigPath:Z,projectConfigPath:J,userLockPath:S0(Z),projectLockPath:S0(J),userScope:Q,projectScope:X,userConfigTarget:X1(Q,Z),projectConfigTarget:X1(X,J),userLockTarget:X1(Q,S0(Z)),projectLockTarget:X1(X,S0(J))}}function AM($){let Z=$.global?$.userConfigPath??wZ($):$.projectConfigPath??yZ($.cwd),J=$.global?uZ(Z,$):hZ(Z,$),Q=S0(Z);return{configDir:i1(Z),configPath:Z,lockPath:Q,filesystemScope:J,configTarget:X1(J,Z),lockTarget:X1(J,Q)}}function uZ($,Z){let J=Z.userConfigPath?i1(i1(s1(Z.userConfigPath))):i1(s1(Z.userConfigDir??Y0(Z)));return z1(J,"user policy")}function hZ($,Z){let J=s1(Z.cwd??process.cwd()),Q=s1($),X=eX(J,Q);if(X!==".."&&!X.startsWith(`..${$W}`)&&!tX(X))return z1(J,"project policy");return z1(i1(i1(Q)),"project policy")}function gZ($){if($.kind==="github"&&$.display_ref)return`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`;return $.spec}function c2($,Z){let J=$.digest.startsWith("sha256:")?$.digest.slice(7):$.digest;return y1(kZ(Z),"rulebooks",`${KW($)}--${J.slice(0,12)}`,l2)}function EM($){return y1(kZ($),"rulebooks")}function d2($,Z){let J=Z;return{cacheConfigDir:$,cwd:Z.cwd,global:J.global}}function KW($){return($.kind==="github"&&$.display_ref?`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`:$.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function kZ($){let Z=$?.cacheConfigDir??Y0($),J=$;if(J&&!J.global&&J.cwd&&s1(Z)===s1(J.cwd))return y1(s1(J.cwd),SZ,AZ);return y1(i1(Z),AZ)}import{lstatSync as xZ,readdirSync as YW,readFileSync as cZ,rmdirSync as BW,statSync as lZ,unlinkSync as qW,utimesSync as UW,writeFileSync as GW}from"node:fs";import{dirname as HW,join as K$}from"node:path";var i2=30,o3=1,t3=365;function s2($){if(typeof $!=="number"||!Number.isInteger($))return 30;if($<1)return 1;return $>365?365:$}var $6=86400000,jW=".last-prune",_W=/^\d{4}-\d{2}$/,OW=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,mZ=($)=>Math.floor($/$6);function LW($){try{let Z=K$(HW(Y0($)),p2),J=JSON.parse(cZ(Z,"utf-8"));return s2(J?.audit?.retention_days)}catch{return i2}}function dZ($,Z=()=>new Date){try{let J=Z().getTime();if(!lZ($,{throwIfNoEntry:!1})?.isDirectory())return;let Q=K$($,jW),X=lZ(Q,{throwIfNoEntry:!1})?.mtimeMs;if(X!==void 0&&mZ(X)===mZ(J))return;let W=J-LW()*$6,K=new Date(J).toISOString().slice(0,7);for(let Y of e3($)){if(Y.isDirectory()){MW(K$($,Y.name),W,K);continue}if(Y.isFile()&&Y.name.endsWith(".jsonl"))FW(K$($,Y.name),W)}GW(Q,"",{mode:384}),UW(Q,J/1000,J/1000)}catch{}}function MW($,Z,J){for(let Q of e3($)){if(!Q.isDirectory()||!_W.test(Q.name))continue;let X=K$($,Q.name);for(let W of e3(X)){if(!W.isFile())continue;let K=OW.exec(W.name);if(!K||K[2]!==Q.name)continue;let Y=Date.parse(`${K[1]}T00:00:00.000Z`)+$6;if(!Number.isFinite(Y)||Y>=Z)continue;iZ(K$(X,W.name))}if(Q.name!==J)pZ(X)}pZ($)}function FW($,Z){try{let J=xZ($);if(J.mtimeMs>=Z)return;let Q=cZ($,"utf-8").split(`
2
- `).filter((X)=>X.trim()).map(NW);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(xZ($).mtimeMs!==J.mtimeMs)return;iZ($)}catch{}}function NW($){try{let Z=JSON.parse($).ts,J=typeof Z==="string"?Date.parse(Z):Number.NaN;return Number.isFinite(J)?J:void 0}catch{return}}function e3($){try{return YW($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function iZ($){try{qW($)}catch{}}function pZ($){try{BW($)}catch{}}import{randomBytes as IW}from"node:crypto";import{appendFileSync as bW,mkdirSync as fW}from"node:fs";import{homedir as PW,userInfo as CW}from"node:os";import{isAbsolute as AW,join as Z6}from"node:path";var VW=[/\bgh[pousr]_[A-Za-z0-9]{20,}\b/g,/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,/\bglpat-[A-Za-z0-9_-]{20,}\b/g,/\bxox[abeprs]-[A-Za-z0-9-]{20,}\b/g,/\bnpm_[A-Za-z0-9_]{20,}\b/g,/\bpypi-[A-Za-z0-9_-]{20,}\b/g,/\b[rs]k_(?:live|test)_[A-Za-z0-9_]{20,}\b/g,/\bsk-[A-Za-z0-9_-]{20,}\b/g,/\bsk_[A-Za-z0-9]{20,}\b/g,/\bgsk_[A-Za-z0-9]{52,}\b/g,/\bxai-[A-Za-z0-9_-]{80,}\b/g,/\bpplx-[A-Za-z0-9_-]{20,}\b/g,/\bbastn_[A-Za-z0-9]{16,}\b/g,/\btgp_v1_[A-Za-z0-9_-]{43,}\b/g,/\bflp_[A-Za-z0-9]{10,}\b/g,/\bwfr_[A-Za-z0-9]{20,}\b/g,/\bfwp?_[A-Za-z0-9_-]{20,}\b/g,/\btp-[A-Za-z0-9_-]{20,}\b/g,/\bpsk-[A-Za-z0-9_-]{8,}-[A-Za-z0-9_-]{8,}\b/g,/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/g];function B0($){let Z=$.replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_DSN|CONNECTION_STRING)=("[^"]*"|'[^']*'|[^\s]+(?:\s+[A-Z_][A-Z0-9_]*=[^\s]+)*)/gi,"$1=<redacted>").replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_(?:URL|URI|CONNECTION_STRING))=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>").replace(/\b([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASS|KEY|CREDENTIALS)[A-Z0-9_]*)=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>");return sZ(Z)}function sZ($){let Z=$.replace(/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gi,"<redacted>").replace(/((?:(['"])(?:authorization|cookie|x-api-key|api-key)\2|(?:authorization|cookie|x-api-key|api-key))\s*:\s*)(['"])(?:\\[^\r\n]|(?!\3)[^\\\r\n])*\3/gi,"$1$3<redacted>$3").replace(/(['"]?\s*(?:authorization|cookie|x-api-key|api-key)\s*:(?!\s*(?:"<redacted>"|'<redacted>'))\s*)([^'"\r\n]+)(['"]?)/gi,"$1<redacted>$3").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/:@]+):([^\s@/]+)@/gi,"$1<redacted>:<redacted>@").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]+)@/gi,"$1<redacted>@").replace(/(^|[\s?&;|])((?:x-amz-signature|x-goog-signature|sig|signature)=)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^&#\s'"`;|<>()]*)/gi,"$1$2<redacted>").replace(/(^|\s)((?:-u|--user)(?:\s+|=))([^\s:]+):([^\s]+)/g,"$1$2<redacted>:<redacted>");for(let J of VW)Z=Z.replace(J,"<redacted>");return Z.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,"<redacted>").replace(/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,"<redacted>")}function RW($){return rZ($).reduceRight((J,Q)=>`${J.slice(0,Q.valueStart)}<redacted>${J.slice(Q.valueEnd)}`,$)}function kM($){return sZ(RW($))}function xM($){return rZ($).map((Z)=>$.slice(Z.valueStart,Z.valueEnd))}function lM($){return/[A-Za-z_][A-Za-z0-9_]*=/.test($)}function rZ($){let Z=[],J=/[A-Za-z_][A-Za-z0-9_]*=/g;for(let Q of $.matchAll(J)){let X=Q.index,W=$[X-1];if(X>0&&W&&!/[\s"'([{]/.test(W))continue;let K=X+Q[0].length;if(K>=$.length)continue;Z.push({valueStart:K,valueEnd:DW($,K)})}return Z}function DW($,Z){if($.startsWith("$(",Z))return zW($,Z);let J=$[Z];if(J==='"'||J==="'"){for(let X=Z+1;X<$.length;X++)if(J==='"'&&$[X]==="\\")X++;else if($[X]===J)return X+1}let Q=Z;while(Q<$.length&&!/\s/.test($[Q]??""))Q++;return Q}function zW($,Z){let J=0,Q;for(let X=Z;X<$.length;X++){let W=$[X];if(Q){if(Q==='"'&&W==="\\")X++;else if(W===Q)Q=void 0;continue}if(W==='"'||W==="'"){Q=W;continue}if(W==="$"&&$[X+1]==="("){J++,X++;continue}if(W!==")")continue;if(J--,J===0)return X+1}return $.length}var EW="2.0.7",TW=1e4,SW=2000,yW=256,wW=32768;function vW($){let Z=$.trim();if(!Z)return null;let J=Z.replace(/[^A-Za-z0-9_.-]+/g,"_");if(J=J.replace(/^[._-]+|[._-]+$/g,"").slice(0,128),!J||J==="."||J==="..")return null;return J}function uW($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function J6($,Z,J,Q,X,W={}){let K=vW($);if(!K)return;let Y=W.homeDir??nZ();if(!Y)return;let B=hW(Y);if(!B)return;try{let q=(W.now??(()=>new Date))().toISOString(),U=r2(B0(Z),TW),G=r2(B0(J),SW),j=W.toolName?r2(B0(W.toolName),yW):void 0,H=X===null?void 0:r2(B0(X),wW),_=Z6(B,uW(H?.value??null),q.slice(0,7));fW(_,{recursive:!0,mode:448});let O=Z6(_,`${q.slice(0,10)}-${K}.jsonl`),M={ts:q,id:(W.createId??(()=>IW(8).toString("hex")))(),v:EW,sessionId:K,decision:W.decision??"deny",agent:W.agent,shape:W.shape,level:W.level,configFallback:W.configFallback,toolName:j?.value,command:U.value,segment:G.value,...U.truncated||G.truncated||j?.truncated||H?.truncated?{truncated:!0}:{},reason:Q,ruleId:W.ruleId,intent:W.intent,failureStage:W.failureStage,errorCode:W.errorCode,cwd:H?.value??null};bW(O,`${JSON.stringify(M)}
2
+ `).filter((X)=>X.trim()).map(NW);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(xZ($).mtimeMs!==J.mtimeMs)return;iZ($)}catch{}}function NW($){try{let Z=JSON.parse($).ts,J=typeof Z==="string"?Date.parse(Z):Number.NaN;return Number.isFinite(J)?J:void 0}catch{return}}function e3($){try{return YW($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function iZ($){try{qW($)}catch{}}function pZ($){try{BW($)}catch{}}import{randomBytes as IW}from"node:crypto";import{appendFileSync as bW,mkdirSync as fW}from"node:fs";import{homedir as PW,userInfo as CW}from"node:os";import{isAbsolute as AW,join as Z6}from"node:path";var VW=[/\bgh[pousr]_[A-Za-z0-9]{20,}\b/g,/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,/\bglpat-[A-Za-z0-9_-]{20,}\b/g,/\bxox[abeprs]-[A-Za-z0-9-]{20,}\b/g,/\bnpm_[A-Za-z0-9_]{20,}\b/g,/\bpypi-[A-Za-z0-9_-]{20,}\b/g,/\b[rs]k_(?:live|test)_[A-Za-z0-9_]{20,}\b/g,/\bsk-[A-Za-z0-9_-]{20,}\b/g,/\bsk_[A-Za-z0-9]{20,}\b/g,/\bgsk_[A-Za-z0-9]{52,}\b/g,/\bxai-[A-Za-z0-9_-]{80,}\b/g,/\bpplx-[A-Za-z0-9_-]{20,}\b/g,/\bbastn_[A-Za-z0-9]{16,}\b/g,/\btgp_v1_[A-Za-z0-9_-]{43,}\b/g,/\bflp_[A-Za-z0-9]{10,}\b/g,/\bwfr_[A-Za-z0-9]{20,}\b/g,/\bfwp?_[A-Za-z0-9_-]{20,}\b/g,/\btp-[A-Za-z0-9_-]{20,}\b/g,/\bpsk-[A-Za-z0-9_-]{8,}-[A-Za-z0-9_-]{8,}\b/g,/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/g];function B0($){let Z=$.replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_DSN|CONNECTION_STRING)=("[^"]*"|'[^']*'|[^\s]+(?:\s+[A-Z_][A-Z0-9_]*=[^\s]+)*)/gi,"$1=<redacted>").replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_(?:URL|URI|CONNECTION_STRING))=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>").replace(/\b([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASS|KEY|CREDENTIALS)[A-Z0-9_]*)=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>");return sZ(Z)}function sZ($){let Z=$.replace(/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gi,"<redacted>").replace(/((?:(['"])(?:authorization|cookie|x-api-key|api-key)\2|(?:authorization|cookie|x-api-key|api-key))\s*:\s*)(['"])(?:\\[^\r\n]|(?!\3)[^\\\r\n])*\3/gi,"$1$3<redacted>$3").replace(/(['"]?\s*(?:authorization|cookie|x-api-key|api-key)\s*:(?!\s*(?:"<redacted>"|'<redacted>'))\s*)([^'"\r\n]+)(['"]?)/gi,"$1<redacted>$3").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/:@]+):([^\s@/]+)@/gi,"$1<redacted>:<redacted>@").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]+)@/gi,"$1<redacted>@").replace(/(^|[\s?&;|])((?:x-amz-signature|x-goog-signature|sig|signature)=)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^&#\s'"`;|<>()]*)/gi,"$1$2<redacted>").replace(/(^|\s)((?:-u|--user)(?:\s+|=))([^\s:]+):([^\s]+)/g,"$1$2<redacted>:<redacted>");for(let J of VW)Z=Z.replace(J,"<redacted>");return Z.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,"<redacted>").replace(/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,"<redacted>")}function RW($){return rZ($).reduceRight((J,Q)=>`${J.slice(0,Q.valueStart)}<redacted>${J.slice(Q.valueEnd)}`,$)}function kM($){return sZ(RW($))}function xM($){return rZ($).map((Z)=>$.slice(Z.valueStart,Z.valueEnd))}function lM($){return/[A-Za-z_][A-Za-z0-9_]*=/.test($)}function rZ($){let Z=[],J=/[A-Za-z_][A-Za-z0-9_]*=/g;for(let Q of $.matchAll(J)){let X=Q.index,W=$[X-1];if(X>0&&W&&!/[\s"'([{]/.test(W))continue;let K=X+Q[0].length;if(K>=$.length)continue;Z.push({valueStart:K,valueEnd:DW($,K)})}return Z}function DW($,Z){if($.startsWith("$(",Z))return zW($,Z);let J=$[Z];if(J==='"'||J==="'"){for(let X=Z+1;X<$.length;X++)if(J==='"'&&$[X]==="\\")X++;else if($[X]===J)return X+1}let Q=Z;while(Q<$.length&&!/\s/.test($[Q]??""))Q++;return Q}function zW($,Z){let J=0,Q;for(let X=Z;X<$.length;X++){let W=$[X];if(Q){if(Q==='"'&&W==="\\")X++;else if(W===Q)Q=void 0;continue}if(W==='"'||W==="'"){Q=W;continue}if(W==="$"&&$[X+1]==="("){J++,X++;continue}if(W!==")")continue;if(J--,J===0)return X+1}return $.length}var EW="2.0.8",TW=1e4,SW=2000,yW=256,wW=32768;function vW($){let Z=$.trim();if(!Z)return null;let J=Z.replace(/[^A-Za-z0-9_.-]+/g,"_");if(J=J.replace(/^[._-]+|[._-]+$/g,"").slice(0,128),!J||J==="."||J==="..")return null;return J}function uW($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function J6($,Z,J,Q,X,W={}){let K=vW($);if(!K)return;let Y=W.homeDir??nZ();if(!Y)return;let B=hW(Y);if(!B)return;try{let q=(W.now??(()=>new Date))().toISOString(),U=r2(B0(Z),TW),G=r2(B0(J),SW),j=W.toolName?r2(B0(W.toolName),yW):void 0,H=X===null?void 0:r2(B0(X),wW),_=Z6(B,uW(H?.value??null),q.slice(0,7));fW(_,{recursive:!0,mode:448});let O=Z6(_,`${q.slice(0,10)}-${K}.jsonl`),M={ts:q,id:(W.createId??(()=>IW(8).toString("hex")))(),v:EW,sessionId:K,decision:W.decision??"deny",agent:W.agent,shape:W.shape,level:W.level,configFallback:W.configFallback,toolName:j?.value,command:U.value,segment:G.value,...U.truncated||G.truncated||j?.truncated||H?.truncated?{truncated:!0}:{},reason:Q,ruleId:W.ruleId,intent:W.intent,failureStage:W.failureStage,errorCode:W.errorCode,cwd:H?.value??null};bW(O,`${JSON.stringify(M)}
3
3
  `,{encoding:"utf-8",mode:384}),dZ(B,W.now)}catch{}}function r2($,Z){return{value:$.slice(0,Z),truncated:$.length>Z}}function nZ($=process.env.CC_SAFETY_NET_AUDIT_HOME||process.env.HOME){let Z=$||PW()||CW().homedir;return Z&&AW(Z)?Z:null}function hW($=nZ()){return $?Z6($,".cc-safety-net","logs"):null}function oZ($,Z,J,Q=!0,X){if(Z.decision.kind==="allow"){if(!J||$.route.kind!=="command")return;let Y=aZ($);return{decision:"allow",command:Y,segment:Y,reason:"allowed",cwd:$.context.executionCwd,toolName:$.toolName,level:Z.level,...Z.configFallback?{configFallback:!0}:{}}}let W=Z.decision.evidence.find((Y)=>Y.kind==="command"),K=W?.command??(Q?aZ($):"");return{decision:"deny",command:K,segment:W?.segment??K,reason:Z.decision.reason,cwd:$.context.executionCwd,toolName:$.toolName,level:Z.level,...Z.configFallback?{configFallback:!0}:{},ruleId:Z.decision.ruleId,intent:Z.decision.intent,failureStage:X?.stage,errorCode:X?.errorCode}}function aZ($){return"command"in $?$.command??"":""}function tZ($,Z,J){if(!$)return;let Q;try{Q=Z()}catch{return}if(typeof Q!=="string"||!Q.trim())return;J6(Q,$.command,$.segment,$.reason,$.cwd,{homeDir:J.homeDir,decision:$.decision,agent:J.agent,shape:J.shape,level:$.level,configFallback:$.configFallback,toolName:$.toolName,ruleId:$.ruleId,intent:$.intent,failureStage:$.failureStage,errorCode:$.errorCode})}function tM($,Z,J){let Q;try{Q=Z()}catch{return}if(typeof Q!=="string"||!Q.trim())return;J6(Q,$.command??"",$.segment??$.command??"",$.reason,J.cwd??null,{homeDir:J.homeDir,decision:"deny",agent:J.agent,shape:J.shape,toolName:J.toolName??$.toolName,ruleId:$.ruleId,intent:$.intent})}var D0="Command could not be safely analyzed (strict mode). Simplify the command and retry, or ask the user to verify.",q0="Command exceeds maximum recursion depth and cannot be safely analyzed. Flatten the nesting and retry.",eZ="CC Safety Net could not validate the command because its structure exceeds safe analysis limits.",n2="CC Safety Net failed closed because command analysis failed unexpectedly. This is not caused by your command. Report it to the user.";function Z8($){let{reason:Z,command:J,segment:Q,toolName:X}=$,W=$.maxLen??200,K=$.redact??((B)=>B),Y=`BLOCKED by CC Safety Net
4
4
 
5
5
  Reason: ${K(Z)}`;if($.ruleId)Y+=`
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as B}from"./chunks/index-25nh5wqs.js";import{$ as O,M as W,N as F,O as z,P as L,Z as x,_ as M,jb as _,ma as N,nb as b,ua as k}from"./chunks/index-4pw6zr4t.js";import{accessSync as h,constants as R,statSync as w}from"node:fs";import{resolve as T}from"node:path";var P="cc-safety-net";function X(q){let Q=new Set(q??[]),J={},K={description:"Manage CC Safety Net rulebooks",template:B.slice(B.indexOf("## Workflow"))};if(!Q.has(P))J[P]=K;return J}var C=new Set(["powershell","pwsh"]),s=new Set(["bash","dash","ksh","sh","zsh"]);function A(q={}){return async({directory:Q,homeDir:J})=>{let K=T(Q),$;return{config:async(Z)=>{$=Z;let H=X(),j=Z.command??{};Z.command={...H,...j}},"tool.execute.before":async(Z,H)=>{let j=(V,g,m=K)=>{W(V,()=>Z.sessionID,{agent:"opencode",toolName:g,cwd:m,homeDir:J}),S(V)};if(typeof Z.tool!=="string"||Z.tool.trim()==="")j(z());let Y=H.args,y;try{y=O(Y)}catch(V){if(!(V instanceof x))throw V;j(z({toolName:Z.tool}),Z.tool)}let D=p($?.shell),E=c(Z.tool,D),G=u(K,Y);if(!I(K)||!G)return j(z({command:y,toolName:Z.tool}),Z.tool);let f={configCwd:K,executionCwd:G},v=k(Z.tool,Y,E,f,y??null);try{let V=b(v,{guard:{auditAllowed:N(),dependencies:q},audit:{agent:"opencode",homeDir:J,getSessionId:()=>Z.sessionID}});U(V,V.stage!=="config-state")}catch(V){if(!(V instanceof _))throw V;if(V.stage==="policy-protection"||V.stage==="config-load"||V.stage==="secret-protection")throw V.cause;U(V.evaluation,!0);return}}}}}function p(q,Q=process.platform,J=process.env.SHELL){if(typeof q!=="string"&&Q==="win32")return"powershell";let K=typeof q==="string"?q:J;if(typeof K!=="string")return"auto";let $=K.trim().split(/[\\/]/).at(-1)?.toLowerCase().replace(/\.exe$/,"");if(!$)return"auto";if(C.has($))return"powershell";if(s.has($))return"posix";return"auto"}function c(q,Q){if(q==="bash")return{kind:"command",shell:Q};return{kind:M(q)}}function u(q,Q){if(!Q||typeof Q!=="object"||Array.isArray(Q))return q;if(!Object.hasOwn(Q,"workdir"))return q;let J=Q.workdir;if(typeof J!=="string"||J.trim()==="")return null;let K=process.platform==="win32"?a(J):J,$=T(q,K);return I($)?$:null}function a(q){return q.replace(/^\/([a-zA-Z]):(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/cygdrive\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/mnt\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`)}function I(q){try{if(!w(q).isDirectory())return!1;return h(q,R.R_OK|R.X_OK),!0}catch{return!1}}function U(q,Q){let J=F(q,{includeEvidence:Q});if(J)S(J)}function S(q){throw Error(L(q))}var zq=A();export{zq as CCSafetyNetPlugin};
1
+ import{a as B}from"./chunks/index-25nh5wqs.js";import{$ as O,M as W,N as F,O as z,P as L,Z as x,_ as M,jb as _,ma as N,nb as b,ua as k}from"./chunks/index-hwg5anw1.js";import{accessSync as h,constants as R,statSync as w}from"node:fs";import{resolve as T}from"node:path";var P="cc-safety-net";function X(q){let Q=new Set(q??[]),J={},K={description:"Manage CC Safety Net rulebooks",template:B.slice(B.indexOf("## Workflow"))};if(!Q.has(P))J[P]=K;return J}var C=new Set(["powershell","pwsh"]),s=new Set(["bash","dash","ksh","sh","zsh"]);function A(q={}){return async({directory:Q,homeDir:J})=>{let K=T(Q),$;return{config:async(Z)=>{$=Z;let H=X(),j=Z.command??{};Z.command={...H,...j}},"tool.execute.before":async(Z,H)=>{let j=(V,g,m=K)=>{W(V,()=>Z.sessionID,{agent:"opencode",toolName:g,cwd:m,homeDir:J}),S(V)};if(typeof Z.tool!=="string"||Z.tool.trim()==="")j(z());let Y=H.args,y;try{y=O(Y)}catch(V){if(!(V instanceof x))throw V;j(z({toolName:Z.tool}),Z.tool)}let D=p($?.shell),E=c(Z.tool,D),G=u(K,Y);if(!I(K)||!G)return j(z({command:y,toolName:Z.tool}),Z.tool);let f={configCwd:K,executionCwd:G},v=k(Z.tool,Y,E,f,y??null);try{let V=b(v,{guard:{auditAllowed:N(),dependencies:q},audit:{agent:"opencode",homeDir:J,getSessionId:()=>Z.sessionID}});U(V,V.stage!=="config-state")}catch(V){if(!(V instanceof _))throw V;if(V.stage==="policy-protection"||V.stage==="config-load"||V.stage==="secret-protection")throw V.cause;U(V.evaluation,!0);return}}}}}function p(q,Q=process.platform,J=process.env.SHELL){if(typeof q!=="string"&&Q==="win32")return"powershell";let K=typeof q==="string"?q:J;if(typeof K!=="string")return"auto";let $=K.trim().split(/[\\/]/).at(-1)?.toLowerCase().replace(/\.exe$/,"");if(!$)return"auto";if(C.has($))return"powershell";if(s.has($))return"posix";return"auto"}function c(q,Q){if(q==="bash")return{kind:"command",shell:Q};return{kind:M(q)}}function u(q,Q){if(!Q||typeof Q!=="object"||Array.isArray(Q))return q;if(!Object.hasOwn(Q,"workdir"))return q;let J=Q.workdir;if(typeof J!=="string"||J.trim()==="")return null;let K=process.platform==="win32"?a(J):J,$=T(q,K);return I($)?$:null}function a(q){return q.replace(/^\/([a-zA-Z]):(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/cygdrive\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`).replace(/^\/mnt\/([a-zA-Z])(?:[\\/]|$)/,(J,K)=>`${K.toUpperCase()}:/`)}function I(q){try{if(!w(q).isDirectory())return!1;return h(q,R.R_OK|R.X_OK),!0}catch{return!1}}function U(q,Q){let J=F(q,{includeEvidence:Q});if(J)S(J)}function S(q){throw Error(L(q))}var zq=A();export{zq as CCSafetyNetPlugin};
@@ -1,7 +1,7 @@
1
1
  // cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw
2
- // version: 2.0.7
2
+ // version: 2.0.8
3
3
  var jM=Object.defineProperty;var RM=($)=>$;function bM($,J){this[$]=RM.bind(null,J)}var U2=($,J)=>{for(var Q in J)jM($,Q,{get:J[Q],enumerable:!0,configurable:!0,set:bM.bind(J,Q)})};var PK={id:"cc-safety-net",name:"CC Safety Net",description:"Block destructive commands and secret-file access before OpenClaw runs a tool."};import{randomBytes as _O}from"node:crypto";import{appendFileSync as DO,mkdirSync as zO}from"node:fs";import{homedir as IO,userInfo as jO}from"node:os";import{isAbsolute as RO,join as SJ}from"node:path";var PM=[/\bgh[pousr]_[A-Za-z0-9]{20,}\b/g,/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,/\bglpat-[A-Za-z0-9_-]{20,}\b/g,/\bxox[abeprs]-[A-Za-z0-9-]{20,}\b/g,/\bnpm_[A-Za-z0-9_]{20,}\b/g,/\bpypi-[A-Za-z0-9_-]{20,}\b/g,/\b[rs]k_(?:live|test)_[A-Za-z0-9_]{20,}\b/g,/\bsk-[A-Za-z0-9_-]{20,}\b/g,/\bsk_[A-Za-z0-9]{20,}\b/g,/\bgsk_[A-Za-z0-9]{52,}\b/g,/\bxai-[A-Za-z0-9_-]{80,}\b/g,/\bpplx-[A-Za-z0-9_-]{20,}\b/g,/\bbastn_[A-Za-z0-9]{16,}\b/g,/\btgp_v1_[A-Za-z0-9_-]{43,}\b/g,/\bflp_[A-Za-z0-9]{10,}\b/g,/\bwfr_[A-Za-z0-9]{20,}\b/g,/\bfwp?_[A-Za-z0-9_-]{20,}\b/g,/\btp-[A-Za-z0-9_-]{20,}\b/g,/\bpsk-[A-Za-z0-9_-]{8,}-[A-Za-z0-9_-]{8,}\b/g,/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/g];function A0($){let J=$.replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_DSN|CONNECTION_STRING)=("[^"]*"|'[^']*'|[^\s]+(?:\s+[A-Z_][A-Z0-9_]*=[^\s]+)*)/gi,"$1=<redacted>").replace(/\b((?:DATABASE|POSTGRES|POSTGRESQL|MYSQL|MARIADB|REDIS|MONGO(?:DB)?|DB)_(?:URL|URI|CONNECTION_STRING))=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>").replace(/\b([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|PASS|KEY|CREDENTIALS)[A-Z0-9_]*)=("[^"]*"|'[^']*'|[^\s]+)/gi,"$1=<redacted>");return AM(J)}function AM($){let J=$.replace(/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gi,"<redacted>").replace(/((?:(['"])(?:authorization|cookie|x-api-key|api-key)\2|(?:authorization|cookie|x-api-key|api-key))\s*:\s*)(['"])(?:\\[^\r\n]|(?!\3)[^\\\r\n])*\3/gi,"$1$3<redacted>$3").replace(/(['"]?\s*(?:authorization|cookie|x-api-key|api-key)\s*:(?!\s*(?:"<redacted>"|'<redacted>'))\s*)([^'"\r\n]+)(['"]?)/gi,"$1<redacted>$3").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/:@]+):([^\s@/]+)@/gi,"$1<redacted>:<redacted>@").replace(/\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]+)@/gi,"$1<redacted>@").replace(/(^|[\s?&;|])((?:x-amz-signature|x-goog-signature|sig|signature)=)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^&#\s'"`;|<>()]*)/gi,"$1$2<redacted>").replace(/(^|\s)((?:-u|--user)(?:\s+|=))([^\s:]+):([^\s]+)/g,"$1$2<redacted>:<redacted>");for(let Q of PM)J=J.replace(Q,"<redacted>");return J.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,"<redacted>").replace(/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,"<redacted>")}import{lstatSync as mK,readdirSync as KO,readFileSync as dK,rmdirSync as BO,statSync as lK,unlinkSync as qO,utimesSync as UO,writeFileSync as GO}from"node:fs";import{dirname as HO,join as r2}from"node:path";var b6=30,_J=1,DJ=365;function P6($){if(typeof $!=="number"||!Number.isInteger($))return 30;if($<1)return 1;return $>365?365:$}import{homedir as dM}from"node:os";import{dirname as p0,isAbsolute as rM,join as c0,relative as iM,resolve as C0,sep as oM}from"node:path";import{closeSync as EM,constants as AK,fstatSync as CM,fsyncSync as lE,lstatSync as EK,mkdirSync as pE,openSync as SM,readdirSync as cE,readFileSync as TM,realpathSync as A6,renameSync as dE,rmdirSync as rE,statSync as wM,unlinkSync as iE,writeFileSync as oE}from"node:fs";import{isAbsolute as CK,join as SK,normalize as vM,parse as fM,relative as zJ,resolve as IJ,sep as jJ}from"node:path";var kM=Symbol("PolicyFilesystemScope"),hM=Symbol("PolicyFilesystemTarget"),yM=AK.O_NOFOLLOW??0;class K1 extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function l0($,J){return{[kM]:!0,root:IJ($),label:J}}function TK($,J){let Q=vM(J);if(J===""||CK(J)||Q===".."||Q.startsWith(`..${jJ}`))throw new K1($.label);return{[hM]:!0,scope:$,relativePath:Q,path:SK($.root,Q)}}function E0($,J){let Q=zJ($.root,IJ(J));return TK($,Q)}function C6($,J="rules policy"){let Q=IJ($),W=fM(Q).dir;return TK(l0(W,J),zJ(W,Q))}function G2($){try{if(!E6($,!1).exists)return null;let Q=SM($.path,AK.O_RDONLY|yM);try{let W=CM(Q);if(!W.isFile())throw new K1($.scope.label);let X=TM(Q,"utf-8"),Y=EK($.path);if(!Y.isFile()||Y.isSymbolicLink()||W.dev!==Y.dev||W.ino!==Y.ino)throw new K1($.scope.label);return E6($,!1),X}finally{EM(Q)}}catch(J){uM($.scope.label,J)}}function wK($,J){if($.path===J.path)return!0;try{if(!E6($,!1).exists||!E6(J,!1).exists)return!1;return A6($.path)===A6(J.path)}catch(Q){if(Q instanceof K1)throw Q;throw new K1($.scope.label)}}function E6($,J,Q="file"){let W=gM($.scope);if(!W)return{exists:!1};let X=$.relativePath.split(jJ);for(let Y of X.keys()){let K=SK($.scope.root,...X.slice(0,Y+1)),B=vK(K);if(!B){if(Y===X.length-1&&J)return{exists:!1};return{exists:!1}}if(B.isSymbolicLink())throw new K1($.scope.label);if(Y<X.length-1&&!B.isDirectory())throw new K1($.scope.label);if(Y===X.length-1&&(Q==="file"?!B.isFile():!B.isDirectory()))throw new K1($.scope.label);xM(W,A6(K),$.scope.label)}return{exists:!0}}function gM($){if(!vK($.root))return null;if(!wM($.root).isDirectory())throw new K1($.label);return A6($.root)}function xM($,J,Q){let W=zJ($,J);if(W===".."||W.startsWith(`..${jJ}`)||CK(W))throw new K1(Q)}function vK($){try{return EK($)}catch(J){if(mM(J)&&J.code==="ENOENT")return null;throw J}}function uM($,J){if(J instanceof K1)throw J;throw new K1($)}function mM($){return $ instanceof Error&&"code"in $}var q0=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,RJ="rulebook.json",bJ=".cc-safety-net/rules";var fK=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;var lM=/^[A-Za-z0-9._-]+$/,pM=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),cM="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),kK=new RegExp(`^${pM}/(${q0.source.slice(1,-1)})/${cM}$`);function hK($){return`.cc-safety-net/rules/${$}/rulebook.json`}function n4($){if(T6($))try{return S6($),null}catch(J){return J instanceof Error?J.message:String(J)}return q0.test($)?null:`Local rulebook sources must be bare names matching ${q0}: ${$}`}function S6($){if($.startsWith("github:"))throw Error(`Invalid rulebook source: ${$}`);let J=$.match(fK);if(!J?.[1]||!J[2]||!J[3])throw Error(`Invalid GitHub rulebook source: ${$}`);let[Q,W,...X]=J[3].split("/");if(!Q||!lM.test(Q))throw Error(`GitHub rulebook refs must be a single path segment: ${$}`);if(!W||X.length>0||!q0.test(W))throw Error(`GitHub rulebook sources must be owner/repo#ref/<rulebook-name>: ${$}`);return{owner:J[1],repo:J[2],ref:Q,path:hK(W),name:W}}function T6($){return fK.test($)}var gK="rule.json",w6="policy.json",nM="rule.lock";var xK=".cc-safety-net",sM="rules",yK="cache",aM="CC_SAFETY_NET_HOME",d0="`cc-safety-net rule sync`";function tM($){return C0($??process.cwd(),bJ)}function eM($){return c0(tM($),gK)}function H2($){return $?.userConfigDir??($?.userConfigPath?p0($.userConfigPath):c0($O(),sM))}function $O(){let $=process.env[aM];return $?C0($):c0(dM(),xK)}function JO($){return c0(H2($),gK)}function s4($){return c0(p0($),nM)}function uK($){let J=$.userConfigPath??JO($),Q=$.projectConfigPath??eM($.cwd),W=QO(J,$),X=WO(Q,$);return{userConfigPath:J,projectConfigPath:Q,userLockPath:s4(J),projectLockPath:s4(Q),userScope:W,projectScope:X,userConfigTarget:E0(W,J),projectConfigTarget:E0(X,Q),userLockTarget:E0(W,s4(J)),projectLockTarget:E0(X,s4(Q))}}function QO($,J){let Q=J.userConfigPath?p0(p0(C0(J.userConfigPath))):p0(C0(J.userConfigDir??H2(J)));return l0(Q,"user policy")}function WO($,J){let Q=C0(J.cwd??process.cwd()),W=C0($),X=iM(Q,W);if(X!==".."&&!X.startsWith(`..${oM}`)&&!rM(X))return l0(Q,"project policy");return l0(p0(p0(W)),"project policy")}function PJ($,J){let Q=$.digest.startsWith("sha256:")?$.digest.slice(7):$.digest;return c0(YO(J),"rulebooks",`${XO($)}--${Q.slice(0,12)}`,RJ)}function AJ($,J){let Q=J;return{cacheConfigDir:$,cwd:J.cwd,global:Q.global}}function XO($){return($.kind==="github"&&$.display_ref?`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`:$.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function YO($){let J=$?.cacheConfigDir??H2($),Q=$;if(Q&&!Q.global&&Q.cwd&&C0(J)===C0(Q.cwd))return c0(C0(Q.cwd),xK,yK);return c0(p0(J),yK)}var CJ=86400000,ZO=".last-prune",LO=/^\d{4}-\d{2}$/,MO=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,pK=($)=>Math.floor($/CJ);function OO($){try{let J=r2(HO(H2($)),w6),Q=JSON.parse(dK(J,"utf-8"));return P6(Q?.audit?.retention_days)}catch{return b6}}function rK($,J=()=>new Date){try{let Q=J().getTime();if(!lK($,{throwIfNoEntry:!1})?.isDirectory())return;let W=r2($,ZO),X=lK(W,{throwIfNoEntry:!1})?.mtimeMs;if(X!==void 0&&pK(X)===pK(Q))return;let Y=Q-OO()*CJ,K=new Date(Q).toISOString().slice(0,7);for(let B of EJ($)){if(B.isDirectory()){NO(r2($,B.name),Y,K);continue}if(B.isFile()&&B.name.endsWith(".jsonl"))FO(r2($,B.name),Y)}GO(W,"",{mode:384}),UO(W,Q/1000,Q/1000)}catch{}}function NO($,J,Q){for(let W of EJ($)){if(!W.isDirectory()||!LO.test(W.name))continue;let X=r2($,W.name);for(let Y of EJ(X)){if(!Y.isFile())continue;let K=MO.exec(Y.name);if(!K||K[2]!==W.name)continue;let B=Date.parse(`${K[1]}T00:00:00.000Z`)+CJ;if(!Number.isFinite(B)||B>=J)continue;iK(r2(X,Y.name))}if(W.name!==Q)cK(X)}cK($)}function FO($,J){try{let Q=mK($);if(Q.mtimeMs>=J)return;let W=dK($,"utf-8").split(`
4
- `).filter((X)=>X.trim()).map(VO);if(W.length===0)return;if(W.some((X)=>X===void 0||X>=J))return;if(mK($).mtimeMs!==Q.mtimeMs)return;iK($)}catch{}}function VO($){try{let J=JSON.parse($).ts,Q=typeof J==="string"?Date.parse(J):Number.NaN;return Number.isFinite(Q)?Q:void 0}catch{return}}function EJ($){try{return KO($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function iK($){try{qO($)}catch{}}function cK($){try{BO($)}catch{}}var bO="2.0.7",PO=1e4,AO=2000,EO=256,CO=32768;function SO($){let J=$.trim();if(!J)return null;let Q=J.replace(/[^A-Za-z0-9_.-]+/g,"_");if(Q=Q.replace(/^[._-]+|[._-]+$/g,"").slice(0,128),!Q||Q==="."||Q==="..")return null;return Q}function TO($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function TJ($,J,Q,W,X,Y={}){let K=SO($);if(!K)return;let B=Y.homeDir??oK();if(!B)return;let q=wO(B);if(!q)return;try{let U=(Y.now??(()=>new Date))().toISOString(),G=v6(A0(J),PO),H=v6(A0(Q),AO),L=Y.toolName?v6(A0(Y.toolName),EO):void 0,Z=X===null?void 0:v6(A0(X),CO),M=SJ(q,TO(Z?.value??null),U.slice(0,7));zO(M,{recursive:!0,mode:448});let O=SJ(M,`${U.slice(0,10)}-${K}.jsonl`),V={ts:U,id:(Y.createId??(()=>_O(8).toString("hex")))(),v:bO,sessionId:K,decision:Y.decision??"deny",agent:Y.agent,shape:Y.shape,level:Y.level,configFallback:Y.configFallback,toolName:L?.value,command:G.value,segment:H.value,...G.truncated||H.truncated||L?.truncated||Z?.truncated?{truncated:!0}:{},reason:W,ruleId:Y.ruleId,intent:Y.intent,failureStage:Y.failureStage,errorCode:Y.errorCode,cwd:Z?.value??null};DO(O,`${JSON.stringify(V)}
4
+ `).filter((X)=>X.trim()).map(VO);if(W.length===0)return;if(W.some((X)=>X===void 0||X>=J))return;if(mK($).mtimeMs!==Q.mtimeMs)return;iK($)}catch{}}function VO($){try{let J=JSON.parse($).ts,Q=typeof J==="string"?Date.parse(J):Number.NaN;return Number.isFinite(Q)?Q:void 0}catch{return}}function EJ($){try{return KO($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function iK($){try{qO($)}catch{}}function cK($){try{BO($)}catch{}}var bO="2.0.8",PO=1e4,AO=2000,EO=256,CO=32768;function SO($){let J=$.trim();if(!J)return null;let Q=J.replace(/[^A-Za-z0-9_.-]+/g,"_");if(Q=Q.replace(/^[._-]+|[._-]+$/g,"").slice(0,128),!Q||Q==="."||Q==="..")return null;return Q}function TO($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function TJ($,J,Q,W,X,Y={}){let K=SO($);if(!K)return;let B=Y.homeDir??oK();if(!B)return;let q=wO(B);if(!q)return;try{let U=(Y.now??(()=>new Date))().toISOString(),G=v6(A0(J),PO),H=v6(A0(Q),AO),L=Y.toolName?v6(A0(Y.toolName),EO):void 0,Z=X===null?void 0:v6(A0(X),CO),M=SJ(q,TO(Z?.value??null),U.slice(0,7));zO(M,{recursive:!0,mode:448});let O=SJ(M,`${U.slice(0,10)}-${K}.jsonl`),V={ts:U,id:(Y.createId??(()=>_O(8).toString("hex")))(),v:bO,sessionId:K,decision:Y.decision??"deny",agent:Y.agent,shape:Y.shape,level:Y.level,configFallback:Y.configFallback,toolName:L?.value,command:G.value,segment:H.value,...G.truncated||H.truncated||L?.truncated||Z?.truncated?{truncated:!0}:{},reason:W,ruleId:Y.ruleId,intent:Y.intent,failureStage:Y.failureStage,errorCode:Y.errorCode,cwd:Z?.value??null};DO(O,`${JSON.stringify(V)}
5
5
  `,{encoding:"utf-8",mode:384}),rK(q,Y.now)}catch{}}function v6($,J){return{value:$.slice(0,J),truncated:$.length>J}}function oK($=process.env.CC_SAFETY_NET_AUDIT_HOME||process.env.HOME){let J=$||IO()||jO().homedir;return J&&RO(J)?J:null}function wO($=oK()){return $?SJ($,".cc-safety-net","logs"):null}function sK($,J,Q,W=!0,X){if(J.decision.kind==="allow"){if(!Q||$.route.kind!=="command")return;let B=nK($);return{decision:"allow",command:B,segment:B,reason:"allowed",cwd:$.context.executionCwd,toolName:$.toolName,level:J.level,...J.configFallback?{configFallback:!0}:{}}}let Y=J.decision.evidence.find((B)=>B.kind==="command"),K=Y?.command??(W?nK($):"");return{decision:"deny",command:K,segment:Y?.segment??K,reason:J.decision.reason,cwd:$.context.executionCwd,toolName:$.toolName,level:J.level,...J.configFallback?{configFallback:!0}:{},ruleId:J.decision.ruleId,intent:J.decision.intent,failureStage:X?.stage,errorCode:X?.errorCode}}function nK($){return"command"in $?$.command??"":""}function aK($,J,Q){if(!$)return;let W;try{W=J()}catch{return}if(typeof W!=="string"||!W.trim())return;TJ(W,$.command,$.segment,$.reason,$.cwd,{homeDir:Q.homeDir,decision:$.decision,agent:Q.agent,shape:Q.shape,level:$.level,configFallback:$.configFallback,toolName:$.toolName,ruleId:$.ruleId,intent:$.intent,failureStage:$.failureStage,errorCode:$.errorCode})}function tK($,J,Q){let W;try{W=J()}catch{return}if(typeof W!=="string"||!W.trim())return;TJ(W,$.command??"",$.segment??$.command??"",$.reason,Q.cwd??null,{homeDir:Q.homeDir,decision:"deny",agent:Q.agent,shape:Q.shape,toolName:Q.toolName??$.toolName,ruleId:$.ruleId,intent:$.intent})}import{realpathSync as uO,statSync as mO}from"node:fs";import{isAbsolute as $B,relative as lO,resolve as pO,sep as cO}from"node:path";import{dirname as vO,isAbsolute as fO,parse as kO,sep as hO}from"node:path";function Z2($,J=process.platform){if(J!=="win32")return!1;return($[0]==="/"||$[0]==="\\")&&($[1]==="/"||$[1]==="\\")}function r0($,J,Q){if(Z2(J))throw Error("Unsupported Windows namespace path");let W=fO(J)?gO(J):"",X=W||$;for(let Y of xO(W?J.slice(W.length):J)){if(Y===""||Y===".")continue;if(Y===".."){X=vO(X);continue}let K=yO(X,Y),B=Q.entryKind(K),q=B==="symlink"?Q.realpath(K):K;if(B==="missing"||q===null)throw Error(`Cannot resolve path component: ${K}`);X=q}return X}function yO($,J){return $.endsWith("/")||$.endsWith("\\")?`${$}${J}`:`${$}${hO}${J}`}function gO($){return kO($).root}function xO($){let J=process.platform==="win32"?/[\\/]+/:/\/+/;return $.split(J)}function f6($,J){if(Z2($))return;let Q=J.flatMap((X)=>eK(X));if(!Q[0])return;let W=eK($B($)?$:pO(Q[0],$))[0];if(!W)return;return Q.some((X)=>JB(W,X))?W:void 0}function eK($){try{let J=uO($);return mO(J).isDirectory()?[J]:[]}catch{return[]}}function JB($,J){let Q=lO(J,$);return Q===""||Q!==".."&&!Q.startsWith(`..${cO}`)&&!$B(Q)}var i0="Command could not be safely analyzed (strict mode). Simplify the command and retry, or ask the user to verify.",S0="Command exceeds maximum recursion depth and cannot be safely analyzed. Flatten the nesting and retry.",QB="CC Safety Net could not validate the command because its structure exceeds safe analysis limits.",k6="CC Safety Net failed closed because command analysis failed unexpectedly. This is not caused by your command. Report it to the user.";function XB($){let{reason:J,command:Q,segment:W,toolName:X}=$,Y=$.maxLen??200,K=$.redact??((q)=>q),B=`BLOCKED by CC Safety Net
6
6
 
7
7
  Reason: ${K(J)}`;if($.ruleId)B+=`
@@ -2,7 +2,7 @@
2
2
  "id": "cc-safety-net",
3
3
  "name": "CC Safety Net",
4
4
  "description": "Block destructive commands and secret-file access before OpenClaw runs a tool.",
5
- "version": "2.0.7",
5
+ "version": "2.0.8",
6
6
  "activation": {
7
7
  "onStartup": true
8
8
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safety-net",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "description": "Block destructive commands and secret-file access before OpenClaw runs a tool.",
5
5
  "type": "module",
6
6
  "openclaw": {
package/dist/pi/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{a as $}from"../chunks/index-25nh5wqs.js";import{M as Q,N as W,O as f,P as k,Q as y,_ as Y,jb as L,ka as F,kb as b,ma as G,nb as I,oa as U,ua as j}from"../chunks/index-4pw6zr4t.js";var R="cc-safety-net",w="Manage CC Safety Net rulebooks",S="Help me configure CC Safety Net.";function B(z){z.registerCommand(R,{description:w,handler:async(H,q)=>{z.sendUserMessage(D(H),q.isIdle()?void 0:{deliverAs:"followUp"})}})}function D(z){return`${$.slice($.indexOf("## Workflow")).trimEnd()}
1
+ import{a as $}from"../chunks/index-25nh5wqs.js";import{M as Q,N as W,O as f,P as k,Q as y,_ as Y,jb as L,ka as F,kb as b,ma as G,nb as I,oa as U,ua as j}from"../chunks/index-hwg5anw1.js";var R="cc-safety-net",w="Manage CC Safety Net rulebooks",S="Help me configure CC Safety Net.";function B(z){z.registerCommand(R,{description:w,handler:async(H,q)=>{z.sendUserMessage(D(H),q.isIdle()?void 0:{deliverAs:"followUp"})}})}function D(z){return`${$.slice($.indexOf("## Workflow")).trimEnd()}
2
2
 
3
3
  ## User request
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-safety-net",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "description": "A coding agent CLI hook - block destructive commands and secret file access",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -103,5 +103,5 @@
103
103
  "cursor",
104
104
  "amp"
105
105
  ],
106
- "gitHead": "5c5eace87adc0db41ba762018a1cf7d1506e589c"
106
+ "gitHead": "299f19c8c0c8f59cc332a2d58c272138fe368e81"
107
107
  }