Skip to main content

Security configuration scanner for Claude Code

Project description

Clauditor

Clauditor

Security configuration scanner for Claude Code.

Tests Security Lint PyPI Python License

Clauditor audits your Claude Code settings and repository configuration to detect security misconfigurations.


Table of Contents


Features

  • Scans all Claude Code configuration scopes: user, project, local, and managed
  • Checks repository-level files (CODEOWNERS, CLAUDE.md, etc.)
  • Checks are defined as YAML files โ€” easy to read, extend, and contribute
  • Each check maps to a concrete threat, severity, and remediation
  • Scan a local path, a remote git URL, or just the current directory
  • Rich terminal output with optional verbose remediation steps
  • CI-friendly --exit-code flag
  • --base-level flag to enforce a minimum required scope

๐Ÿ‘‰ Browse all checks โ†’


Installation

The recommended way to install Clauditor is with pipx, which installs CLI tools in isolated environments and makes them available system-wide:

pipx install clauditor

Install pipx if you don't have it yet:

# macOS
brew install pipx && pipx ensurepath

# Linux / WSL
python3 -m pip install --user pipx && pipx ensurepath

Alternative โ€” pip inside a virtual environment:

python3 -m venv .venv
source .venv/bin/activate
pip install clauditor

From source:

git clone https://github.com/gabrielsoltz/clauditor
cd clauditor
python3.13 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Usage

# Scan current directory (project + user scope settings)
clauditor scan

# Scan a specific local repository
clauditor scan --path /path/to/repo

# Clone and scan a remote repository
clauditor scan --url https://github.com/org/repo

# Filter by severity
clauditor scan --severity CRITICAL,HIGH

# Show remediation steps for failed checks
clauditor scan -v

# Exit with code 1 if any failures found (for CI)
clauditor scan --exit-code

# List all available checks
clauditor list-checks

# Generate a settings file (user scope by default)
clauditor generate

# Generate a managed settings file covering all checks
clauditor generate --scope managed -o managed-settings.json

Configuration Scopes

Claude Code reads settings from multiple locations. Each location is a scope. Understanding scopes is key to understanding Clauditor's output.

See the official Claude Code settings documentation for details.

The four Claude Code scopes

Column Scope File Who it applies to
M managed System path (platform-specific) Everyone on the machine; deployed by IT
L local .claude/settings.local.json You, in this repo only; gitignored
P project .claude/settings.json All collaborators; committed to git
U user ~/.claude/settings.json You, across all projects

Scope precedence

When the same setting exists in multiple scopes, Claude Code applies the highest-precedence scope:

managed  >  local  >  project  >  user
(highest)                        (lowest)

managed is set by an administrator and cannot be overridden by anyone. local takes precedence over project, which means a developer can use .claude/settings.local.json to override what the team committed in .claude/settings.json.

Repository scope (Clauditor extension)

Column Scope What it checks
R repository VCS governance files: CODEOWNERS, workflow configs, etc.

repository is not a Claude Code scope โ€” it's Clauditor's own concept for checks that look at repository governance files rather than Claude Code JSON settings. It has no precedence relationship with the config scopes above.


How Findings Work

Per-scope icons in the output table

Each scope column shows one icon:

Icon Meaning
โœ” Setting is correctly configured at this scope
โœ˜ Setting is present but has the wrong value
โ†‘ Covered โ€” a higher-precedence scope already passes, so this scope is irrelevant
โ€“ Skipped โ€” the settings file for this scope was not found or is empty
ยท N/A โ€” this check does not apply to this scope

How the effective (overall) status is decided

The effective status in the Status column is determined by the highest-precedence scope that is not skipped:

  • If managed=PASS โ†’ effective is PASS, regardless of lower scopes. All lower scopes show โ†‘ (covered).
  • If managed=FAIL โ†’ effective is FAIL, regardless of lower scopes. A wrong value at the top level locks everyone.
  • If managed=โ€“, local=โ€“, project=PASS โ†’ effective is PASS, user shows โ†‘ (covered).
  • If all config scopes are โ€“ (not configured anywhere) โ†’ effective is FAIL. A missing setting is not a passing setting.

