-
Notifications
You must be signed in to change notification settings - Fork 185
[bug] policy inheritance: child without unmanaged_files block silently downgrades parent's action: deny #1198
Copy link
Copy link
Labels
area/audit-policyapm-policy.yml schema, custom_checks, install-time enforcement.apm-policy.yml schema, custom_checks, install-time enforcement.area/content-securityUnicode scanning, Glassworm, apm audit content checks, SARIF output.Unicode scanning, Glassworm, apm audit content checks, SARIF output.priority/highShips in current or next milestoneShips in current or next milestonestatus/acceptedDirection approved, safe to start work.Direction approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).Initial agentic triage complete; pending maintainer ratification (silence = approval).theme/governanceGoverned by policy. apm-policy, audit, enforcement, enterprise rollout.Governed by policy. apm-policy, audit, enforcement, enterprise rollout.type/bugSomething does not work as documented.Something does not work as documented.
Metadata
Metadata
Assignees
Labels
area/audit-policyapm-policy.yml schema, custom_checks, install-time enforcement.apm-policy.yml schema, custom_checks, install-time enforcement.area/content-securityUnicode scanning, Glassworm, apm audit content checks, SARIF output.Unicode scanning, Glassworm, apm audit content checks, SARIF output.priority/highShips in current or next milestoneShips in current or next milestonestatus/acceptedDirection approved, safe to start work.Direction approved, safe to start work.status/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).Initial agentic triage complete; pending maintainer ratification (silence = approval).theme/governanceGoverned by policy. apm-policy, audit, enforcement, enterprise rollout.Governed by policy. apm-policy, audit, enforcement, enterprise rollout.type/bugSomething does not work as documented.Something does not work as documented.
Type
Fields
Give feedbackNo fields configured for issues without a type.
Projects
Status
Done
Summary
When a child policy declares
extends: orgbut does NOT redeclare anunmanaged_files:block, the merged policy'sunmanaged_files.actionis silently downgraded to the model's default (ignore) instead of inheriting the parent'sdeny.The
_escalate(_UNMANAGED_ACTION_LEVELS, parent.action, child.action)call atsrc/apm_cli/policy/inheritance.py:198correctly takes the max, but thechild.unmanaged_filesfor a child that omits the block is not "no opinion" — it'sUnmanagedFilesPolicy(action='ignore', directories=()). Somax('deny', 'ignore') == 'deny'should hold but the resulting merged check reports as disabled.Repro
org/.github/apm-policy.yml:repo/apm-policy.yml:Add an unmanaged file (e.g.
.github/hooks/sneaky.hook.md) and run:Expected:
unmanaged-filescheck fails with actiondenyinherited from org.Actual:
[+] unmanaged-files | Unmanaged files check disabled (action: ignore)and the audit passes.Workaround
Redeclare the
unmanaged_filesblock in every override that should preserve the parent's posture:This loses the value proposition of
extends:(single source of truth at the org root) — the override has to mirror the parent's directory list verbatim, which is exactly what the inheritance feature is supposed to avoid.Suggested fix
Two routes:
UnmanagedFilesPolicydistinguish "default" from "explicitly set". A child that did NOT declareunmanaged_files:should be treated as transparent in_merge_unmanaged_files, returningparentunchanged. (Mirrors how_intersect_allowtreatsNoneas "no opinion".)The first is cleaner because it matches the rest of the inheritance.py contract.
Affected versions
Reproduced with
apmv0.x (current main). Same logic atsrc/apm_cli/policy/inheritance.py:194-200.Impact
Org-wide governance posture silently weakens whenever a team adds a repo override for an unrelated policy area (e.g. extra dependency deny patterns). Hard to detect —
apm audit --policy orgshows the right floor, butapm audit --policy ./apm-policy.yml(which the consumer typically runs in CI for layered enforcement) silently ignores the floor forunmanaged_files.