# How VulnClaw Handles Target State Management and Rollbacks

> Learn how VulnClaw manages target states and handles rollbacks. Revert assessments to previous states using timestamped snapshots saved in JSON files.

- Repository: [Unclecheng/VulnClaw](https://github.com/Unclecheng-li/VulnClaw)
- Tags: internals
- Published: 2026-06-30

---

**VulnClaw implements rollback functionality by maintaining timestamped snapshots of target states in JSON files, allowing users to revert assessments to any previous point by overwriting the active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) with a selected snapshot.**

VulnClaw persists target assessment data to disk using a deterministic directory structure based on SHA-256 hashing. Each target maintains an active state file and a history of snapshots, enabling robust **VulnClaw target state management rollbacks** when assessments need to be rewound to earlier configurations.

## How Target State Persistence Works

### State Storage Architecture

VulnClaw organizes target data under a dedicated `TARGETS_DIR` directory defined in [`vulnclaw/config/settings.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/config/settings.py). The system uses the `_target_path()` function in [`vulnclaw/target_state/store.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/target_state/store.py) to compute deterministic storage locations by hashing target names with SHA-256.

Each target receives its own subdirectory containing:
- An active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) file representing the current assessment state
- A `snapshots/` subfolder containing historical versions

```python

# Deterministic path resolution via SHA-256 hashing

# Located in vulnclaw/target_state/store.py

def _target_path(target_name):
    target_hash = hashlib.sha256(target_name.encode()).hexdigest()
    return os.path.join(TARGETS_DIR, target_hash, "state.json")

```

### Snapshot Creation Process

Every command execution triggers `save_target_state()` (lines 21-30 in [`vulnclaw/target_state/store.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/target_state/store.py)), which performs dual writes:
1. Updates the active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) with current session data
2. Creates a timestamped snapshot in `snapshots/` with a unique ID format: [`YYYYMMDDHHMMSS_microseconds_command.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/YYYYMMDDHHMMSS_microseconds_command.json)

```python

# Example snapshot filename format

# 20240630_134215_123456_scan_command.json

```

This automatic snapshotting ensures that **VulnClaw target state management rollbacks** are always available to recent commands without manual intervention.

## The Rollback Mechanism

### Loading Snapshots

The `load_target_state()` function (lines 51-58) retrieves state data from either the active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) or a specific snapshot file. When requesting a specific snapshot by ID, the function checks the `snapshots/` directory and returns `None` if the requested version does not exist.

```python
from vulnclaw.target_state.store import load_target_state

# Load a specific snapshot for inspection

state_data = load_target_state("192.168.1.100", "20240630_101500_000001_run")
if state_data is None:
    print("Snapshot not found")

```

### Executing Rollbacks

The `rollback_target_state()` function (lines 43-50) handles the actual restoration process:
1. Loads the specified snapshot via `load_target_state()`
2. Overwrites the active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) path (retrieved via `_target_path()`) with the snapshot contents
3. Returns the path of the restored file or `None` if the snapshot is unavailable

```python
from vulnclaw.target_state.store import rollback_target_state

target = "192.168.1.100"
snapshot_id = "20240630_101500_000001_run"

restored_path = rollback_target_state(target, snapshot_id)
if restored_path:
    print(f"State restored to: {restored_path}")
else:
    print("Rollback failed: snapshot not found")

```

## Working with Snapshots Programmatically

Before performing **VulnClaw target state management rollbacks**, users typically inspect available snapshots using `list_target_snapshots()` (lines 19-40). This function reads all `*.json` files in the target's snapshots directory and returns metadata including snapshot ID, timestamp, and associated command.

```python
from vulnclaw.target_state.store import list_target_snapshots

snapshots = list_target_snapshots("192.168.1.100")
for snap in snapshots:
    print(f"{snap['snapshot_id']} – {snap['last_saved_at']} ({snap['last_command']})")

```

This programmatic interface enables automation workflows where rollback decisions depend on snapshot metadata rather than manual file inspection.

## CLI Integration

The command-line interface in [`vulnclaw/cli/main.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/cli/main.py) exposes the rollback capability through a dedicated `rollback` subcommand. This CLI wrapper forwards the target name and snapshot ID directly to `rollback_target_state()`, providing a user-friendly entry point for manual state restoration without requiring Python imports.

```bash

# CLI usage example

vulnclaw rollback 192.168.1.100 20240630_101500_000001_run

```

According to the VulnClaw source code, the CLI validates the snapshot ID format before invoking the store API, though the actual existence check occurs within the `rollback_target_state()` function.

## Summary

- **VulnClaw target state management rollbacks** rely on automatic snapshot creation after every command, storing timestamped JSON files in per-target directories.
- The rollback mechanism overwrites the active [`state.json`](https://github.com/Unclecheng-li/VulnClaw/blob/main/state.json) by copying contents from a selected snapshot file in the `snapshots/` subfolder.
- Core functions reside in [`vulnclaw/target_state/store.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/target_state/store.py): `rollback_target_state()` (lines 43-50) performs restores, while `save_target_state()` (lines 21-30) creates snapshots.
- Directory paths are deterministically generated using SHA-256 hashing of target names via `_target_path()`.
- Both programmatic APIs and CLI interfaces support rollback operations, returning `None` when snapshot IDs cannot be found.

## Frequently Asked Questions

### How does VulnClaw determine where to store target state files?

VulnClaw computes storage locations using the `_target_path()` function in [`vulnclaw/target_state/store.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/target_state/store.py), which generates a SHA-256 hash of the target name to create a deterministic directory under `TARGETS_DIR`. This ensures consistent file paths across sessions while avoiding filesystem conflicts with special characters in target names.

### What happens if I try to rollback to a snapshot that does not exist?

The `rollback_target_state()` function returns `None` when a requested snapshot ID cannot be found in the target's `snapshots/` directory. Similarly, `load_target_state()` returns `None` for missing snapshots, allowing calling code to handle the error gracefully without raising exceptions.

### How can I view available snapshots before performing a rollback?

Use the `list_target_snapshots()` function (lines 19-40 in [`vulnclaw/target_state/store.py`](https://github.com/Unclecheng-li/VulnClaw/blob/main/vulnclaw/target_state/store.py)) to retrieve metadata for all available snapshots. This returns a list of dictionaries containing the snapshot ID, save timestamp, and command name, enabling informed selection of rollback targets.

### Does VulnClaw keep unlimited snapshots, or is there a retention policy?

The source code analysis indicates that snapshots are stored indefinitely in the `snapshots/` subfolder as individual JSON files. Users must manually manage disk space by removing old snapshot files if retention limits are required, as the current implementation does not enforce automatic expiration of historical states.