Scenario examples

Scenario A โ€” Enforced via managed settings (best)

M L P U Status
โœ” โ†‘ โ†‘ โ†‘ โœ” PASS

Setting is in managed. Everyone on the machine is protected. Lower scopes are irrelevant.

Scenario D โ€” Nobody has it set

M L P U Status
โ€“ โ€“ โ€“ โ€“ โœ˜ FAIL

The setting is not configured anywhere. This is always FAIL โ€” a missing setting provides no protection.


Enforcing a Minimum Scope

By default, Clauditor marks a check as PASS if the setting is correctly configured at any scope. However, you may want to require enforcement at a specific level.

# Require the setting to exist at project scope or above (for team-wide enforcement)
clauditor scan --base-level project

# Require enterprise-wide enforcement through managed settings only
clauditor scan --base-level managed

With --base-level project, a setting that is only present in the user scope becomes FAIL โ€” the setting is only personal and doesn't protect the team.

--base-level What passes
user (default) Any scope: user, project, local, or managed
project Must be in project, local, or managed (not just user)
local Must be in local or managed (not just project/user)
managed Only managed qualifies

Check Format

Checks live in the checks/ directory as YAML files. Example structure:

id: CC001
name: CODEOWNERS Enforcement for Claude Code Paths
description: >
  Ensures that /.claude/ and /CLAUDE.md have CODEOWNERS entries
  requiring security team review.

scope:
  - repository

severity: HIGH  # CRITICAL | HIGH | MEDIUM | LOW | INFO

threat: >
  Without CODEOWNERS enforcement, contributors can silently modify
  Claude Code settings, hooks, or instructions without security review...

category: access_control

check_type: file_content  # config_value | config_contains | config_set | file_content | file_exists

check_config:
  search_paths:
    - CODEOWNERS
    - .github/CODEOWNERS
  required_entries:
    - pattern: "/.claude/"
      owner: "@security-team"
    - pattern: "/CLAUDE.md"
      owner: "@security-team"

remediation: >
  Add to CODEOWNERS:
    /.claude/ @security-team
    /CLAUDE.md @security-team

fix_available: true

references:
  - https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
  - https://code.claude.com/docs/en/settings

Check Types

check_type check_config keys Description
config_value key, expected_value Verifies a key/value in a JSON settings file
config_contains key, required_values Verifies a list key contains all required values
config_set key Verifies a key is present and non-empty (any truthy value)
file_content search_paths, required_entries Verifies required lines exist in a file
file_exists paths, any_of Verifies file(s) exist in the repository

Generating a Settings File

clauditor generate produces a ready-to-deploy JSON settings file containing all the values needed to remediate the applicable checks.

clauditor generate                          # All checks โ†’ user settings
clauditor generate --scope managed         # Full managed settings file
clauditor generate --scope project         # Project-level (.claude/settings.json)
clauditor generate --severity CRITICAL     # Only critical checks
clauditor generate --checks CC002,CC010    # Specific checks only
clauditor generate --scope managed -o managed-settings.json

Scope controls which checks are included:

--scope Checks included
user (default) user-scoped checks only
project project + user checks
local local + project + user checks
managed All config checks: managed + local + project + user

What gets generated:

  • config_value checks โ†’ sets the key to its required value
  • config_contains checks โ†’ builds/merges the required list entries (e.g. multiple checks writing to permissions.deny are merged automatically)
  • config_set checks โ†’ skipped (e.g. forceLoginOrgUUID requires your org-specific UUID; reported separately)
  • file_content / file_exists checks โ†’ skipped (repository governance files, not settings values)

Example output (clauditor generate --scope managed):

