Audit Integrity
Audit Integrity ensures the audit trail has not been tampered with by validating SHA-256 checksums stored on every audit record. Compliant with ISO 27001 A.12.4.2 (protection of log information).
'alt' => 'Dashboard overview', 'caption' => 'The default Kiwire dashboard layout', 'screenshot' => true, 'class' => '', ]) Drop images into: public/assets/img/docs/{page}/{filename} --}}public/assets/img/docs/audit-integrity/overview.png
How It Works
Every audit record is written with a checksum column. When the record is created, Kiwire computes a SHA-256 hash over 10 key fields and stores the result:
user_typeuser_ideventauditable_typeauditable_idold_valuesnew_valuesurlip_addresscreated_at
The hash is computed once and never updated. If any of these 10 fields is modified after the record is written — whether through a direct database query, a backup restore, or an application bug — the checksum will no longer match the recomputed value, indicating tampering.
Running Verification
Verification is performed by the kiwire:verify-audits Artisan command. It reads every audit record, recomputes the SHA-256 hash, and compares it against the stored checksum.
# Verify all records for all tenants (current month)
php artisan kiwire:verify-audits
# Verify a specific month
php artisan kiwire:verify-audits --month=202604
# Verify a specific tenant
php artisan kiwire:verify-audits --tenant=default
# Verify all historical months
php artisan kiwire:verify-audits --all-months
The command outputs a summary: total records checked, number of valid records, and number of mismatches. It exits with code 0 if all records are clean, or a non-zero code if any tampered records are found — making it suitable for use in cron jobs, monitoring scripts, or CI pipelines.
Integrity Dashboard
The Audit Integrity page in the admin panel shows:
- Last Verification Run — timestamp and result of the most recent verification.
- Records Verified — total count of audit records checked.
- Mismatches Detected — number of records that failed checksum validation. A non-zero count indicates potential tampering.
- Verification History — log of past verification runs with results and durations.
Scheduled Verification
Configure automatic verification runs from the Scheduler module. Recommended cadence: nightly for the current month's records, weekly for all historical records. If a verification run detects mismatches, a critical security alert email is sent automatically.
Alert on Mismatch
When the verification command detects a checksum mismatch, it:
- Logs the details to the security log channel.
- Sends a critical security alert email to the configured security alert address.
- Reports exactly which record IDs are affected (timestamp, event type, admin, auditable model).
When Mismatches Occur
Do not modify or delete the tampered records. Preserve them exactly as-is for forensic investigation. Modifying records to "fix" a mismatch destroys the evidence.
Steps to follow on detection:
- Immediately notify your security team and document the mismatch report.
- Identify when the tampering occurred by comparing backup snapshots against the current database.
- Determine the scope: which records are affected, which admin account was the actor, what data was changed.
- Investigate the root cause — direct database access, a compromised admin account, or an application vulnerability.
- File an incident report as required by your information security policy.
Coverage
Checksum validation covers all audit records in:
- All audit records in every tenant's audit log
- All audit records in the system-level audit log (superuser actions)
Records created before the checksum feature was enabled will have no checksum and are skipped during verification.
The checksum covers the record as written, not the raw HTTP request. Normal application-level writes through Eloquent will always produce valid checksums. Only out-of-band database modifications (direct SQL, restored backups, bulk updates) will cause mismatches.
Required Permissions
view-audit-integrity