Skip to content

fix(policy): reject unknown endpoint security modes - #3187

Open
2000krysztof wants to merge 2 commits into
NVIDIA:mainfrom
2000krysztof:fix/fail-closed-policy-enums
Open

fix(policy): reject unknown endpoint security modes#3187
2000krysztof wants to merge 2 commits into
NVIDIA:mainfrom
2000krysztof:fix/fail-closed-policy-enums

Conversation

@2000krysztof

@2000krysztof 2000krysztof commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Make security-sensitive network policy values fail closed across all policy ingress paths. Replace the public TLS, enforcement, and access strings with typed protobuf enums so invalid values cannot silently weaken enforcement.

Related Issue

Closes #3046

Changes

  • Added shared validation for endpoint TLS, enforcement, and access values.
  • Rejects unknown values with actionable, field-level errors.
  • Applies validation across sandbox policies, policy updates, provider profiles, and merge operations.
  • Prevents malformed enforcement values such as enforc from falling back to audit mode.
  • Added defensive runtime rejection for invalid endpoint modes.
  • Returns gRPC INVALID_ARGUMENT before invalid policies are persisted or activated.
  • Replaced public protobuf strings for TLS, enforcement, and access with typed enums.
  • Updated generated Go bindings and SDK conversions to use the new enum types.
  • Preserved the documented YAML spellings for compatibility.
  • Added regression coverage across policy, provider-profile, gateway, SDK, and runtime paths.
  • Documented accepted values and fail-closed behavior.

Testing

  • mise run pre-commit passes
  • mise run test passes
  • Unit tests added/updated
  • E2E tests added/updated (not applicable)
  • Manually verified sandbox creation and live policy updates using the Podman gateway
  • Confirmed malformed TLS, enforcement, and access values are rejected
  • Confirmed rejected updates do not alter the active policy

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@copy-pr-bot

copy-pr-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@johntmyers
johntmyers marked this pull request as draft September 4, 2026 18:41
@2000krysztof
2000krysztof marked this pull request as ready for review September 7, 2026 11:03
Closes NVIDIA#3046

Validate TLS, enforcement, and access values across policy and provider profile ingress, and prevent runtime parsing from falling back to audit for unknown enforcement values.

Signed-off-by: Krzysztof Malczuk <kmalczuk@redhat.com>
@2000krysztof
2000krysztof force-pushed the fix/fail-closed-policy-enums branch from 267b665 to c1c3bdd Compare September 7, 2026 11:43

@gmenher gmenher left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this!! @2000krysztof , the centralization in l7_validate.rs is a clean design and the test coverage there is thorough.

One question: I noticed that sandbox policies are persisted as binary protobuf blobs (encode_to_vec / decode in policy_store.rs). Changing NetworkEndpoint.tls, .enforcement, and .access from string (wire type 2) to enum (wire type 0) means that existing stored blobs with non-empty values for those fields will have those fields silently dropped to 0 (Unspecified) when decoded by the new code, since prost skips fields with a wire type mismatch rather than erroring.

The most sensitive case seems to be tls: skip, which would silently become tls: Unspecified (auto-detect) on upgrade. How is this currently handled for existing deployments?

Comment thread proto/sandbox.proto
}
}

pub fn network_access_preset_from_str(value: &str) -> Option<NetworkAccessPreset> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the proto fields now typed as enums on the wire, I'm curious whether these string-to-enum conversion functions are still needed for an active code path, for example YAML/Helm config that arrives as strings before being mapped to proto, or whether they're now primarily used for legacy input validation. Just trying to understand if there's an external config surface that still uses the string form.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these are still used by active input paths rather than only for legacy validation. The protobuf/gRPC representation is now typed, but policy YAML, provider-profile YAML, CLI policy-update arguments, and proposal JSON retain their documented lowercase string spellings. These helpers centralize conversion from those authored forms into the protobuf enums. The corresponding to_str helpers are also used when serializing policies and producing runtime/UI representations.

@2000krysztof

Copy link
Copy Markdown
Contributor Author

Great work on this!! @2000krysztof , the centralization in l7_validate.rs is a clean design and the test coverage there is thorough.

