Audit logs are tenant-scoped
Why it matters
Audit logs that are not scoped by tenant become a cross-tenant intelligence source: a tenant admin can query another organization's activity history, exposing who is active, what features they use, and what actions their users take. CWE-285 and NIST AU-9 both address this; SOC 2 CC7.2 requires that audit records be protected from unauthorized access. Beyond privacy, unscoped audit logs mean a legitimate tenant admin cannot be confident that the logs they see reflect only their organization's actions.
Severity rationale
Low because exploiting unscoped audit logs requires tenant-admin privileges, limiting the attacker surface, but exposure of another tenant's activity trail is a direct SOC 2 CC7.2 control failure.
Remediation
Add organizationId as a required field on every audit log write and as a mandatory filter on every read:
// Write — include tenant context on every event
await db.auditLog.create({
data: {
organizationId: session.user.organizationId,
userId: session.user.id,
action: 'document.deleted',
resourceId: docId,
createdAt: new Date()
}
})
// Read — always scope to the requesting tenant
const logs = await db.auditLog.findMany({
where: { organizationId: session.user.organizationId },
orderBy: { createdAt: 'desc' },
take: 100
})
If the audit log table was created without an organizationId column, add it via migration and backfill from the related resource's organizationId before removing the global-read path.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Multi-Tenancy Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-285 — Improper Authorization
- nist:rev5 · AU-9 — Protection of Audit Information
- soc2:2017 · CC7.2 — Monitors System Components
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-multi-tenancy·automated