cc-safety-net 2.0.4 → 2.0.5

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
  var zX=[/\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 Q0($){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 XZ(Z)}function XZ($){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 zX)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 bX($){return KZ($).reduceRight((J,Q)=>`${J.slice(0,Q.valueStart)}<redacted>${J.slice(Q.valueEnd)}`,$)}function cL($){return XZ(bX($))}function dL($){return KZ($).map((Z)=>$.slice(Z.valueStart,Z.valueEnd))}function iL($){return/[A-Za-z_][A-Za-z0-9_]*=/.test($)}function KZ($){let Z=[],J=/[A-Za-z_][A-Za-z0-9_]*=/g;for(let Q of $.matchAll(J)){let X=Q.index,K=$[X-1];if(X>0&&K&&!/[\s"'([{]/.test(K))continue;let Y=X+Q[0].length;if(Y>=$.length)continue;Z.push({valueStart:Y,valueEnd:IX($,Y)})}return Z}function IX($,Z){if($.startsWith("$(",Z))return fX($,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 fX($,Z){let J=0,Q;for(let X=Z;X<$.length;X++){let K=$[X];if(Q){if(Q==='"'&&K==="\\")X++;else if(K===Q)Q=void 0;continue}if(K==='"'||K==="'"){Q=K;continue}if(K==="$"&&$[X+1]==="("){J++,X++;continue}if(K!==")")continue;if(J--,J===0)return X+1}return $.length}import{randomBytes as PX}from"node:crypto";import{closeSync as v3,constants as g$,fstatSync as y3,fsyncSync as CX,lstatSync as F0,mkdirSync as YZ,openSync as BZ,readdirSync as u3,readFileSync as AX,realpathSync as A0,renameSync as EX,rmdirSync as TX,statSync as w3,unlinkSync as h3,writeFileSync as SX}from"node:fs";import{isAbsolute as WZ,join as $$,normalize as yX,parse as qZ,relative as g3,resolve as k3,sep as x$}from"node:path";var wX=Symbol("PolicyFilesystemScope"),vX=Symbol("PolicyFilesystemTarget"),UZ=g$.O_NOFOLLOW??0;class u extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function D1($,Z){return{[wX]:!0,root:k3($),label:Z}}function l$($,Z){let J=yX(Z);if(Z===""||WZ(Z)||J===".."||J.startsWith(`..${x$}`))throw new u($.label);return{[vX]:!0,scope:$,relativePath:J,path:$$($.root,J)}}function X1($,Z){let J=g3($.root,k3(Z));return l$($,J)}function u2($,Z="rules policy"){let J=k3($),Q=qZ(J).dir;return l$(D1(Q,Z),g3(Q,J))}function X0($){try{if(!W1($,!1).exists)return null;let J=BZ($.path,g$.O_RDONLY|UZ);try{let Q=y3(J);if(!Q.isFile())throw new u($.scope.label);let X=AX(J,"utf-8"),K=F0($.path);if(!K.isFile()||K.isSymbolicLink()||Q.dev!==K.dev||Q.ino!==K.ino)throw new u($.scope.label);return W1($,!1),X}finally{v3(J)}}catch(Z){N0($.scope.label,Z)}}function GZ($,Z,J=384,Q){let X=`${$.path}.${PX(8).toString("hex")}.tmp`,K=null;try{gX($),W1($,!0),K=BZ(X,g$.O_CREAT|g$.O_EXCL|g$.O_WRONLY|UZ,J);let Y=y3(K);if(!Y.isFile())throw new u($.scope.label);SX(K,Z,"utf-8"),CX(K);let B=y3(K);if(!B.isFile()||B.dev!==Y.dev||B.ino!==Y.ino)throw new u($.scope.label);v3(K),K=null,W1($,!0),xX($,X,B.dev,B.ino),EX(X,$.path),Q?.($.path),W1($,!1)}catch(Y){if(K!==null)mX(K);pX(X),N0($.scope.label,Y)}}function HZ($,Z){if($.path===Z.path)return!0;try{if(!W1($,!1).exists||!W1(Z,!1).exists)return!1;return A0($.path)===A0(Z.path)}catch(J){if(J instanceof u)throw J;throw new u($.scope.label)}}function uX($){try{if(!W1($,!1,"directory").exists)return null;let J=u3($.path);return W1($,!1,"directory"),J}catch(Z){N0($.scope.label,Z)}}function oL($){let Z=uX($);if(!Z)return null;try{let J=Z.map((Q)=>{let X=l$($.scope,$$($.relativePath,Q)),K=F0(X.path);if(K.isSymbolicLink()||!K.isFile()&&!K.isDirectory())throw new u($.scope.label);return h2(LZ($.scope),A0(X.path),$.scope.label),{name:Q,kind:K.isDirectory()?"directory":"file"}});return W1($,!1,"directory"),J}catch(J){N0($.scope.label,J)}}function tL($){try{if(!W1($,!0).exists)return;h3($.path),W1($,!0)}catch(Z){N0($.scope.label,Z)}}function eL($){try{OZ($,$.relativePath.split(x$))}catch(Z){N0($.scope.label,Z)}}function $M($){try{if(!hX($))return;_Z($),W1($,!0,"directory")}catch(Z){N0($.scope.label,Z)}}function hX($){try{if(!W1($,!0,"directory").exists)return!1;return jZ($),!0}catch(Z){N0($.scope.label,Z)}}function W1($,Z,J="file"){let Q=x3($.scope);if(!Q)return{exists:!1};let X=$.relativePath.split(x$);for(let K of X.keys()){let Y=$$($.scope.root,...X.slice(0,K+1)),B=k$(Y);if(!B){if(K===X.length-1&&Z)return{exists:!1};return{exists:!1}}if(B.isSymbolicLink())throw new u($.scope.label);if(K<X.length-1&&!B.isDirectory())throw new u($.scope.label);if(K===X.length-1&&(J==="file"?!B.isFile():!B.isDirectory()))throw new u($.scope.label);h2(Q,A0(Y),$.scope.label)}return{exists:!0}}function jZ($){for(let Z of u3($.path)){let J=l$($.scope,$$($.relativePath,Z)),Q=F0(J.path);if(Q.isSymbolicLink()||!Q.isDirectory()&&!Q.isFile())throw new u($.scope.label);if(Q.isDirectory())jZ(J)}W1($,!1,"directory")}function _Z($){for(let Z of u3($.path)){let J=l$($.scope,$$($.relativePath,Z)),Q=F0(J.path);if(Q.isSymbolicLink())throw new u($.scope.label);if(Q.isDirectory()){_Z(J);continue}if(!Q.isFile())throw new u($.scope.label);h3(J.path)}TX($.path)}function gX($){OZ($,$.relativePath.split(x$).slice(0,-1))}function OZ($,Z){kX($.scope);let J=LZ($.scope);for(let Q of Z.keys()){let X=$$($.scope.root,...Z.slice(0,Q+1));if(!k$(X))YZ(X,{mode:448});let Y=F0(X);if(!Y.isDirectory()||Y.isSymbolicLink())throw new u($.scope.label);h2(J,A0(X),$.scope.label)}}function kX($){if(k$($.root)){if(!w3($.root).isDirectory())throw new u($.label);return}let Z=[],J=$.root;while(!k$(J)){Z.unshift(J);let Q=qZ(J).dir;if(Q===J)throw new u($.label);J=Q}if(!w3(J).isDirectory())throw new u($.label);for(let Q of Z){YZ(Q,{mode:448});let X=F0(Q);if(!X.isDirectory()||X.isSymbolicLink())throw new u($.label)}}function x3($){if(!k$($.root))return null;if(!w3($.root).isDirectory())throw new u($.label);return A0($.root)}function LZ($){let Z=x3($);if(!Z)throw new u($.label);return Z}function xX($,Z,J,Q){let X=F0(Z);if(!X.isFile()||X.isSymbolicLink()||X.dev!==J||X.ino!==Q)throw new u($.scope.label);let K=x3($.scope);if(!K)throw new u($.scope.label);h2(K,A0(Z),$.scope.label)}function h2($,Z,J){let Q=g3($,Z);if(Q===".."||Q.startsWith(`..${x$}`)||WZ(Q))throw new u(J)}function k$($){try{return F0($)}catch(Z){if(lX(Z)&&Z.code==="ENOENT")return null;throw Z}}function N0($,Z){if(Z instanceof u)throw Z;throw new u($)}function lX($){return $ instanceof Error&&"code"in $}function mX($){try{v3($)}catch{}}function pX($){try{h3($)}catch{}}import{homedir as rX}from"node:os";import{dirname as m1,isAbsolute as nX,join as T1,relative as aX,resolve as p1,sep as oX}from"node:path";var z1=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,g2="rulebook.json",k2=".cc-safety-net/rules";var MZ=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/,cX=/^[A-Za-z0-9][A-Za-z0-9_.-]*\/[A-Za-z0-9_.-]+$/,dX=/^[A-Za-z0-9._-]+$/,iX=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),sX="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l3=new RegExp(`^${iX}/(${z1.source.slice(1,-1)})/${sX}$`);function FZ($){return`.cc-safety-net/rules/${$}/rulebook.json`}function m$($){if(J$($))try{return Z$($),null}catch(Z){return Z instanceof Error?Z.message:String(Z)}return z1.test($)?null:`Local rulebook sources must be bare names matching ${z1}: ${$}`}function Z$($){if($.startsWith("github:"))throw Error(`Invalid rulebook source: ${$}`);let Z=$.match(MZ);if(!Z?.[1]||!Z[2]||!Z[3])throw Error(`Invalid GitHub rulebook source: ${$}`);let[J,Q,...X]=Z[3].split("/");if(!J||!dX.test(J))throw Error(`GitHub rulebook refs must be a single path segment: ${$}`);if(!Q||X.length>0||!z1.test(Q))throw Error(`GitHub rulebook sources must be owner/repo#ref/<rulebook-name>: ${$}`);return{owner:Z[1],repo:Z[2],ref:J,path:FZ(Q),name:Q}}function NZ($){return cX.test($)}function J$($){return MZ.test($)}function m3($){if(!z1.test($))throw Error(`Local rulebook sources must be bare names matching ${z1}: ${$}`)}var RZ="rule.json",x2="policy.json",DZ="rule.lock",tX="config.json",zZ=".cc-safety-net",eX="rules",VZ="cache",$K="CC_SAFETY_NET_HOME",S1="`cc-safety-net rule sync`";function ZK($){return p1($??process.cwd(),k2)}function bZ($){return T1(ZK($),RZ)}function K0($){return $?.userConfigDir??($?.userConfigPath?m1($.userConfigPath):T1(JK(),eX))}function JK(){let $=process.env[$K];return $?p1($):T1(rX(),zZ)}function IZ($){return T1(K0($),RZ)}function WM($){return T1(K0($),DZ)}function E0($){return T1(m1($),DZ)}function qM($={}){return T1(m1(K0($)),tX)}function UM($={}){return p1($.cwd??process.cwd(),".safety-net.json")}function fZ($){let Z=$.userConfigPath??IZ($),J=$.projectConfigPath??bZ($.cwd),Q=PZ(Z,$),X=CZ(J,$);return{userConfigPath:Z,projectConfigPath:J,userLockPath:E0(Z),projectLockPath:E0(J),userScope:Q,projectScope:X,userConfigTarget:X1(Q,Z),projectConfigTarget:X1(X,J),userLockTarget:X1(Q,E0(Z)),projectLockTarget:X1(X,E0(J))}}function GM($){let Z=$.global?$.userConfigPath??IZ($):$.projectConfigPath??bZ($.cwd),J=$.global?PZ(Z,$):CZ(Z,$),Q=E0(Z);return{configDir:m1(Z),configPath:Z,lockPath:Q,filesystemScope:J,configTarget:X1(J,Z),lockTarget:X1(J,Q)}}function PZ($,Z){let J=Z.userConfigPath?m1(m1(p1(Z.userConfigPath))):m1(p1(Z.userConfigDir??K0(Z)));return D1(J,"user policy")}function CZ($,Z){let J=p1(Z.cwd??process.cwd()),Q=p1($),X=aX(J,Q);if(X!==".."&&!X.startsWith(`..${oX}`)&&!nX(X))return D1(J,"project policy");return D1(m1(m1(Q)),"project policy")}function AZ($){if($.kind==="github"&&$.display_ref)return`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`;return $.spec}function l2($,Z){let J=$.digest.startsWith("sha256:")?$.digest.slice(7):$.digest;return T1(EZ(Z),"rulebooks",`${QK($)}--${J.slice(0,12)}`,g2)}function HM($){return T1(EZ($),"rulebooks")}function m2($,Z){let J=Z;return{cacheConfigDir:$,cwd:Z.cwd,global:J.global}}function QK($){return($.kind==="github"&&$.display_ref?`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`:$.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function EZ($){let Z=$?.cacheConfigDir??K0($),J=$;if(J&&!J.global&&J.cwd&&p1(Z)===p1(J.cwd))return T1(p1(J.cwd),zZ,VZ);return T1(m1(Z),VZ)}import{lstatSync as TZ,readdirSync as XK,readFileSync as vZ,rmdirSync as KK,statSync as SZ,unlinkSync as YK,utimesSync as BK,writeFileSync as WK}from"node:fs";import{dirname as qK,join as Q$}from"node:path";var p2=30,p3=1,c3=365;function c2($){if(typeof $!=="number"||!Number.isInteger($))return 30;if($<1)return 1;return $>365?365:$}var i3=86400000,UK=".last-prune",GK=/^\d{4}-\d{2}$/,HK=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,yZ=($)=>Math.floor($/i3);function jK($){try{let Z=Q$(qK(K0($)),x2),J=JSON.parse(vZ(Z,"utf-8"));return c2(J?.audit?.retention_days)}catch{return p2}}function uZ($,Z=()=>new Date){try{let J=Z().getTime();if(!SZ($,{throwIfNoEntry:!1})?.isDirectory())return;let Q=Q$($,UK),X=SZ(Q,{throwIfNoEntry:!1})?.mtimeMs;if(X!==void 0&&yZ(X)===yZ(J))return;let K=J-jK()*i3,Y=new Date(J).toISOString().slice(0,7);for(let B of d3($)){if(B.isDirectory()){_K(Q$($,B.name),K,Y);continue}if(B.isFile()&&B.name.endsWith(".jsonl"))OK(Q$($,B.name),K)}WK(Q,"",{mode:384}),BK(Q,J/1000,J/1000)}catch{}}function _K($,Z,J){for(let Q of d3($)){if(!Q.isDirectory()||!GK.test(Q.name))continue;let X=Q$($,Q.name);for(let K of d3(X)){if(!K.isFile())continue;let Y=HK.exec(K.name);if(!Y||Y[2]!==Q.name)continue;let B=Date.parse(`${Y[1]}T00:00:00.000Z`)+i3;if(!Number.isFinite(B)||B>=Z)continue;hZ(Q$(X,K.name))}if(Q.name!==J)wZ(X)}wZ($)}function OK($,Z){try{let J=TZ($);if(J.mtimeMs>=Z)return;let Q=vZ($,"utf-8").split(`
2
- `).filter((X)=>X.trim()).map(LK);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(TZ($).mtimeMs!==J.mtimeMs)return;hZ($)}catch{}}function LK($){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 d3($){try{return XK($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function hZ($){try{YK($)}catch{}}function wZ($){try{KK($)}catch{}}import{randomBytes as MK}from"node:crypto";import{appendFileSync as FK,mkdirSync as NK}from"node:fs";import{homedir as VK,userInfo as RK}from"node:os";import{isAbsolute as DK,join as s3}from"node:path";var zK="2.0.4",bK=1e4,IK=2000,fK=256,PK=32768;function CK($){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 AK($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function r3($,Z,J,Q,X,K={}){let Y=CK($);if(!Y)return;let B=K.homeDir??gZ();if(!B)return;let W=EK(B);if(!W)return;try{let q=(K.now??(()=>new Date))().toISOString(),U=d2(Q0(Z),bK),H=d2(Q0(J),IK),j=K.toolName?d2(Q0(K.toolName),fK):void 0,G=X===null?void 0:d2(Q0(X),PK),_=s3(W,AK(G?.value??null),q.slice(0,7));NK(_,{recursive:!0,mode:448});let O=s3(_,`${q.slice(0,10)}-${Y}.jsonl`),M={ts:q,id:(K.createId??(()=>MK(8).toString("hex")))(),v:zK,sessionId:Y,decision:K.decision??"deny",agent:K.agent,shape:K.shape,level:K.level,configFallback:K.configFallback,toolName:j?.value,command:U.value,segment:H.value,...U.truncated||H.truncated||j?.truncated||G?.truncated?{truncated:!0}:{},reason:Q,ruleId:K.ruleId,intent:K.intent,failureStage:K.failureStage,errorCode:K.errorCode,cwd:G?.value??null};FK(O,`${JSON.stringify(M)}
2
+ `).filter((X)=>X.trim()).map(LK);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(TZ($).mtimeMs!==J.mtimeMs)return;hZ($)}catch{}}function LK($){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 d3($){try{return XK($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function hZ($){try{YK($)}catch{}}function wZ($){try{KK($)}catch{}}import{randomBytes as MK}from"node:crypto";import{appendFileSync as FK,mkdirSync as NK}from"node:fs";import{homedir as VK,userInfo as RK}from"node:os";import{isAbsolute as DK,join as s3}from"node:path";var zK="2.0.5",bK=1e4,IK=2000,fK=256,PK=32768;function CK($){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 AK($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function r3($,Z,J,Q,X,K={}){let Y=CK($);if(!Y)return;let B=K.homeDir??gZ();if(!B)return;let W=EK(B);if(!W)return;try{let q=(K.now??(()=>new Date))().toISOString(),U=d2(Q0(Z),bK),H=d2(Q0(J),IK),j=K.toolName?d2(Q0(K.toolName),fK):void 0,G=X===null?void 0:d2(Q0(X),PK),_=s3(W,AK(G?.value??null),q.slice(0,7));NK(_,{recursive:!0,mode:448});let O=s3(_,`${q.slice(0,10)}-${Y}.jsonl`),M={ts:q,id:(K.createId??(()=>MK(8).toString("hex")))(),v:zK,sessionId:Y,decision:K.decision??"deny",agent:K.agent,shape:K.shape,level:K.level,configFallback:K.configFallback,toolName:j?.value,command:U.value,segment:H.value,...U.truncated||H.truncated||j?.truncated||G?.truncated?{truncated:!0}:{},reason:Q,ruleId:K.ruleId,intent:K.intent,failureStage:K.failureStage,errorCode:K.errorCode,cwd:G?.value??null};FK(O,`${JSON.stringify(M)}
3
3
  `,{encoding:"utf-8",mode:384}),uZ(W,K.now)}catch{}}function d2($,Z){return{value:$.slice(0,Z),truncated:$.length>Z}}function gZ($=process.env.CC_SAFETY_NET_AUDIT_HOME||process.env.HOME){let Z=$||VK()||RK().homedir;return Z&&DK(Z)?Z:null}function EK($=gZ()){return $?s3($,".cc-safety-net","logs"):null}function xZ($,Z,J,Q=!0,X){if(Z.decision.kind==="allow"){if(!J||$.route.kind!=="command")return;let B=kZ($);return{decision:"allow",command:B,segment:B,reason:"allowed",cwd:$.context.executionCwd,toolName:$.toolName,level:Z.level,...Z.configFallback?{configFallback:!0}:{}}}let K=Z.decision.evidence.find((B)=>B.kind==="command"),Y=K?.command??(Q?kZ($):"");return{decision:"deny",command:Y,segment:K?.segment??Y,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 kZ($){return"command"in $?$.command??"":""}function lZ($,Z,J){if(!$)return;let Q;try{Q=Z()}catch{return}if(typeof Q!=="string"||!Q.trim())return;r3(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 EM($,Z,J){let Q;try{Q=Z()}catch{return}if(typeof Q!=="string"||!Q.trim())return;r3(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 V0="Command could not be safely analyzed (strict mode). Simplify the command and retry, or ask the user to verify.",Y0="Command exceeds maximum recursion depth and cannot be safely analyzed. Flatten the nesting and retry.",mZ="CC Safety Net could not validate the command because its structure exceeds safe analysis limits.",i2="CC Safety Net failed closed because command analysis failed unexpectedly. This is not caused by your command. Report it to the user.";function cZ($){let{reason:Z,command:J,segment:Q,toolName:X}=$,K=$.maxLen??200,Y=$.redact??((W)=>W),B=`BLOCKED by CC Safety Net
4
4
 
5
5
  Reason: ${Y(Z)}`;if($.ruleId)B+=`
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as B}from"./chunks/index-25nh5wqs.js";import{$ as O,M as F,N as W,O as H,P as L,Z as x,_ as M,ib as b,la as N,mb as k,ta as _}from"./chunks/index-xvfhq21r.js";import{accessSync as m,constants as R,statSync as w}from"node:fs";import{resolve as S}from"node:path";var P="cc-safety-net";function X(q){let J=new Set(q??[]),K={},Q={description:"Manage CC Safety Net rulebooks",template:B.slice(B.indexOf("## Workflow"))};if(!J.has(P))K[P]=Q;return K}var C=new Set(["powershell","pwsh"]),s=new Set(["bash","dash","ksh","sh","zsh"]);function T(q={}){return async({directory:J,homeDir:K})=>{let Q=S(J),$;return{config:async(Z)=>{$=Z;let Y=X(),j=Z.command??{};Z.command={...Y,...j}},"tool.execute.before":async(Z,Y)=>{let j=(V,g,h=Q)=>{F(V,()=>Z.sessionID,{agent:"opencode",toolName:g,cwd:h,homeDir:K}),I(V)};if(typeof Z.tool!=="string"||Z.tool.trim()==="")j(H());let y=Y.args,z;try{z=O(y)}catch(V){if(!(V instanceof x))throw V;j(H({toolName:Z.tool}),Z.tool)}let D=p($?.shell),f=c(Z.tool,D),G=u(Q,y);if(!A(Q)||!G)return j(H({command:z,toolName:Z.tool}),Z.tool);let E={configCwd:Q,executionCwd:G},v=_(Z.tool,y,f,E,z??null);try{let V=k(v,{guard:{auditAllowed:N(),dependencies:q},audit:{agent:"opencode",homeDir:K,getSessionId:()=>Z.sessionID}});U(V,V.stage!=="config-state")}catch(V){if(!(V instanceof b))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){if(typeof q!=="string")return"auto";let J=q.trim().split(/[\\/]/).at(-1)?.toLowerCase().replace(/\.exe$/,"");if(!J)return"auto";if(C.has(J))return"powershell";if(s.has(J))return"posix";return"auto"}function c(q,J){if(q==="bash")return{kind:"command",shell:J};return{kind:M(q)}}function u(q,J){if(!J||typeof J!=="object"||Array.isArray(J))return q;if(!Object.hasOwn(J,"workdir"))return q;let K=J.workdir;if(typeof K!=="string"||K.trim()==="")return null;let Q=process.platform==="win32"?a(K):K;if(!Q)return null;let $=S(q,Q);return A($)?$:null}function a(q){let J=q.replace(/^\/([a-zA-Z]):(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/cygdrive\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/mnt\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`);return J.startsWith("/")?null:J}function A(q){try{if(!w(q).isDirectory())return!1;return m(q,R.R_OK|R.X_OK),!0}catch{return!1}}function U(q,J){let K=W(q,{includeEvidence:J});if(K)I(K)}function I(q){throw Error(L(q))}var Hq=T();export{Hq as CCSafetyNetPlugin};
1
+ import{a as B}from"./chunks/index-25nh5wqs.js";import{$ as O,M as F,N as W,O as H,P as L,Z as x,_ as M,ib as b,la as N,mb as k,ta as _}from"./chunks/index-bmvm3x9s.js";import{accessSync as m,constants as R,statSync as w}from"node:fs";import{resolve as S}from"node:path";var P="cc-safety-net";function X(q){let J=new Set(q??[]),K={},Q={description:"Manage CC Safety Net rulebooks",template:B.slice(B.indexOf("## Workflow"))};if(!J.has(P))K[P]=Q;return K}var C=new Set(["powershell","pwsh"]),s=new Set(["bash","dash","ksh","sh","zsh"]);function T(q={}){return async({directory:J,homeDir:K})=>{let Q=S(J),$;return{config:async(Z)=>{$=Z;let Y=X(),j=Z.command??{};Z.command={...Y,...j}},"tool.execute.before":async(Z,Y)=>{let j=(V,g,h=Q)=>{F(V,()=>Z.sessionID,{agent:"opencode",toolName:g,cwd:h,homeDir:K}),I(V)};if(typeof Z.tool!=="string"||Z.tool.trim()==="")j(H());let y=Y.args,z;try{z=O(y)}catch(V){if(!(V instanceof x))throw V;j(H({toolName:Z.tool}),Z.tool)}let D=p($?.shell),f=c(Z.tool,D),G=u(Q,y);if(!A(Q)||!G)return j(H({command:z,toolName:Z.tool}),Z.tool);let E={configCwd:Q,executionCwd:G},v=_(Z.tool,y,f,E,z??null);try{let V=k(v,{guard:{auditAllowed:N(),dependencies:q},audit:{agent:"opencode",homeDir:K,getSessionId:()=>Z.sessionID}});U(V,V.stage!=="config-state")}catch(V){if(!(V instanceof b))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){if(typeof q!=="string")return"auto";let J=q.trim().split(/[\\/]/).at(-1)?.toLowerCase().replace(/\.exe$/,"");if(!J)return"auto";if(C.has(J))return"powershell";if(s.has(J))return"posix";return"auto"}function c(q,J){if(q==="bash")return{kind:"command",shell:J};return{kind:M(q)}}function u(q,J){if(!J||typeof J!=="object"||Array.isArray(J))return q;if(!Object.hasOwn(J,"workdir"))return q;let K=J.workdir;if(typeof K!=="string"||K.trim()==="")return null;let Q=process.platform==="win32"?a(K):K;if(!Q)return null;let $=S(q,Q);return A($)?$:null}function a(q){let J=q.replace(/^\/([a-zA-Z]):(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/cygdrive\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`).replace(/^\/mnt\/([a-zA-Z])(?:[\\/]|$)/,(K,Q)=>`${Q.toUpperCase()}:/`);return J.startsWith("/")?null:J}function A(q){try{if(!w(q).isDirectory())return!1;return m(q,R.R_OK|R.X_OK),!0}catch{return!1}}function U(q,J){let K=W(q,{includeEvidence:J});if(K)I(K)}function I(q){throw Error(L(q))}var Hq=T();export{Hq 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.4
2
+ // version: 2.0.5
3
3
  var NM=Object.defineProperty;var FM=($)=>$;function VM($,J){this[$]=FM.bind(null,J)}var B2=($,J)=>{for(var Q in J)NM($,Q,{get:J[Q],enumerable:!0,configurable:!0,set:VM.bind(J,Q)})};var OK={id:"cc-safety-net",name:"CC Safety Net",description:"Block destructive commands and secret-file access before OpenClaw runs a tool."};import{randomBytes as ZO}from"node:crypto";import{appendFileSync as LO,mkdirSync as MO}from"node:fs";import{homedir as OO,userInfo as NO}from"node:os";import{isAbsolute as FO,join as RJ}from"node:path";var _M=[/\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 j0($){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 DM(J)}function DM($){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 _M)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 SK,readdirSync as eM,readFileSync as fK,rmdirSync as $O,statSync as TK,unlinkSync as JO,utimesSync as QO,writeFileSync as XO}from"node:fs";import{dirname as YO,join as l2}from"node:path";var R6=30,HJ=1,ZJ=365;function I6($){if(typeof $!=="number"||!Number.isInteger($))return 30;if($<1)return 1;return $>365?365:$}import{homedir as yM}from"node:os";import{dirname as l0,isAbsolute as xM,join as p0,relative as uM,resolve as P0,sep as mM}from"node:path";import{closeSync as zM,constants as NK,fstatSync as RM,fsyncSync as DE,lstatSync as FK,mkdirSync as zE,openSync as IM,readdirSync as RE,readFileSync as jM,realpathSync as j6,renameSync as IE,rmdirSync as jE,statSync as bM,unlinkSync as bE,writeFileSync as PE}from"node:fs";import{isAbsolute as VK,join as _K,normalize as PM,parse as AM,relative as LJ,resolve as MJ,sep as OJ}from"node:path";var EM=Symbol("PolicyFilesystemScope"),CM=Symbol("PolicyFilesystemTarget"),SM=NK.O_NOFOLLOW??0;class W1 extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function m0($,J){return{[EM]:!0,root:MJ($),label:J}}function DK($,J){let Q=PM(J);if(J===""||VK(J)||Q===".."||Q.startsWith(`..${OJ}`))throw new W1($.label);return{[CM]:!0,scope:$,relativePath:Q,path:_K($.root,Q)}}function b0($,J){let Q=LJ($.root,MJ(J));return DK($,Q)}function P6($,J="rules policy"){let Q=MJ($),X=AM(Q).dir;return DK(m0(X,J),LJ(X,Q))}function q2($){try{if(!b6($,!1).exists)return null;let Q=IM($.path,NK.O_RDONLY|SM);try{let X=RM(Q);if(!X.isFile())throw new W1($.scope.label);let Y=jM(Q,"utf-8"),W=FK($.path);if(!W.isFile()||W.isSymbolicLink()||X.dev!==W.dev||X.ino!==W.ino)throw new W1($.scope.label);return b6($,!1),Y}finally{zM(Q)}}catch(J){vM($.scope.label,J)}}function zK($,J){if($.path===J.path)return!0;try{if(!b6($,!1).exists||!b6(J,!1).exists)return!1;return j6($.path)===j6(J.path)}catch(Q){if(Q instanceof W1)throw Q;throw new W1($.scope.label)}}function b6($,J,Q="file"){let X=TM($.scope);if(!X)return{exists:!1};let Y=$.relativePath.split(OJ);for(let W of Y.keys()){let K=_K($.scope.root,...Y.slice(0,W+1)),B=RK(K);if(!B){if(W===Y.length-1&&J)return{exists:!1};return{exists:!1}}if(B.isSymbolicLink())throw new W1($.scope.label);if(W<Y.length-1&&!B.isDirectory())throw new W1($.scope.label);if(W===Y.length-1&&(Q==="file"?!B.isFile():!B.isDirectory()))throw new W1($.scope.label);wM(X,j6(K),$.scope.label)}return{exists:!0}}function TM($){if(!RK($.root))return null;if(!bM($.root).isDirectory())throw new W1($.label);return j6($.root)}function wM($,J,Q){let X=LJ($,J);if(X===".."||X.startsWith(`..${OJ}`)||VK(X))throw new W1(Q)}function RK($){try{return FK($)}catch(J){if(fM(J)&&J.code==="ENOENT")return null;throw J}}function vM($,J){if(J instanceof W1)throw J;throw new W1($)}function fM($){return $ instanceof Error&&"code"in $}var Y0=/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,NJ="rulebook.json",FJ=".cc-safety-net/rules";var IK=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;var hM=/^[A-Za-z0-9._-]+$/,kM=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),gM="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),jK=new RegExp(`^${kM}/(${Y0.source.slice(1,-1)})/${gM}$`);function bK($){return`.cc-safety-net/rules/${$}/rulebook.json`}function o4($){if(E6($))try{return A6($),null}catch(J){return J instanceof Error?J.message:String(J)}return Y0.test($)?null:`Local rulebook sources must be bare names matching ${Y0}: ${$}`}function A6($){if($.startsWith("github:"))throw Error(`Invalid rulebook source: ${$}`);let J=$.match(IK);if(!J?.[1]||!J[2]||!J[3])throw Error(`Invalid GitHub rulebook source: ${$}`);let[Q,X,...Y]=J[3].split("/");if(!Q||!hM.test(Q))throw Error(`GitHub rulebook refs must be a single path segment: ${$}`);if(!X||Y.length>0||!Y0.test(X))throw Error(`GitHub rulebook sources must be owner/repo#ref/<rulebook-name>: ${$}`);return{owner:J[1],repo:J[2],ref:Q,path:bK(X),name:X}}function E6($){return IK.test($)}var AK="rule.json",C6="policy.json",lM="rule.lock";var EK=".cc-safety-net",pM="rules",PK="cache",cM="CC_SAFETY_NET_HOME",c0="`cc-safety-net rule sync`";function dM($){return P0($??process.cwd(),FJ)}function rM($){return p0(dM($),AK)}function U2($){return $?.userConfigDir??($?.userConfigPath?l0($.userConfigPath):p0(iM(),pM))}function iM(){let $=process.env[cM];return $?P0($):p0(yM(),EK)}function oM($){return p0(U2($),AK)}function n4($){return p0(l0($),lM)}function CK($){let J=$.userConfigPath??oM($),Q=$.projectConfigPath??rM($.cwd),X=nM(J,$),Y=sM(Q,$);return{userConfigPath:J,projectConfigPath:Q,userLockPath:n4(J),projectLockPath:n4(Q),userScope:X,projectScope:Y,userConfigTarget:b0(X,J),projectConfigTarget:b0(Y,Q),userLockTarget:b0(X,n4(J)),projectLockTarget:b0(Y,n4(Q))}}function nM($,J){let Q=J.userConfigPath?l0(l0(P0(J.userConfigPath))):l0(P0(J.userConfigDir??U2(J)));return m0(Q,"user policy")}function sM($,J){let Q=P0(J.cwd??process.cwd()),X=P0($),Y=uM(Q,X);if(Y!==".."&&!Y.startsWith(`..${mM}`)&&!xM(Y))return m0(Q,"project policy");return m0(l0(l0(X)),"project policy")}function VJ($,J){let Q=$.digest.startsWith("sha256:")?$.digest.slice(7):$.digest;return p0(tM(J),"rulebooks",`${aM($)}--${Q.slice(0,12)}`,NJ)}function _J($,J){let Q=J;return{cacheConfigDir:$,cwd:J.cwd,global:Q.global}}function aM($){return($.kind==="github"&&$.display_ref?`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`:$.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function tM($){let J=$?.cacheConfigDir??U2($),Q=$;if(Q&&!Q.global&&Q.cwd&&P0(J)===P0(Q.cwd))return p0(P0(Q.cwd),EK,PK);return p0(l0(J),PK)}var zJ=86400000,WO=".last-prune",KO=/^\d{4}-\d{2}$/,BO=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,wK=($)=>Math.floor($/zJ);function qO($){try{let J=l2(YO(U2($)),C6),Q=JSON.parse(fK(J,"utf-8"));return I6(Q?.audit?.retention_days)}catch{return R6}}function hK($,J=()=>new Date){try{let Q=J().getTime();if(!TK($,{throwIfNoEntry:!1})?.isDirectory())return;let X=l2($,WO),Y=TK(X,{throwIfNoEntry:!1})?.mtimeMs;if(Y!==void 0&&wK(Y)===wK(Q))return;let W=Q-qO()*zJ,K=new Date(Q).toISOString().slice(0,7);for(let B of DJ($)){if(B.isDirectory()){UO(l2($,B.name),W,K);continue}if(B.isFile()&&B.name.endsWith(".jsonl"))GO(l2($,B.name),W)}XO(X,"",{mode:384}),QO(X,Q/1000,Q/1000)}catch{}}function UO($,J,Q){for(let X of DJ($)){if(!X.isDirectory()||!KO.test(X.name))continue;let Y=l2($,X.name);for(let W of DJ(Y)){if(!W.isFile())continue;let K=BO.exec(W.name);if(!K||K[2]!==X.name)continue;let B=Date.parse(`${K[1]}T00:00:00.000Z`)+zJ;if(!Number.isFinite(B)||B>=J)continue;kK(l2(Y,W.name))}if(X.name!==Q)vK(Y)}vK($)}function GO($,J){try{let Q=SK($);if(Q.mtimeMs>=J)return;let X=fK($,"utf-8").split(`
4
- `).filter((Y)=>Y.trim()).map(HO);if(X.length===0)return;if(X.some((Y)=>Y===void 0||Y>=J))return;if(SK($).mtimeMs!==Q.mtimeMs)return;kK($)}catch{}}function HO($){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 DJ($){try{return eM($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function kK($){try{JO($)}catch{}}function vK($){try{$O($)}catch{}}var VO="2.0.4",_O=1e4,DO=2000,zO=256,RO=32768;function IO($){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 jO($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function IJ($,J,Q,X,Y,W={}){let K=IO($);if(!K)return;let B=W.homeDir??gK();if(!B)return;let q=bO(B);if(!q)return;try{let U=(W.now??(()=>new Date))().toISOString(),G=S6(j0(J),_O),H=S6(j0(Q),DO),L=W.toolName?S6(j0(W.toolName),zO):void 0,Z=Y===null?void 0:S6(j0(Y),RO),M=RJ(q,jO(Z?.value??null),U.slice(0,7));MO(M,{recursive:!0,mode:448});let O=RJ(M,`${U.slice(0,10)}-${K}.jsonl`),V={ts:U,id:(W.createId??(()=>ZO(8).toString("hex")))(),v:VO,sessionId:K,decision:W.decision??"deny",agent:W.agent,shape:W.shape,level:W.level,configFallback:W.configFallback,toolName:L?.value,command:G.value,segment:H.value,...G.truncated||H.truncated||L?.truncated||Z?.truncated?{truncated:!0}:{},reason:X,ruleId:W.ruleId,intent:W.intent,failureStage:W.failureStage,errorCode:W.errorCode,cwd:Z?.value??null};LO(O,`${JSON.stringify(V)}
4
+ `).filter((Y)=>Y.trim()).map(HO);if(X.length===0)return;if(X.some((Y)=>Y===void 0||Y>=J))return;if(SK($).mtimeMs!==Q.mtimeMs)return;kK($)}catch{}}function HO($){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 DJ($){try{return eM($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function kK($){try{JO($)}catch{}}function vK($){try{$O($)}catch{}}var VO="2.0.5",_O=1e4,DO=2000,zO=256,RO=32768;function IO($){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 jO($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function IJ($,J,Q,X,Y,W={}){let K=IO($);if(!K)return;let B=W.homeDir??gK();if(!B)return;let q=bO(B);if(!q)return;try{let U=(W.now??(()=>new Date))().toISOString(),G=S6(j0(J),_O),H=S6(j0(Q),DO),L=W.toolName?S6(j0(W.toolName),zO):void 0,Z=Y===null?void 0:S6(j0(Y),RO),M=RJ(q,jO(Z?.value??null),U.slice(0,7));MO(M,{recursive:!0,mode:448});let O=RJ(M,`${U.slice(0,10)}-${K}.jsonl`),V={ts:U,id:(W.createId??(()=>ZO(8).toString("hex")))(),v:VO,sessionId:K,decision:W.decision??"deny",agent:W.agent,shape:W.shape,level:W.level,configFallback:W.configFallback,toolName:L?.value,command:G.value,segment:H.value,...G.truncated||H.truncated||L?.truncated||Z?.truncated?{truncated:!0}:{},reason:X,ruleId:W.ruleId,intent:W.intent,failureStage:W.failureStage,errorCode:W.errorCode,cwd:Z?.value??null};LO(O,`${JSON.stringify(V)}
5
5
  `,{encoding:"utf-8",mode:384}),hK(q,W.now)}catch{}}function S6($,J){return{value:$.slice(0,J),truncated:$.length>J}}function gK($=process.env.CC_SAFETY_NET_AUDIT_HOME||process.env.HOME){let J=$||OO()||NO().homedir;return J&&FO(J)?J:null}function bO($=gK()){return $?RJ($,".cc-safety-net","logs"):null}function xK($,J,Q,X=!0,Y){if(J.decision.kind==="allow"){if(!Q||$.route.kind!=="command")return;let B=yK($);return{decision:"allow",command:B,segment:B,reason:"allowed",cwd:$.context.executionCwd,toolName:$.toolName,level:J.level,...J.configFallback?{configFallback:!0}:{}}}let W=J.decision.evidence.find((B)=>B.kind==="command"),K=W?.command??(X?yK($):"");return{decision:"deny",command:K,segment:W?.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:Y?.stage,errorCode:Y?.errorCode}}function yK($){return"command"in $?$.command??"":""}function uK($,J,Q){if(!$)return;let X;try{X=J()}catch{return}if(typeof X!=="string"||!X.trim())return;IJ(X,$.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 mK($,J,Q){let X;try{X=J()}catch{return}if(typeof X!=="string"||!X.trim())return;IJ(X,$.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 vO,statSync as fO}from"node:fs";import{isAbsolute as pK,relative as hO,resolve as kO,sep as gO}from"node:path";import{dirname as PO,isAbsolute as AO,parse as EO,sep as CO}from"node:path";function G2($,J=process.platform){if(J!=="win32")return!1;return($[0]==="/"||$[0]==="\\")&&($[1]==="/"||$[1]==="\\")}function d0($,J,Q){if(G2(J))throw Error("Unsupported Windows namespace path");let X=AO(J)?TO(J):"",Y=X||$;for(let W of wO(X?J.slice(X.length):J)){if(W===""||W===".")continue;if(W===".."){Y=PO(Y);continue}let K=SO(Y,W),B=Q.entryKind(K),q=B==="symlink"?Q.realpath(K):K;if(B==="missing"||q===null)throw Error(`Cannot resolve path component: ${K}`);Y=q}return Y}function SO($,J){return $.endsWith("/")||$.endsWith("\\")?`${$}${J}`:`${$}${CO}${J}`}function TO($){return EO($).root}function wO($){let J=process.platform==="win32"?/[\\/]+/:/\/+/;return $.split(J)}function T6($,J){if(G2($))return;let Q=J.flatMap((Y)=>lK(Y));if(!Q[0])return;let X=lK(pK($)?$:kO(Q[0],$))[0];if(!X)return;return Q.some((Y)=>cK(X,Y))?X:void 0}function lK($){try{let J=vO($);return fO(J).isDirectory()?[J]:[]}catch{return[]}}function cK($,J){let Q=hO(J,$);return Q===""||Q!==".."&&!Q.startsWith(`..${gO}`)&&!pK(Q)}var r0="Command could not be safely analyzed (strict mode). Simplify the command and retry, or ask the user to verify.",A0="Command exceeds maximum recursion depth and cannot be safely analyzed. Flatten the nesting and retry.",dK="CC Safety Net could not validate the command because its structure exceeds safe analysis limits.",w6="CC Safety Net failed closed because command analysis failed unexpectedly. This is not caused by your command. Report it to the user.";function iK($){let{reason:J,command:Q,segment:X,toolName:Y}=$,W=$.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.4",
5
+ "version": "2.0.5",
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.4",
3
+ "version": "2.0.5",
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 j}from"../chunks/index-25nh5wqs.js";import{M as y,N as Y,O as F,P as G,Q as U,_ as L,ib as R,ja as b,jb as K,la as h,mb as S,na as O,ta as B}from"../chunks/index-xvfhq21r.js";var P="cc-safety-net",N="Manage CC Safety Net rulebooks",w="Help me configure CC Safety Net.";function f(H){H.registerCommand(P,{description:N,handler:async(z,q)=>{H.sendUserMessage(A(z),q.isIdle()?void 0:{deliverAs:"followUp"})}})}function A(H){return`${j.slice(j.indexOf("## Workflow")).trimEnd()}
1
+ import{a as j}from"../chunks/index-25nh5wqs.js";import{M as y,N as Y,O as F,P as G,Q as U,_ as L,ib as R,ja as b,jb as K,la as h,mb as S,na as O,ta as B}from"../chunks/index-bmvm3x9s.js";var P="cc-safety-net",N="Manage CC Safety Net rulebooks",w="Help me configure CC Safety Net.";function f(H){H.registerCommand(P,{description:N,handler:async(z,q)=>{H.sendUserMessage(A(z),q.isIdle()?void 0:{deliverAs:"followUp"})}})}function A(H){return`${j.slice(j.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.4",
3
+ "version": "2.0.5",
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",
@@ -41,7 +41,7 @@
41
41
  "test:e2e": "bun test tests/e2e",
42
42
  "test:e2e:stability": "bun test tests/e2e --randomize --rerun-each 3",
43
43
  "test:e2e:live": "CC_SAFETY_NET_E2E_LIVE=1 bun test tests/e2e-live",
44
- "test:coverage": "AGENT=1 bun test tests --coverage --coverage-reporter=text --coverage-reporter=lcov",
44
+ "test:coverage": "AGENT=1 bun test tests --path-ignore-patterns 'tests/e2e-live/**' --coverage --coverage-reporter=text --coverage-reporter=lcov",
45
45
  "cc-safety-net": "bun run src/cli/cc-safety-net.ts"
46
46
  },
47
47
  "author": {
@@ -104,5 +104,5 @@
104
104
  "cursor",
105
105
  "amp"
106
106
  ],
107
- "gitHead": "73275768641a6f8647b085b6dc9fc43504aa5a70"
107
+ "gitHead": "83819e0005e7a22f52cf73afd0c860601b24a3be"
108
108
  }