BUG-HUNT: [error-handling] PersistentSessionService.import_session() checksum computation uses sha256 prefix inconsistently #7345

Open
opened 2026-04-10 17:57:41 +00:00 by HAL9000 · 3 comments
Owner

Bug Report: [error-handling] PersistentSessionService.import_session() checksum verification has prefix inconsistency causing verification failures

Severity Assessment

  • Impact: Session imports can fail with a SessionImportError("Checksum verification failed") even for legitimate export files, preventing session restoration
  • Likelihood: Medium — depends on which version generated the export and whether the prefix was included in the raw checksum value
  • Priority: Medium

Location

  • File: src/cleveragents/application/services/session_service.py
  • Function/Class: PersistentSessionService.import_session()
  • Lines: ~175-195

Description

In import_session(), the checksum handling has an inconsistency:

  1. The raw checksum is extracted from the data: raw_checksum = data.get("checksum")
  2. The "sha256:" prefix is added to raw_checksum: checksum = "sha256:" + raw_checksum
  3. The expected checksum is computed with the prefix: expected_checksum = "sha256:" + hashlib.sha256(...).hexdigest()
  4. The comparison is: if checksum != expected_checksum

This means checksum = "sha256:" + raw_checksum.

The bug: if raw_checksum itself already includes the "sha256:" prefix (e.g., if as_export_dict() exports the checksum as "sha256:abc123..."), then checksum would be "sha256:sha256:abc123...", which would never match expected_checksum = "sha256:abc123...".

Conversely, if raw_checksum is just the hex digest without prefix (e.g., "abc123..."), then checksum = "sha256:abc123..." which matches expected_checksum.

The inconsistency means the behavior depends entirely on what as_export_dict() produces, and if that format ever changes, all existing export files become unimportable without any migration path.

Evidence

def import_session(self, data: dict[str, Any]) -> Session:
    # ...
    raw_checksum = data.get("checksum")
    if raw_checksum is None:
        raise SessionImportError("Missing checksum in import data")
    checksum = "sha256:" + raw_checksum  # BUG: blindly adds "sha256:" prefix
    # If raw_checksum is "sha256:abc123..." this becomes "sha256:sha256:abc123..."

    # Recompute checksum
    data_without_checksum = {k: v for k, v in data.items() if k != "checksum"}
    canonical = json.dumps(data_without_checksum, sort_keys=True, default=str)
    expected_checksum = "sha256:" + hashlib.sha256(canonical.encode()).hexdigest()
    if checksum != expected_checksum:  # Will ALWAYS fail if raw_checksum had prefix
        raise SessionImportError("Checksum verification failed")

Expected Behavior

The checksum comparison should normalize the format — either always strip the prefix before comparing the hex digests, or check for the prefix before adding it:

# Option 1: Strip prefix if present, compare raw hex
raw_checksum = data.get("checksum", "")
if raw_checksum.startswith("sha256:"):
    raw_hex = raw_checksum[7:]
else:
    raw_hex = raw_checksum

expected_hex = hashlib.sha256(canonical.encode()).hexdigest()
if raw_hex != expected_hex:
    raise SessionImportError("Checksum verification failed")

Actual Behavior

The "sha256:" prefix is unconditionally prepended to whatever is stored in the "checksum" key. If the export format stores "sha256:<hex>" (which is a common convention), then all imports will fail with a checksum mismatch.

Category

error-handling

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.


Automated by CleverAgents Bot
Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor

## Bug Report: [error-handling] PersistentSessionService.import_session() checksum verification has prefix inconsistency causing verification failures ### Severity Assessment - **Impact**: Session imports can fail with a `SessionImportError("Checksum verification failed")` even for legitimate export files, preventing session restoration - **Likelihood**: Medium — depends on which version generated the export and whether the prefix was included in the raw checksum value - **Priority**: Medium ### Location - **File**: `src/cleveragents/application/services/session_service.py` - **Function/Class**: `PersistentSessionService.import_session()` - **Lines**: ~175-195 ### Description In `import_session()`, the checksum handling has an inconsistency: 1. The raw checksum is extracted from the data: `raw_checksum = data.get("checksum")` 2. The `"sha256:"` prefix is **added** to `raw_checksum`: `checksum = "sha256:" + raw_checksum` 3. The expected checksum is computed with the prefix: `expected_checksum = "sha256:" + hashlib.sha256(...).hexdigest()` 4. The comparison is: `if checksum != expected_checksum` This means `checksum = "sha256:" + raw_checksum`. **The bug**: if `raw_checksum` itself already includes the `"sha256:"` prefix (e.g., if `as_export_dict()` exports the checksum as `"sha256:abc123..."`), then `checksum` would be `"sha256:sha256:abc123..."`, which would **never match** `expected_checksum = "sha256:abc123..."`. Conversely, if `raw_checksum` is just the hex digest without prefix (e.g., `"abc123..."`), then `checksum = "sha256:abc123..."` which matches `expected_checksum`. The inconsistency means the behavior depends entirely on what `as_export_dict()` produces, and if that format ever changes, all existing export files become unimportable without any migration path. ### Evidence ```python def import_session(self, data: dict[str, Any]) -> Session: # ... raw_checksum = data.get("checksum") if raw_checksum is None: raise SessionImportError("Missing checksum in import data") checksum = "sha256:" + raw_checksum # BUG: blindly adds "sha256:" prefix # If raw_checksum is "sha256:abc123..." this becomes "sha256:sha256:abc123..." # Recompute checksum data_without_checksum = {k: v for k, v in data.items() if k != "checksum"} canonical = json.dumps(data_without_checksum, sort_keys=True, default=str) expected_checksum = "sha256:" + hashlib.sha256(canonical.encode()).hexdigest() if checksum != expected_checksum: # Will ALWAYS fail if raw_checksum had prefix raise SessionImportError("Checksum verification failed") ``` ### Expected Behavior The checksum comparison should normalize the format — either always strip the prefix before comparing the hex digests, or check for the prefix before adding it: ```python # Option 1: Strip prefix if present, compare raw hex raw_checksum = data.get("checksum", "") if raw_checksum.startswith("sha256:"): raw_hex = raw_checksum[7:] else: raw_hex = raw_checksum expected_hex = hashlib.sha256(canonical.encode()).hexdigest() if raw_hex != expected_hex: raise SessionImportError("Checksum verification failed") ``` ### Actual Behavior The `"sha256:"` prefix is unconditionally prepended to whatever is stored in the `"checksum"` key. If the export format stores `"sha256:<hex>"` (which is a common convention), then all imports will fail with a checksum mismatch. ### Category error-handling ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. --- **Automated by CleverAgents Bot** Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor
Author
Owner

Verified — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Bug: inconsistent sha256 prefix in checksum computation. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#7345
No description provided.