cc-safety-net 2.0.0 → 2.0.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/amp/cc-safety-net.ts +2 -2
- package/dist/bin/cc-safety-net.js +74 -74
- package/dist/chunks/{index-9s8cwhj0.js → index-mf3j7fqk.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/openclaw/cc-safety-net/index.js +2 -2
- package/dist/openclaw/cc-safety-net/openclaw.plugin.json +1 -1
- package/dist/openclaw/cc-safety-net/package.json +1 -1
- package/dist/pi/index.js +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var DX=[/\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 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 DX)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 zX($){return KZ($).reduceRight((J,Q)=>`${J.slice(0,Q.valueStart)}<redacted>${J.slice(Q.valueEnd)}`,$)}function dL($){return XZ(zX($))}function cL($){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:bX($,Y)})}return Z}function bX($,Z){if($.startsWith("$(",Z))return IX($,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 IX($,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 fX}from"node:crypto";import{closeSync as v3,constants as h$,fstatSync as y3,fsyncSync as PX,lstatSync as F0,mkdirSync as YZ,openSync as BZ,readdirSync as u3,readFileSync as CX,realpathSync as A0,renameSync as AX,rmdirSync as EX,statSync as w3,unlinkSync as h3,writeFileSync as TX}from"node:fs";import{isAbsolute as WZ,join as $$,normalize as SX,parse as qZ,relative as g3,resolve as k3,sep as k$}from"node:path";var yX=Symbol("PolicyFilesystemScope"),wX=Symbol("PolicyFilesystemTarget"),UZ=h$.O_NOFOLLOW??0;class u extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function D1($,Z){return{[yX]:!0,root:k3($),label:Z}}function x$($,Z){let J=SX(Z);if(Z===""||WZ(Z)||J===".."||J.startsWith(`..${k$}`))throw new u($.label);return{[wX]:!0,scope:$,relativePath:J,path:$$($.root,J)}}function X1($,Z){let J=g3($.root,k3(Z));return x$($,J)}function u2($,Z="rules policy"){let J=k3($),Q=qZ(J).dir;return x$(D1(Q,Z),g3(Q,J))}function Q0($){try{if(!W1($,!1).exists)return null;let J=BZ($.path,h$.O_RDONLY|UZ);try{let Q=y3(J);if(!Q.isFile())throw new u($.scope.label);let X=CX(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}.${fX(8).toString("hex")}.tmp`,K=null;try{hX($),W1($,!0),K=BZ(X,h$.O_CREAT|h$.O_EXCL|h$.O_WRONLY|UZ,J);let Y=y3(K);if(!Y.isFile())throw new u($.scope.label);TX(K,Z,"utf-8"),PX(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),kX($,X,B.dev,B.ino),AX(X,$.path),Q?.($.path),W1($,!1)}catch(Y){if(K!==null)lX(K);mX(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 vX($){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=vX($);if(!Z)return null;try{let J=Z.map((Q)=>{let X=x$($.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(k$))}catch(Z){N0($.scope.label,Z)}}function $M($){try{if(!uX($))return;_Z($),W1($,!0,"directory")}catch(Z){N0($.scope.label,Z)}}function uX($){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(k$);for(let K of X.keys()){let Y=$$($.scope.root,...X.slice(0,K+1)),B=g$(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=x$($.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=x$($.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)}EX($.path)}function hX($){OZ($,$.relativePath.split(k$).slice(0,-1))}function OZ($,Z){gX($.scope);let J=LZ($.scope);for(let Q of Z.keys()){let X=$$($.scope.root,...Z.slice(0,Q+1));if(!g$(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 gX($){if(g$($.root)){if(!w3($.root).isDirectory())throw new u($.label);return}let Z=[],J=$.root;while(!g$(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(!g$($.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 kX($,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(`..${k$}`)||WZ(Q))throw new u(J)}function g$($){try{return F0($)}catch(Z){if(xX(Z)&&Z.code==="ENOENT")return null;throw Z}}function N0($,Z){if(Z instanceof u)throw Z;throw new u($)}function xX($){return $ instanceof Error&&"code"in $}function lX($){try{v3($)}catch{}}function mX($){try{h3($)}catch{}}import{homedir as sX}from"node:os";import{dirname as m1,isAbsolute as rX,join as T1,relative as nX,resolve as p1,sep as aX}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_.-]+)#(.+)$/,pX=/^[A-Za-z0-9][A-Za-z0-9_.-]*\/[A-Za-z0-9_.-]+$/,dX=/^[A-Za-z0-9._-]+$/,cX=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),iX="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l3=new RegExp(`^${cX}/(${z1.source.slice(1,-1)})/${iX}$`);function FZ($){return`.cc-safety-net/rules/${$}/rulebook.json`}function l$($){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 pX.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",oX="config.json",zZ=".cc-safety-net",tX="rules",VZ="cache",eX="CC_SAFETY_NET_HOME",S1="`cc-safety-net rule sync`";function $K($){return p1($??process.cwd(),k2)}function bZ($){return T1($K($),RZ)}function X0($){return $?.userConfigDir??($?.userConfigPath?m1($.userConfigPath):T1(ZK(),tX))}function ZK(){let $=process.env[eX];return $?p1($):T1(sX(),zZ)}function IZ($){return T1(X0($),RZ)}function WM($){return T1(X0($),DZ)}function E0($){return T1(m1($),DZ)}function qM($={}){return T1(m1(X0($)),oX)}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??X0(Z)));return D1(J,"user policy")}function CZ($,Z){let J=p1(Z.cwd??process.cwd()),Q=p1($),X=nX(J,Q);if(X!==".."&&!X.startsWith(`..${aX}`)&&!rX(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",`${JK($)}--${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 JK($){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??X0($),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 QK,readFileSync as vZ,rmdirSync as XK,statSync as SZ,unlinkSync as KK,utimesSync as YK,writeFileSync as BK}from"node:fs";import{dirname as WK,join as Q$}from"node:path";var p2=30,p3=1,d3=365;function d2($){if(typeof $!=="number"||!Number.isInteger($))return 30;if($<1)return 1;return $>365?365:$}var i3=86400000,qK=".last-prune",UK=/^\d{4}-\d{2}$/,GK=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,yZ=($)=>Math.floor($/i3);function HK($){try{let Z=Q$(WK(X0($)),x2),J=JSON.parse(vZ(Z,"utf-8"));return d2(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$($,qK),X=SZ(Q,{throwIfNoEntry:!1})?.mtimeMs;if(X!==void 0&&yZ(X)===yZ(J))return;let K=J-HK()*i3,Y=new Date(J).toISOString().slice(0,7);for(let B of c3($)){if(B.isDirectory()){jK(Q$($,B.name),K,Y);continue}if(B.isFile()&&B.name.endsWith(".jsonl"))_K(Q$($,B.name),K)}BK(Q,"",{mode:384}),YK(Q,J/1000,J/1000)}catch{}}function jK($,Z,J){for(let Q of c3($)){if(!Q.isDirectory()||!UK.test(Q.name))continue;let X=Q$($,Q.name);for(let K of c3(X)){if(!K.isFile())continue;let Y=GK.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 _K($,Z){try{let J=TZ($);if(J.mtimeMs>=Z)return;let Q=vZ($,"utf-8").split(`
|
|
2
|
-
`).filter((X)=>X.trim()).map(OK);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(TZ($).mtimeMs!==J.mtimeMs)return;hZ($)}catch{}}function OK($){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 c3($){try{return QK($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function hZ($){try{KK($)}catch{}}function wZ($){try{XK($)}catch{}}import{randomBytes as LK}from"node:crypto";import{appendFileSync as MK,mkdirSync as FK}from"node:fs";import{homedir as NK,userInfo as VK}from"node:os";import{isAbsolute as RK,join as s3}from"node:path";var DK="2.0.
|
|
2
|
+
`).filter((X)=>X.trim()).map(OK);if(Q.length===0)return;if(Q.some((X)=>X===void 0||X>=Z))return;if(TZ($).mtimeMs!==J.mtimeMs)return;hZ($)}catch{}}function OK($){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 c3($){try{return QK($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function hZ($){try{KK($)}catch{}}function wZ($){try{XK($)}catch{}}import{randomBytes as LK}from"node:crypto";import{appendFileSync as MK,mkdirSync as FK}from"node:fs";import{homedir as NK,userInfo as VK}from"node:os";import{isAbsolute as RK,join as s3}from"node:path";var DK="2.0.1",zK=1e4,bK=2000,IK=256,fK=32768;function PK($){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 CK($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function r3($,Z,J,Q,X,K={}){let Y=PK($);if(!Y)return;let B=K.homeDir??gZ();if(!B)return;let W=AK(B);if(!W)return;try{let q=(K.now??(()=>new Date))().toISOString(),U=c2(J0(Z),zK),H=c2(J0(J),bK),j=K.toolName?c2(J0(K.toolName),IK):void 0,G=X===null?void 0:c2(J0(X),fK),_=s3(W,CK(G?.value??null),q.slice(0,7));FK(_,{recursive:!0,mode:448});let O=s3(_,`${q.slice(0,10)}-${Y}.jsonl`),M={ts:q,id:(K.createId??(()=>LK(8).toString("hex")))(),v:DK,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};MK(O,`${JSON.stringify(M)}
|
|
3
3
|
`,{encoding:"utf-8",mode:384}),uZ(W,K.now)}catch{}}function c2($,Z){return{value:$.slice(0,Z),truncated:$.length>Z}}function gZ($=process.env.CC_SAFETY_NET_AUDIT_HOME||process.env.HOME){let Z=$||NK()||VK().homedir;return Z&&RK(Z)?Z:null}function AK($=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.",K0="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 dZ($){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-
|
|
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-mf3j7fqk.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.
|
|
2
|
+
// version: 2.0.1
|
|
3
3
|
var MM=Object.defineProperty;var OM=($)=>$;function NM($,J){this[$]=OM.bind(null,J)}var B2=($,J)=>{for(var Q in J)MM($,Q,{get:J[Q],enumerable:!0,configurable:!0,set:NM.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 GO}from"node:crypto";import{appendFileSync as HO,mkdirSync as ZO}from"node:fs";import{homedir as LO,userInfo as MO}from"node:os";import{isAbsolute as OO,join as RJ}from"node:path";var FM=[/\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 I0($){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 VM(J)}function VM($){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 FM)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 aM,readFileSync as fK,rmdirSync as tM,statSync as TK,unlinkSync as eM,utimesSync as $O,writeFileSync as JO}from"node:fs";import{dirname as QO,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 kM}from"node:os";import{dirname as l0,isAbsolute as gM,join as p0,relative as yM,resolve as b0,sep as xM}from"node:path";import{closeSync as _M,constants as NK,fstatSync as DM,fsyncSync as DE,lstatSync as FK,mkdirSync as zE,openSync as zM,readdirSync as RE,readFileSync as RM,realpathSync as j6,renameSync as IE,rmdirSync as jE,statSync as IM,unlinkSync as bE,writeFileSync as PE}from"node:fs";import{isAbsolute as VK,join as _K,normalize as jM,parse as bM,relative as LJ,resolve as MJ,sep as OJ}from"node:path";var PM=Symbol("PolicyFilesystemScope"),AM=Symbol("PolicyFilesystemTarget"),EM=NK.O_NOFOLLOW??0;class W1 extends Error{constructor($){super(`Unable to access ${$} filesystem safely.`);this.name="PolicyFilesystemError"}}function m0($,J){return{[PM]:!0,root:MJ($),label:J}}function DK($,J){let Q=jM(J);if(J===""||VK(J)||Q===".."||Q.startsWith(`..${OJ}`))throw new W1($.label);return{[AM]:!0,scope:$,relativePath:Q,path:_K($.root,Q)}}function j0($,J){let Q=LJ($.root,MJ(J));return DK($,Q)}function P6($,J="rules policy"){let Q=MJ($),X=bM(Q).dir;return DK(m0(X,J),LJ(X,Q))}function q2($){try{if(!b6($,!1).exists)return null;let Q=zM($.path,NK.O_RDONLY|EM);try{let X=DM(Q);if(!X.isFile())throw new W1($.scope.label);let Y=RM(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{_M(Q)}}catch(J){TM($.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=CM($.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);SM(X,j6(K),$.scope.label)}return{exists:!0}}function CM($){if(!RK($.root))return null;if(!IM($.root).isDirectory())throw new W1($.label);return j6($.root)}function SM($,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(wM(J)&&J.code==="ENOENT")return null;throw J}}function TM($,J){if(J instanceof W1)throw J;throw new W1($)}function wM($){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 vM=/^[A-Za-z0-9._-]+$/,fM=".cc-safety-net/rules".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),hM="rulebook.json".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),jK=new RegExp(`^${fM}/(${Y0.source.slice(1,-1)})/${hM}$`);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||!vM.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",uM="rule.lock";var EK=".cc-safety-net",mM="rules",PK="cache",lM="CC_SAFETY_NET_HOME",c0="`cc-safety-net rule sync`";function pM($){return b0($??process.cwd(),FJ)}function cM($){return p0(pM($),AK)}function U2($){return $?.userConfigDir??($?.userConfigPath?l0($.userConfigPath):p0(dM(),mM))}function dM(){let $=process.env[lM];return $?b0($):p0(kM(),EK)}function rM($){return p0(U2($),AK)}function n4($){return p0(l0($),uM)}function CK($){let J=$.userConfigPath??rM($),Q=$.projectConfigPath??cM($.cwd),X=iM(J,$),Y=oM(Q,$);return{userConfigPath:J,projectConfigPath:Q,userLockPath:n4(J),projectLockPath:n4(Q),userScope:X,projectScope:Y,userConfigTarget:j0(X,J),projectConfigTarget:j0(Y,Q),userLockTarget:j0(X,n4(J)),projectLockTarget:j0(Y,n4(Q))}}function iM($,J){let Q=J.userConfigPath?l0(l0(b0(J.userConfigPath))):l0(b0(J.userConfigDir??U2(J)));return m0(Q,"user policy")}function oM($,J){let Q=b0(J.cwd??process.cwd()),X=b0($),Y=yM(Q,X);if(Y!==".."&&!Y.startsWith(`..${xM}`)&&!gM(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(sM(J),"rulebooks",`${nM($)}--${Q.slice(0,12)}`,NJ)}function _J($,J){let Q=J;return{cacheConfigDir:$,cwd:J.cwd,global:Q.global}}function nM($){return($.kind==="github"&&$.display_ref?`${$.owner}/${$.repo}#${$.display_ref}/${$.name}`:$.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function sM($){let J=$?.cacheConfigDir??U2($),Q=$;if(Q&&!Q.global&&Q.cwd&&b0(J)===b0(Q.cwd))return p0(b0(Q.cwd),EK,PK);return p0(l0(J),PK)}var zJ=86400000,XO=".last-prune",YO=/^\d{4}-\d{2}$/,WO=/^((\d{4}-\d{2})-\d{2})-.+\.jsonl$/,wK=($)=>Math.floor($/zJ);function KO($){try{let J=l2(QO(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($,XO),Y=TK(X,{throwIfNoEntry:!1})?.mtimeMs;if(Y!==void 0&&wK(Y)===wK(Q))return;let W=Q-KO()*zJ,K=new Date(Q).toISOString().slice(0,7);for(let B of DJ($)){if(B.isDirectory()){BO(l2($,B.name),W,K);continue}if(B.isFile()&&B.name.endsWith(".jsonl"))qO(l2($,B.name),W)}JO(X,"",{mode:384}),$O(X,Q/1000,Q/1000)}catch{}}function BO($,J,Q){for(let X of DJ($)){if(!X.isDirectory()||!YO.test(X.name))continue;let Y=l2($,X.name);for(let W of DJ(Y)){if(!W.isFile())continue;let K=WO.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 qO($,J){try{let Q=SK($);if(Q.mtimeMs>=J)return;let X=fK($,"utf-8").split(`
|
|
4
|
-
`).filter((Y)=>Y.trim()).map(UO);if(X.length===0)return;if(X.some((Y)=>Y===void 0||Y>=J))return;if(SK($).mtimeMs!==Q.mtimeMs)return;kK($)}catch{}}function UO($){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 aM($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function kK($){try{eM($)}catch{}}function vK($){try{tM($)}catch{}}var NO="2.0.
|
|
4
|
+
`).filter((Y)=>Y.trim()).map(UO);if(X.length===0)return;if(X.some((Y)=>Y===void 0||Y>=J))return;if(SK($).mtimeMs!==Q.mtimeMs)return;kK($)}catch{}}function UO($){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 aM($,{withFileTypes:!0,encoding:"utf8"})}catch{return[]}}function kK($){try{eM($)}catch{}}function vK($){try{tM($)}catch{}}var NO="2.0.1",FO=1e4,VO=2000,_O=256,DO=32768;function zO($){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 RO($){return($??"").replace(/[^A-Za-z0-9]/g,"-").slice(0,180)||"no-cwd"}function IJ($,J,Q,X,Y,W={}){let K=zO($);if(!K)return;let B=W.homeDir??gK();if(!B)return;let q=IO(B);if(!q)return;try{let U=(W.now??(()=>new Date))().toISOString(),G=S6(I0(J),FO),H=S6(I0(Q),VO),L=W.toolName?S6(I0(W.toolName),_O):void 0,Z=Y===null?void 0:S6(I0(Y),DO),M=RJ(q,RO(Z?.value??null),U.slice(0,7));ZO(M,{recursive:!0,mode:448});let O=RJ(M,`${U.slice(0,10)}-${K}.jsonl`),V={ts:U,id:(W.createId??(()=>GO(8).toString("hex")))(),v:NO,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};HO(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=$||LO()||MO().homedir;return J&&OO(J)?J:null}function IO($=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 TO,statSync as wO}from"node:fs";import{isAbsolute as pK,relative as vO,resolve as fO,sep as hO}from"node:path";import{dirname as jO,isAbsolute as bO,parse as PO,sep as AO}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=bO(J)?CO(J):"",Y=X||$;for(let W of SO(X?J.slice(X.length):J)){if(W===""||W===".")continue;if(W===".."){Y=jO(Y);continue}let K=EO(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 EO($,J){return $.endsWith("/")||$.endsWith("\\")?`${$}${J}`:`${$}${AO}${J}`}function CO($){return PO($).root}function SO($){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($)?$:fO(Q[0],$))[0];if(!X)return;return Q.some((Y)=>cK(X,Y))?X:void 0}function lK($){try{let J=TO($);return wO(J).isDirectory()?[J]:[]}catch{return[]}}function cK($,J){let Q=vO(J,$);return Q===""||Q!==".."&&!Q.startsWith(`..${hO}`)&&!pK(Q)}var r0="Command could not be safely analyzed (strict mode). Simplify the command and retry, or ask the user to verify.",P0="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+=`
|
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-
|
|
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-mf3j7fqk.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.
|
|
3
|
+
"version": "2.0.1",
|
|
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",
|
|
@@ -104,5 +104,5 @@
|
|
|
104
104
|
"cursor",
|
|
105
105
|
"amp"
|
|
106
106
|
],
|
|
107
|
-
"gitHead": "
|
|
107
|
+
"gitHead": "b9d0f7b1344697cdf401752ce642945b9f1a8292"
|
|
108
108
|
}
|