{
  "disableBypassPermissionsMode": "disable",
  "allowManagedPermissionRulesOnly": true,
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(**/.env)",
      "Read(secrets/**)",
      "Write(secrets/**)",
      "Read(**/credentials)",
      "Bash(curl:*)",
      "Bash(wget:*)"
    ]
  },
  "enableAllProjectMcpServers": false,
  "allowManagedHooksOnly": true,
  "forceLoginMethod": "claudeai",
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "denyWrite": ["/etc", "/usr", "~/.ssh", "~/.aws"],
      "denyRead": ["~/.ssh", "~/.aws/credentials", ".env", "**/.env"]
    }
  }
}

Adding a Custom Check

  1. Create a new YAML file in checks/ following the format above.
  2. Assign the next available CC### ID.
  3. Run clauditor list-checks to verify it loads correctly.
  4. Run clauditor scan to see results.

No code changes required.


Architecture

clauditor/
โ”œโ”€โ”€ cli.py              # Typer CLI entry point
โ”œโ”€โ”€ scanner.py          # Orchestrates checks against providers
โ”œโ”€โ”€ loader.py           # YAML check loader with Pydantic validation
โ”œโ”€โ”€ aggregator.py       # Scope precedence + base_level logic
โ”œโ”€โ”€ generator.py        # Settings file generator
โ”œโ”€โ”€ models/
โ”‚   โ”œโ”€โ”€ check.py        # Check, Scope, Severity, CheckType models
โ”‚   โ””โ”€โ”€ finding.py      # Finding, FindingStatus models
โ”œโ”€โ”€ providers/
โ”‚   โ”œโ”€โ”€ base.py         # BaseProvider interface
โ”‚   โ”œโ”€โ”€ config_provider.py   # User, Project, Local, Managed providers
โ”‚   โ””โ”€โ”€ repository_provider.py  # Repository file provider + git clone
โ”œโ”€โ”€ checkers/
โ”‚   โ”œโ”€โ”€ config_value.py     # Logic for config_value checks
โ”‚   โ”œโ”€โ”€ config_contains.py  # Logic for config_contains checks
โ”‚   โ”œโ”€โ”€ config_set.py       # Logic for config_set checks
โ”‚   โ”œโ”€โ”€ file_content.py     # Logic for file_content checks
โ”‚   โ””โ”€โ”€ file_exists.py      # Logic for file_exists checks
โ””โ”€โ”€ output/
    โ””โ”€โ”€ console.py       # Rich terminal output

checks/                  # YAML check definitions

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clauditor-0.4.1.tar.gz (50.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clauditor-0.4.1-py3-none-any.whl (92.9 kB view details)

Uploaded Python 3

File details

Details for the file clauditor-0.4.1.tar.gz.

File metadata

  • Download URL: clauditor-0.4.1.tar.gz
  • Upload date:
  • Size: 50.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clauditor-0.4.1.tar.gz
Algorithm Hash digest
SHA256 9397c4929cb84943e10908c2fb8e98c1bc1af6ad6000ee82fe76bec5c9fd1381
MD5 82482a14f1e8b84f68121f9316dd0e6e
BLAKE2b-256 ecfb60c378cdfd8b3d6710c867c9c8a74543042614b28c49189dddc7e3725e98

See more details on using hashes here.

Provenance

The following attestation bundles were made for clauditor-0.4.1.tar.gz:

Publisher: python-publish.yml on gabrielsoltz/clauditor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file clauditor-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: clauditor-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 92.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clauditor-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bb6052d5c982d4158fb9ea063f7d470ecdafa7cbc46e6b12f29c1d61a5dd796d
MD5 63190c78e9ffb78c0a11f83771afad97
BLAKE2b-256 7ac3fbc43570fff98422cf70c40b7576061973f8b8213623a6c856a8aeee2870

See more details on using hashes here.

Provenance

The following attestation bundles were made for clauditor-0.4.1-py3-none-any.whl:

Publisher: python-publish.yml on gabrielsoltz/clauditor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page