@@ -2305,7 +2305,23 @@ function analyzeGitWorktree(tokens) {
23052305// src/core/rules-rm.ts
23062306import { realpathSync } from "node:fs" ;
23072307import { homedir as homedir3 , tmpdir } from "node:os" ;
2308- import { normalize , resolve as resolve2 } from "node:path" ;
2308+ import { normalize , resolve as resolve2 , sep } from "node:path" ;
2309+ var IS_WINDOWS = process . platform === "win32" ;
2310+ function normalizePathForComparison ( p ) {
2311+ let normalized = normalize ( p ) ;
2312+ if ( IS_WINDOWS ) {
2313+ normalized = normalized . replace ( / \/ / g, "\\" ) ;
2314+ normalized = normalized . toLowerCase ( ) ;
2315+ if ( normalized . length > 3 && normalized . endsWith ( "\\" ) ) {
2316+ normalized = normalized . slice ( 0 , - 1 ) ;
2317+ }
2318+ } else {
2319+ if ( normalized . length > 1 && normalized . endsWith ( "/" ) ) {
2320+ normalized = normalized . slice ( 0 , - 1 ) ;
2321+ }
2322+ }
2323+ return normalized ;
2324+ }
23092325var REASON_RM_RF = "rm -rf outside cwd is blocked. Use explicit paths within the current directory, or delete manually." ;
23102326var REASON_RM_RF_ROOT_HOME = "rm -rf targeting root or home directory is extremely dangerous and always blocked." ;
23112327function analyzeRm ( tokens , options = { } ) {
@@ -2430,7 +2446,9 @@ function isTempTarget(path, allowTmpdirVar) {
24302446 return true ;
24312447 }
24322448 const systemTmpdir = tmpdir ( ) ;
2433- if ( normalized . startsWith ( `${ systemTmpdir } /` ) || normalized === systemTmpdir ) {
2449+ const normalizedTmpdir = normalizePathForComparison ( systemTmpdir ) ;
2450+ const pathToCompare = normalizePathForComparison ( normalized ) ;
2451+ if ( pathToCompare . startsWith ( `${ normalizedTmpdir } ${ sep } ` ) || pathToCompare === normalizedTmpdir ) {
24342452 return true ;
24352453 }
24362454 if ( allowTmpdirVar ) {
@@ -2448,27 +2466,24 @@ function getHomeDirForRmPolicy() {
24482466}
24492467function isCwdHomeForRmPolicy ( cwd , homeDir ) {
24502468 try {
2451- const normalizedCwd = normalize ( cwd ) ;
2452- const normalizedHome = normalize ( homeDir ) ;
2453- return normalizedCwd === normalizedHome ;
2469+ return normalizePathForComparison ( cwd ) === normalizePathForComparison ( homeDir ) ;
24542470 } catch {
24552471 return false ;
24562472 }
24572473}
24582474function isCwdSelfTarget ( target , cwd ) {
2459- if ( target === "." || target === "./" ) {
2475+ if ( target === "." || target === "./" || target === ".\\" ) {
24602476 return true ;
24612477 }
24622478 try {
24632479 const resolved = resolve2 ( cwd , target ) ;
24642480 const realCwd = realpathSync ( cwd ) ;
24652481 const realResolved = realpathSync ( resolved ) ;
2466- return realResolved === realCwd ;
2482+ return normalizePathForComparison ( realResolved ) === normalizePathForComparison ( realCwd ) ;
24672483 } catch {
24682484 try {
24692485 const resolved = resolve2 ( cwd , target ) ;
2470- const normalizedCwd = normalize ( cwd ) ;
2471- return resolved === normalizedCwd ;
2486+ return normalizePathForComparison ( resolved ) === normalizePathForComparison ( cwd ) ;
24722487 } catch {
24732488 return false ;
24742489 }
@@ -2482,20 +2497,21 @@ function isTargetWithinCwd(target, originalCwd, effectiveCwd) {
24822497 if ( target . includes ( "$" ) || target . includes ( "`" ) ) {
24832498 return false ;
24842499 }
2485- if ( target . startsWith ( "/" ) ) {
2500+ if ( target . startsWith ( "/" ) || / ^ [ A - Z a - z ] : [ \\ / ] / . test ( target ) ) {
24862501 try {
2487- const normalizedTarget = normalize ( target ) ;
2488- const normalizedCwd = `${ normalize ( originalCwd ) } / ` ;
2502+ const normalizedTarget = normalizePathForComparison ( target ) ;
2503+ const normalizedCwd = `${ normalizePathForComparison ( originalCwd ) } ${ sep } ` ;
24892504 return normalizedTarget . startsWith ( normalizedCwd ) ;
24902505 } catch {
24912506 return false ;
24922507 }
24932508 }
2494- if ( target . startsWith ( "./" ) || ! target . includes ( "/" ) ) {
2509+ if ( target . startsWith ( "./" ) || target . startsWith ( ".\\" ) || ! target . includes ( "/" ) && ! target . includes ( "\\ ") ) {
24952510 try {
24962511 const resolved = resolve2 ( resolveCwd , target ) ;
2497- const normalizedOriginalCwd = normalize ( originalCwd ) ;
2498- return resolved . startsWith ( `${ normalizedOriginalCwd } /` ) || resolved === normalizedOriginalCwd ;
2512+ const normalizedResolved = normalizePathForComparison ( resolved ) ;
2513+ const normalizedOriginalCwd = normalizePathForComparison ( originalCwd ) ;
2514+ return normalizedResolved . startsWith ( `${ normalizedOriginalCwd } ${ sep } ` ) || normalizedResolved === normalizedOriginalCwd ;
24992515 } catch {
25002516 return false ;
25012517 }
@@ -2505,18 +2521,17 @@ function isTargetWithinCwd(target, originalCwd, effectiveCwd) {
25052521 }
25062522 try {
25072523 const resolved = resolve2 ( resolveCwd , target ) ;
2508- const normalizedCwd = normalize ( originalCwd ) ;
2509- return resolved . startsWith ( `${ normalizedCwd } /` ) || resolved === normalizedCwd ;
2524+ const normalizedResolved = normalizePathForComparison ( resolved ) ;
2525+ const normalizedCwd = normalizePathForComparison ( originalCwd ) ;
2526+ return normalizedResolved . startsWith ( `${ normalizedCwd } ${ sep } ` ) || normalizedResolved === normalizedCwd ;
25102527 } catch {
25112528 return false ;
25122529 }
25132530}
25142531function isHomeDirectory ( cwd ) {
25152532 const home = process . env . HOME ?? homedir3 ( ) ;
25162533 try {
2517- const normalizedCwd = normalize ( cwd ) ;
2518- const normalizedHome = normalize ( home ) ;
2519- return normalizedCwd === normalizedHome ;
2534+ return normalizePathForComparison ( cwd ) === normalizePathForComparison ( home ) ;
25202535 } catch {
25212536 return false ;
25222537 }
@@ -3608,6 +3623,7 @@ function printReport(report) {
36083623
36093624// src/bin/explain/config.ts
36103625import { existsSync as existsSync5 } from "node:fs" ;
3626+ import { resolve as resolve3 } from "node:path" ;
36113627
36123628// src/core/env.ts
36133629function envTruthy ( name ) {
@@ -3637,7 +3653,7 @@ function getConfigSource(options) {
36373653 return { configSource : null , configValid : true } ;
36383654}
36393655function buildAnalyzeOptions ( explainOptions ) {
3640- const cwd = explainOptions ?. cwd ?? process . cwd ( ) ;
3656+ const cwd = resolve3 ( explainOptions ?. cwd ?? process . cwd ( ) ) ;
36413657 const paranoidAll = envTruthy ( "SAFETY_NET_PARANOID" ) ;
36423658 return {
36433659 cwd,
@@ -4852,18 +4868,18 @@ async function readStdinAsync() {
48524868 if ( process . stdin . isTTY ) {
48534869 return null ;
48544870 }
4855- return new Promise ( ( resolve3 ) => {
4871+ return new Promise ( ( resolve4 ) => {
48564872 let data = "" ;
48574873 process . stdin . setEncoding ( "utf-8" ) ;
48584874 process . stdin . on ( "data" , ( chunk ) => {
48594875 data += chunk ;
48604876 } ) ;
48614877 process . stdin . on ( "end" , ( ) => {
48624878 const trimmed = data . trim ( ) ;
4863- resolve3 ( trimmed || null ) ;
4879+ resolve4 ( trimmed || null ) ;
48644880 } ) ;
48654881 process . stdin . on ( "error" , ( ) => {
4866- resolve3 ( null ) ;
4882+ resolve4 ( null ) ;
48674883 } ) ;
48684884 } ) ;
48694885}
@@ -4927,7 +4943,7 @@ async function printStatusline() {
49274943
49284944// src/bin/verify-config.ts
49294945import { existsSync as existsSync8 , readFileSync as readFileSync6 , writeFileSync } from "node:fs" ;
4930- import { resolve as resolve3 } from "node:path" ;
4946+ import { resolve as resolve4 } from "node:path" ;
49314947var HEADER = "Safety Net Config" ;
49324948var SEPARATOR = "═" . repeat ( HEADER . length ) ;
49334949var SCHEMA_URL = "https://raw.githubusercontent.com/kenryu42/claude-code-safety-net/main/assets/cc-safety-net.schema.json" ;
@@ -4992,7 +5008,7 @@ function verifyConfig(options = {}) {
49925008 const result = validateConfigFile ( projectConfig ) ;
49935009 configsChecked . push ( {
49945010 scope : "Project" ,
4995- path : resolve3 ( projectConfig ) ,
5011+ path : resolve4 ( projectConfig ) ,
49965012 result
49975013 } ) ;
49985014 if ( result . errors . length > 0 ) {
0 commit comments