One question: I noticed that sandbox policies are persisted as binary protobuf blobs (encode_to_vec / decode in policy_store.rs). Changing NetworkEndpoint.tls, .enforcement, and .access from string (wire type 2) to enum (wire type 0) means that existing stored blobs with non-empty values for those fields will have those fields silently dropped to 0 (Unspecified) when decoded by the new code, since prost skips fields with a wire type mismatch rather than erroring.

The most sensitive case seems to be tls: skip, which would silently become tls: Unspecified (auto-detect) on upgrade. How is this currently handled for existing deployments?

Good catch I hadn’t called out the persisted wire-format impact. One relevant detail is that this is pre-0.1 work intended to stabilize the contract for the first release, so my assumption was that compatibility with existing development databases isn’t guaranteed. I also checked Prost’s behavior: it returns UnexpectedWireType here rather than silently defaulting the field, so it would fail closed instead of weakening the policy.

If we do want to support upgrades from current development deployments, I’m happy to add a migration path. I’m just not sure the additional legacy support is worthwhile before 0.1. What do you think?

Replace the public TLS, enforcement, and access strings with protobuf enums and carry the typed values through policy composition, provider profiles, drivers, and runtime conversion.

Preserve the documented YAML spellings, reject unknown and invalid numeric enum values consistently, and update generated Go bindings, SDK conversions, tests, and policy documentation.

Signed-off-by: Krzysztof Malczuk <kmalczuk@redhat.com>
@2000krysztof
2000krysztof force-pushed the fix/fail-closed-policy-enums branch from c1c3bdd to 4d2a055 Compare September 9, 2026 17:59

@johntmyers johntmyers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

PR Review Status

Thanks @2000krysztof. I checked your explanation of the persisted protobuf wire-format concern: Prost does fail closed with UnexpectedWireType, but that still makes existing non-empty policy records unreadable after an in-place gateway upgrade. One blocking compatibility finding remains.

Action required: preserve readable upgrades for persisted policies, or obtain an explicit maintainer waiver of that compatibility requirement.

Blocking findings:

  • GATOR-4d2a055a-01: changing established protobuf tags from strings to enums causes existing policy blobs to fail decoding after upgrade.

Carried findings:

  • None
Gator metadata
  • Validation: Implements the fail-closed security-policy contract in linked issue #3046.
  • Docs: Fern policy-schema and provider-profile docs are updated.
  • Checks: DCO is green; Branch Checks and Helm Lint are pending on the current head.
  • E2E: test:e2e is required for policy-enforcement behavior and will be dispatched after blocking review feedback is resolved or waived.
  • Head SHA: 4d2a055ad370c710b0e857a069b369c5d4bf1a54
  • Base SHA: 8af79a7f4b68abf09299371f20987fde90667139
  • Merge base SHA: 320d4ef79dd572c642133f175f12bafc20d89fd9
  • Patch ID: d0b11f729c98eb3e534292f5774206b0e9686e32
  • Gator payload: 8
  • Review mode: initial
  • Previous reviewed SHA: none
  • Review budget exhausted: no
  • Maintainer decision required: no
  • Next state: gator:in-review

Comment thread proto/sandbox.proto
string enforcement = 5;
// Access preset shorthand: "read-only", "read-write", "full".
// TLS handling. Unspecified enables automatic detection and termination.
NetworkTlsMode tls = 4;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

Warning — GATOR-4d2a055a-01 · Existing policy blobs become unreadable

Summary: An operator upgrading a gateway with persisted endpoints containing TLS, enforcement, or access values will hit UnexpectedWireType when the new schema decodes those records. This fails closed, but policy reads, reloads, and updates can fail until the database is repaired or the gateway is rolled back.

Fix: Keep tags 4–6 as strings with strict allowlist validation, or add typed fields on new tags with transitional dual-read/write behavior and a migration before retiring the string fields.

Verify: Encode a policy with non-empty values using the base schema, load it from SQLite with the head gateway, and confirm GetSandboxConfig succeeds with equivalent values.

Agent context
  • Location: proto/sandbox.proto:150
  • Ownership: This PR changes established length-delimited fields to varint enums without a compatibility decoder or migration.
  • Related sinks: persisted policy decode in policy_store.rs and global-policy decode in grpc/policy.rs.

@johntmyers johntmyers added the gator:in-review Gator is reviewing or awaiting PR review feedback label Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gator:in-review Gator is reviewing or awaiting PR review feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(policy)!: make security-sensitive policy values fail closed

3 participants