evidenceops

ClawSkills 作者 OpenClaw Community v1.0.0

Forensic media triage with chain of custody. Use when receiving images, videos, audio, PDFs, or documents that need evidence-grade handling, integrity verification, and audit trails.

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install clawskills:clawskills~msrovani-skill-evidenceops
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/clawskills%3Aclawskills~msrovani-skill-evidenceops/file -o msrovani-skill-evidenceops.md
# EvidenceOps - Forensic Media Triage

## What It Does

EvidenceOps provides forensic-grade handling of media files with complete chain of custody:

1. **Media Intake** - Accept images, videos, audio, PDFs, and documents from any channel
2. **Immutable Storage** - Store originals in append-only vault with cryptographic hashes
3. **Metadata Extraction** - Extract EXIF, file properties, and media information without altering originals
4. **Derivative Generation** - Create thumbnails, transcripts, previews in separate folders
5. **Chain of Custody** - Maintain tamper-evident audit trail with hash chain
6. **Integrity Verification** - Verify evidence hasn't been modified post-ingest
7. **Audit Trail** - Complete JSONL audit log for compliance

## What It NEVER Does

- **NEVER** modifies original evidence files after ingest
- **NEVER** stores secrets, API keys, or credentials in manifests or logs
- **NEVER** accepts unsanitized paths from user input
- **NEVER** executes untrusted code or downloads remote scripts
- **NEVER** exfiltrates data to external services without explicit configuration
- **NEVER** bypasses channel allowlists or pairing requirements
- **NEVER** stores real personal data in example files

## Prerequisites

Before using this skill, ensure:

1. Plugin `@openclaw/evidence-vault` is installed and initialized
2. Vault storage directory is configured with appropriate permissions
3. Channel allowlist is configured for trusted sources only
4. Retention policies comply with your legal requirements

## Workflow

### Step 1: Receive Media

When media is received via any channel:

```
User sends: [image/video/document]
```

**Required Information:**
- File content (from attachment)
- Original filename
- Source channel (whatsapp, telegram, email, etc.)
- Sender identifier
- Message ID (if available)

### Step 2: Create or Select Case

```
IF user specifies existing caseId:
  USE that caseId
ELSE IF user requests new case:
  CREATE case with format: case-{YYYY}-{NNN}
  EXAMPLE: case-2026-001
ELSE:
  ASK user: "Should I create a new case or add to existing case [case-2026-XXX]?"
```

**Case ID Format:** `case-{year}-{sequence}`
- Must match pattern: `^case-[a-zA-Z0-9_-]+$`
- Examples: `case-2026-001`, `case-incident-alpha`, `case-legal-2026-q1`

### Step 3: Stage Original (Read-Only)

Before ingest:

1. **Save received file to temporary staging area**
2. **Calculate SHA-256 hash immediately**
3. **Record file size and MIME type**
4. **DO NOT modify the file**

```
# Staging directory structure
/tmp/evidence-staging/
├── {caseId}/
│   └── {timestamp}-{filename}
```

### Step 4: Extract Metadata

Extract metadata WITHOUT modifying original:

**For Images:**
- EXIF data (camera, GPS, timestamps)
- Dimensions
- Color profile

**For Videos:**
- Duration
- Codec information
- Resolution

**For Audio:**
- Duration
- Sample rate
- Codec

**For PDFs:**
- Page count
- Author (if embedded)
- Creation date

```
# Use Read tool or appropriate extraction commands
# NEVER write back to original file
```

### Step 5: Generate Derivatives (Optional)

Create derivative artifacts in SEPARATE folder:

```
derivatives/
├── thumbnails/
│   └── {evidenceId}-thumb.jpg
├── transcripts/
│   └── {evidenceId}-transcript.txt
└── previews/
    └── {evidenceId}-preview.pdf
```

**Derivative Types:**
- `thumbnail` - Reduced resolution image/video preview
- `transcript` - Speech-to-text for audio/video
- `preview` - PDF or text representation
- `ocr` - Extracted text from images

### Step 6: Ingest to Vault

Call the evidence.ingest tool:

