JuliusBrussee/caveman · error

sqlite parent grants broad Windows write access

Error message

sqlite parent %q grants broad Windows write access

What it means

The library validates that the parent directory of its SQLite recovery database is not writable by broad groups (Everyone, Authenticated Users, Builtin Users, Builtin Guests). If any allow ACE granting write/append/delete/DELETE_CHILD/WRITE_DAC/WRITE_OWNER or generic write access to one of those SIDs is found on the directory's DACL, it refuses to proceed rather than risk tampering with the recovery store. This is a deliberate fail-closed security check for the CCR store on Windows.

Solutions

  1. Restrict the parent directory ACL so no broad SID holds write access (e.g. icacls <dir> /inheritance:r /grant:r "%USERNAME%":F) and retry
  2. Point the CCR database path at a user-private directory (e.g. %USERPROFILE%\.caveman) whose ACLs only grant your account access
  3. Inspect the offending ACEs with icacls <dir> or Get-Acl to identify which broad SID is granted write and remove that specific ACE
  4. Verify after fixing that the directory is not on a volume applying broad default inheritance from a shared parent

Example fix

# before: broad ACEs on the store directory
icacls C:\Users\me\.caveman  # shows BUILTIN\Users:(W)
# after: strip inheritance, keep only current user
icacls C:\Users\me\.caveman /inheritance:r /grant:r "%USERNAME%":F
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check the parent directory ACL with PowerShell before starting the engine
// icacls <parentDir> — fail if output shows Everyone, Authenticated Users,
// BUILTIN\Users, or BUILTIN\Guests with (W)/(M)/(F)/(DE) rights
// Harden with:
//   icacls <parentDir> /inheritance:r /grant:r "%USERNAME%":F

Try / catch

if err := store.Put(ctx, obj); err != nil {
  if strings.Contains(err.Error(), "grants broad Windows write access") {
    return fmt.Errorf("refusing to use CCR store %s: %w (harden the directory ACL first)", ccrPath, err)
  }
  return err
}

Prevention

When it happens

Trigger: Any CCR store operation (PutObject/putObject path) on Windows where the DB parent directory's DACL contains an inherit-only-excluded, allow-type ACE for WinWorldSid, WinAuthenticatedUserSid, WinBuiltinUsersSid, or WinBuiltinGuestsSid with a broad write mask — e.g. a home directory or temp folder with default Users-write ACLs.

Common situations: Running the engine under a profile or directory whose defaults include BUILTIN\Users write ACEs (e.g. C:\Users\Public, shared temp folders); manually loosened ACLs via icacls; cloned/rolled-back VMs or restored directories whose ACL inheritance was widened; relocating the CCR db to a shared folder.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/6e851f5646450cf4. Report an issue: GitHub.

Appendix: source

Thrown at engine/ccr/sqlite_parent_security_windows.go:34

		windows.SE_FILE_OBJECT,
		windows.DACL_SECURITY_INFORMATION,
	)
	if err != nil {
		return fmt.Errorf("inspect sqlite parent ACL %q: %w", path, err)
	}
	if descriptor == nil {
		return fmt.Errorf("sqlite parent %q has no security descriptor", path)
	}
	dacl, _, err := descriptor.DACL()
	if err != nil || dacl == nil {
		return fmt.Errorf("sqlite parent %q has no restrictive DACL", path)
	}
	broad, err := windowsACLGrantsBroadWrite(dacl)
	if err != nil {
		return fmt.Errorf("inspect sqlite parent ACL %q: %w", path, err)
	}
	if broad {
		return fmt.Errorf("sqlite parent %q grants broad Windows write access", path)
	}
	return nil
}

func windowsACLGrantsBroadWrite(dacl *windows.ACL) (bool, error) {
	broadSIDs := make([]*windows.SID, 0, 4)
	for _, sidType := range []windows.WELL_KNOWN_SID_TYPE{
		windows.WinWorldSid,
		windows.WinAuthenticatedUserSid,
		windows.WinBuiltinUsersSid,
		windows.WinBuiltinGuestsSid,
	} {
		sid, err := windows.CreateWellKnownSid(sidType)
		if err != nil {
			return false, err
		}
		broadSIDs = append(broadSIDs, sid)
	}

View on GitHub (pinned to 3ee70a1026)