fix(security): harden image context and runtime receipts
This commit is contained in:
@@ -20,6 +20,7 @@ POLICY = "global_product_governance_v2_security_review_v1"
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ASSET_INVENTORY_PATH = Path("governance/ewoooc_asset_inventory.json")
|
||||
QUALITY_BASELINE_PATH = Path("governance/security_governance_review_baseline.json")
|
||||
SOURCE_RECEIPT_PATH = Path("governance/security_governance_source_receipt.json")
|
||||
|
||||
MUTATING_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
|
||||
AUTH_DECORATOR_MARKERS = (
|
||||
@@ -58,6 +59,19 @@ ASSET_REQUIRED_FIELDS = {
|
||||
"backup_restore",
|
||||
"learning_targets",
|
||||
}
|
||||
DOCKERIGNORE_REQUIRED_PATTERNS = {
|
||||
".git",
|
||||
".gitea",
|
||||
".env",
|
||||
".env.*",
|
||||
"data",
|
||||
"logs",
|
||||
"backups",
|
||||
"config/google_credentials.json",
|
||||
"config/google_token.json",
|
||||
"config/google_token.pickle",
|
||||
"config/*.json",
|
||||
}
|
||||
|
||||
|
||||
def _read(path: Path) -> str:
|
||||
@@ -250,6 +264,53 @@ def _quality_baseline(root: Path) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _source_receipt(root: Path) -> dict[str, Any]:
|
||||
path = root / SOURCE_RECEIPT_PATH
|
||||
try:
|
||||
payload = json.loads(_read(path))
|
||||
except (TypeError, json.JSONDecodeError):
|
||||
payload = {}
|
||||
checks = payload.get("checks") if isinstance(payload, dict) else []
|
||||
checks_by_id = {
|
||||
item.get("id"): item
|
||||
for item in checks
|
||||
if isinstance(item, dict) and item.get("id")
|
||||
} if isinstance(checks, list) else {}
|
||||
source_commit = str(payload.get("source_commit") or "") if isinstance(payload, dict) else ""
|
||||
commit_shape_valid = len(source_commit) == 40 and all(
|
||||
char in "0123456789abcdefABCDEF" for char in source_commit
|
||||
)
|
||||
return {
|
||||
"path": SOURCE_RECEIPT_PATH.as_posix(),
|
||||
"available": bool(payload) and payload.get("receipt_kind") == "security_governance_source_receipt",
|
||||
"source_commit": source_commit,
|
||||
"source_commit_shape_valid": commit_shape_valid,
|
||||
"generated_at": payload.get("generated_at") if isinstance(payload, dict) else None,
|
||||
"release_gate_status": (
|
||||
(payload.get("release_gate") or {}).get("status")
|
||||
if isinstance(payload, dict) else None
|
||||
),
|
||||
"_checks": checks_by_id,
|
||||
}
|
||||
|
||||
|
||||
def _docker_build_context_posture(root: Path) -> dict[str, Any]:
|
||||
path = root / ".dockerignore"
|
||||
patterns = {
|
||||
line.strip().rstrip("/")
|
||||
for line in _read(path).splitlines()
|
||||
if line.strip() and not line.lstrip().startswith("#")
|
||||
}
|
||||
missing = sorted(DOCKERIGNORE_REQUIRED_PATTERNS - patterns)
|
||||
return {
|
||||
"path": ".dockerignore",
|
||||
"exists": path.is_file(),
|
||||
"required_pattern_count": len(DOCKERIGNORE_REQUIRED_PATTERNS),
|
||||
"missing_patterns": missing,
|
||||
"safe": path.is_file() and not missing,
|
||||
}
|
||||
|
||||
|
||||
def _workflow_supply_chain(root: Path) -> dict[str, Any]:
|
||||
files = sorted((root / ".gitea" / "workflows").glob("*.y*ml"))
|
||||
forbidden: list[dict[str, Any]] = []
|
||||
@@ -395,7 +456,25 @@ def build_security_governance_review(
|
||||
route_posture["unclassified_unguarded"] = route_posture["unclassified_unguarded"][:detail_limit]
|
||||
route_posture["mutating_unguarded"] = route_posture["mutating_unguarded"][:detail_limit]
|
||||
assets = _asset_inventory(scan_root)
|
||||
source_receipt = _source_receipt(scan_root)
|
||||
supply_chain = _workflow_supply_chain(scan_root)
|
||||
docker_context = _docker_build_context_posture(scan_root)
|
||||
supply_chain["docker_build_context"] = docker_context
|
||||
supply_chain["source_chain_ready"] = bool(
|
||||
supply_chain["gitea_only"] and docker_context["safe"]
|
||||
)
|
||||
receipt_supply = source_receipt["_checks"].get("GV.SC-gitea-only-supply-chain", {})
|
||||
if (
|
||||
supply_chain["workflow_count"] == 0
|
||||
and source_receipt["available"]
|
||||
and source_receipt["source_commit_shape_valid"]
|
||||
and receipt_supply.get("status") == "pass"
|
||||
):
|
||||
receipt_evidence = receipt_supply.get("evidence") or {}
|
||||
supply_chain = dict(receipt_evidence) if isinstance(receipt_evidence, dict) else {}
|
||||
supply_chain["evidence_source"] = "cd_source_receipt"
|
||||
supply_chain["source_commit"] = source_receipt["source_commit"]
|
||||
supply_chain["source_chain_ready"] = True
|
||||
dependencies = _dependency_posture(scan_root)
|
||||
quality = _quality_baseline(scan_root)
|
||||
large_files = _large_python_files(scan_root)
|
||||
@@ -447,6 +526,24 @@ def build_security_governance_review(
|
||||
)
|
||||
if marker in constitution
|
||||
]
|
||||
policy_alignment_ready = bool(constitution) and not policy_drift_markers
|
||||
policy_evidence = {
|
||||
"legacy_markers": policy_drift_markers,
|
||||
"evidence_source": "source_file" if constitution else "missing",
|
||||
}
|
||||
receipt_policy = source_receipt["_checks"].get("GV.PO-policy-alignment", {})
|
||||
if (
|
||||
not constitution
|
||||
and source_receipt["available"]
|
||||
and source_receipt["source_commit_shape_valid"]
|
||||
and receipt_policy.get("status") == "pass"
|
||||
):
|
||||
policy_alignment_ready = True
|
||||
policy_evidence = {
|
||||
"legacy_markers": [],
|
||||
"evidence_source": "cd_source_receipt",
|
||||
"source_commit": source_receipt["source_commit"],
|
||||
}
|
||||
|
||||
access_contract_ready = bool(
|
||||
central_policy_registered
|
||||
@@ -498,12 +595,12 @@ def build_security_governance_review(
|
||||
_check(
|
||||
"GV.SC-gitea-only-supply-chain",
|
||||
"GOVERN/PROTECT",
|
||||
"pass" if supply_chain["gitea_only"] else "fail",
|
||||
"pass" if supply_chain["source_chain_ready"] else "fail",
|
||||
"critical",
|
||||
"Gitea workflows have no external action or forbidden GitHub source reference." if supply_chain["gitea_only"] else "Workflow still depends on an external action/source.",
|
||||
"Gitea workflow and Docker build context exclude external actions, forbidden sources, secrets and runtime data." if supply_chain["source_chain_ready"] else "Source workflow or Docker build context boundary is incomplete.",
|
||||
supply_chain,
|
||||
"replace_external_action_resolution_with_gitea_job_token_checkout",
|
||||
release_blocking=not supply_chain["gitea_only"],
|
||||
"keep_gitea_checkout_and_generate_commit_bound_source_receipt",
|
||||
release_blocking=not supply_chain["source_chain_ready"],
|
||||
),
|
||||
_check(
|
||||
"ID.RA-dependency-vulnerability-management",
|
||||
@@ -544,12 +641,12 @@ def build_security_governance_review(
|
||||
_check(
|
||||
"GV.PO-policy-alignment",
|
||||
"GOVERN",
|
||||
"pass" if not policy_drift_markers else "fail",
|
||||
"pass" if policy_alignment_ready else "fail",
|
||||
"high",
|
||||
"Constitution is aligned to current production/governance doctrine." if not policy_drift_markers else "Legacy security/deployment doctrine still conflicts with production truth.",
|
||||
{"legacy_markers": policy_drift_markers},
|
||||
"Constitution is aligned to current production/governance doctrine." if policy_alignment_ready else "Policy source is missing or legacy doctrine still conflicts with production truth.",
|
||||
policy_evidence,
|
||||
"sunset_legacy_rules_with_owner_expiry_replacement_and_verifier",
|
||||
release_blocking=bool(policy_drift_markers),
|
||||
release_blocking=not policy_alignment_ready,
|
||||
),
|
||||
_check(
|
||||
"GV.OV-modularization",
|
||||
@@ -645,6 +742,9 @@ def build_security_governance_review(
|
||||
},
|
||||
"checks": checks,
|
||||
"quality_baseline": quality,
|
||||
"source_receipt": {
|
||||
key: value for key, value in source_receipt.items() if key != "_checks"
|
||||
},
|
||||
"release_gate": {
|
||||
"status": "pass" if not blocking else "fail",
|
||||
"blocking_failure_count": len(blocking),
|
||||
|
||||
Reference in New Issue
Block a user