fix(security): reject unsupported policy fields - #313
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Cannot close or merge this PR, and I am not going to force the compatibility cutover through.
This is an explicit public/runtime break of the security-policy contract. On current main, SecurityPolicy accepts unknown TOML and JSON keys and ignores them. After this change, #[serde(deny_unknown_fields)] turns those same files and elevation payloads into PolicyError::Parse. The PR body already names that as an intentional compatibility change: existing policy files with unsupported keys stop loading.
That includes keys the documented examples previously advertised (max_cve_severity, require_sbom, verify_slsa, trusted_maintainers). Install, update, audit, and privilege-handoff all deserialize this type (load / load_optional / load_default / inherit_policy). A previously valid ~/.config/omg/policy.toml that copied those examples would start failing closed.
In-tree proof the old shape still exists: tests/common/fixtures.rs ENTERPRISE_POLICY still carries require_sbom, require_slsa, and max_cve_age_days, and tests/security_tests.rs parses that fixture through the real SecurityPolicy deserializer. The lib-only tests on this branch do not cover that path.
No merge conflict against main (06941cf9): merge-tree is clean, 0 behind / 1 ahead. There is no leftover non-breaking hole I can land independently of this fail-closed schema change. Author-scoped leftovers (changelog, updating the enterprise fixture, the still-present minimum_grade = "Locked" example) are not a reason to force the break.
I cannot close or merge from this run.
Sent by Cursor Automation: Untitled
| } | ||
|
|
||
| #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] | ||
| #[serde(deny_unknown_fields)] |
There was a problem hiding this comment.
This attribute is the public contract break. File load and elevation JSON both deserialize SecurityPolicy. Keys that currently load and are ignored become parse errors. I will not land or rewrite this to force that cutover; it needs an explicit compatibility decision, not an automation merge.


Audit K1: unsupported security settings must fail explicitly
Citations
Change
Use serde deny_unknown_fields on the policy type, covering file and elevation JSON boundaries. Unknown options return a parse error, not permissive defaults. Preserve supported fields, defaults, serialization and original file contents. Remove misleading advanced examples and correct Locked-grade claims in configuration docs.
Verification
Intentional compatibility change: existing policy files containing unsupported keys now fail with the parser identifying the key. No file is rewritten, discarded or migrated silently. Documented remediation requires reviewing requirements before removing unsupported keys; those keys never enabled protection. No live installation/elevation or full platform matrix run. Static slop tooling abstained on the external Rust worktree; manual review and executed tests back this change.