```json
{
  "filePath": "/path/to/staged/file",
  "filename": "original-filename.jpg",
  "caseId": "case-2026-001",
  "channel": "whatsapp",
  "sender": "user@example.com",
  "messageId": "msg-abc123",
  "retentionDays": 2555,
  "metadata": {
    "exif": { ... },
    "extracted": { ... }
  }
}
```

**Response:**
```json
{
  "success": true,
  "evidenceId": "ev-abc123...",
  "sha256": "a1b2c3...",
  "vaultUrl": "file:///vault/cases/case-2026-001/originals/ev-abc123.jpg",
  "timestamp": "2026-02-17T10:30:00.000Z"
}
```

### Step 7: Update Manifest

The manifest is automatically updated by the ingest operation.

**Manifest Location:** `{vault}/cases/{caseId}/manifest.json`

**Manifest Contents:**
- Case metadata
- Evidence items with hashes
- Derivatives
- Chain of custody entries
- Retention policy

### Step 8: Return Receipt

Provide user with evidence receipt:

```
📋 EVIDENCE RECEIPT

Case ID: case-2026-001
Evidence ID: ev-abc123...
File: original-filename.jpg
SHA-256: a1b2c3d4e5f6...
Size: 1.2 MB
Received: 2026-02-17 10:30:00 UTC
Vault: file:///vault/cases/case-2026-001/originals/ev-abc123.jpg

✅ Chain of custody established
✅ Original preserved immutably
✅ Audit trail active
```

## Tool Reference

### evidence.ingest

Ingest a file into the evidence vault.

**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| filePath | string | Yes | Path to the staged file |
| filename | string | Yes | Original filename |
| caseId | string | Yes | Case identifier |
| channel | string | No | Source channel |
| sender | string | No | Sender identifier |
| messageId | string | No | Message ID from source |
| retentionDays | number | No | Retention period |
| metadata | object | No | Additional metadata |

**Returns:** `{ evidenceId, sha256, vaultUrl, timestamp }`

### evidence.verify

Verify evidence integrity.

**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| evidenceId | string | Yes | Evidence to verify |
| caseId | string | No | Limit search to case |

**Returns:** `{ verified, details: { originalIntact, hashMatch, lastVerifiedAt } }`

### evidence.manifest

Get case manifest.

**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| caseId | string | Yes | Case identifier |

**Returns:** Complete case manifest with all items

### evidence.export

Export case as archive.

**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| caseId | string | Yes | Case identifier |
| format | string | No | 'zip' or 'tar' (default: zip) |

**Returns:** `{ exportPath, sha256, size, itemCount }`

### evidence.access_log

Get audit trail.

**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| caseId | string | Yes | Case identifier |
| limit | number | No | Max events (default: 100) |

**Returns:** `{ events: [ ... ], count }`

## SECURITY POSTURE

### Channel Allowlist Configuration

Configure which channels can submit evidence:

```yaml
# ~/.openclaw/openclaw.json
{
  "plugins": {
    "evidence-vault": {
      "channelAllowlist": ["whatsapp", "telegram", "email"],
      "channelDenylist": ["public-discord"],
      "requirePairing": true
    }
  }
}
```

### Pairing Requirements

For Direct Messages (DMs):
- **REQUIRE** pairing before accepting evidence
- **BLOCK** unpaired DMs by default
- **LOG** rejected ingestion attempts

For Group Channels:
- **VERIFY** channel is in allowlist
- **REJECT** evidence from untrusted channels
- **NEVER** auto-ingest from public channels

### Path Sanitization Rules

ALL paths are validated:

1. **No path traversal** - `../` sequences rejected
2. **No null bytes** - `\0` rejected
3. **No home directory** - `~/` rejected
4. **Canonicalization** - Paths resolved before validation
5. **Base path check** - Must be within vault directory

**Violations result in:** `E_PATH_TRAVERSAL` error + audit log entry

### Destructive Action Confirmation

Before any potentially destructive operation:

1. **EXPORT** - Confirm export destination
2. **RETENTION DELETE** - Require explicit confirmation (if enabled)
3. **LEGAL HOLD RELEASE** - Require explicit confirmation

**Confirmation format:**
```
⚠️ DESTRUCTIVE ACTION

You are about to: [describe action]
Case: [caseId]
Items a