Build authorization-gated tenancy evidence harness
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0260c-4067-7052-9647-ad000d576e38
This commit is contained in:
parent
2c8e1d41ad
commit
beab2a04d1
32 changed files with 1816 additions and 11 deletions
61
src/whitehat_security/e3.py
Normal file
61
src/whitehat_security/e3.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Literal
|
||||
|
||||
from .model import Outcome
|
||||
|
||||
Expectation = Literal["zero_rows", "statement_rejected", "false", "documented_limit"]
|
||||
Query = Callable[[str], object]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class E3Probe:
|
||||
probe_id: str
|
||||
sql_key: str
|
||||
expectation: Expectation
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class E3Result:
|
||||
probe_id: str
|
||||
outcome: Outcome
|
||||
reason: str
|
||||
|
||||
|
||||
PROBES = (
|
||||
E3Probe("conformance-view-empty", "conformance", "zero_rows"),
|
||||
E3Probe("unset-guc-reads-none", "unset_guc", "zero_rows"),
|
||||
E3Probe("tenant-a-cannot-read-b", "wrong_tenant_read", "zero_rows"),
|
||||
E3Probe("tenant-a-cannot-insert-b", "wrong_tenant_insert", "statement_rejected"),
|
||||
E3Probe("runtime-lacks-bypassrls", "runtime_bypassrls", "false"),
|
||||
E3Probe("unsafe-definer-inventory-empty", "unsafe_definer", "zero_rows"),
|
||||
E3Probe("sql-compromise-reset", "reset_to_b", "documented_limit"),
|
||||
)
|
||||
|
||||
|
||||
def evaluate(probe: E3Probe, *, rows: int = 0, rejected: bool = False,
|
||||
boolean: bool | None = None) -> E3Result:
|
||||
if probe.expectation == "documented_limit":
|
||||
return E3Result(probe.probe_id, "inconclusive",
|
||||
"E3-B observation records the documented SQL-compromise limit")
|
||||
passed = {
|
||||
"zero_rows": rows == 0,
|
||||
"statement_rejected": rejected,
|
||||
"false": boolean is False,
|
||||
}[probe.expectation]
|
||||
if passed:
|
||||
return E3Result(probe.probe_id, "pass", f"expectation met: {probe.expectation}")
|
||||
return E3Result(probe.probe_id, "finding", f"expectation failed: {probe.expectation}")
|
||||
|
||||
|
||||
CADENCE = {
|
||||
"interval": "24h",
|
||||
"maximum_detection_window": "24h plus run and reporting latency",
|
||||
"reset_triggers": [
|
||||
"schema migration", "role or grant change", "RLS policy change",
|
||||
"security-definer function change", "posture mechanism change",
|
||||
],
|
||||
"triggered_run_deadline": "before deployment promotion",
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue