Skip to content

Enforce ProcessContainer ingress policy - #1080

Open
Branden Bonaby (bbonaby) wants to merge 1 commit into
mainfrom
user/bbonaby/process-container-ingress-runtime
Open

Enforce ProcessContainer ingress policy#1080
Branden Bonaby (bbonaby) wants to merge 1 commit into
mainfrom
user/bbonaby/process-container-ingress-runtime

Conversation

@bbonaby

@bbonaby Branden Bonaby (bbonaby) commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

📖 Description

Adds OS capability detection for the Process Security Environment (PSEC) ingress contract and enforces ProcessContainer directional ingress when the host advertises support. PSEC 1.1 serializes ingress.default and ingress.hostLoopback directly; older hosts retain the compatible PSEC 1.0 or legacy SBOX capability behavior.

Capability-query failures remain retryable backend_unavailable errors. If the query succeeds but reports that network-ingress policy is unsupported, a request for hostLoopback: allow is rejected as unsupported policy.

🔗 References

🔍 Validation

  • cargo fmt --manifest-path src\Cargo.toml --all -- --check
  • cargo test --manifest-path src\Cargo.toml -p learning_mode_windows secenv::tests
  • cargo test --manifest-path src\Cargo.toml -p appcontainer_common base_container_helpers::tests
  • cargo test --manifest-path src\Cargo.toml -p appcontainer_common base_container_runner::tests
  • cargo test --manifest-path src\Cargo.toml -p appcontainer_common
  • cargo test --manifest-path src\Cargo.toml -p mxc_engine
  • cargo clippy --manifest-path src\Cargo.toml -p appcontainer_common --all-targets -- -D warnings

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Native Windows policy enforcement and downlevel fallback behavior require final host-level verification.

Review tier: Balanced
Findings: None

What changed in this PR

Adds native ProcessContainer ingress-policy enforcement through the PSEC 1.1 contract while retaining PSEC 1.0 and legacy fallback behavior.

Changes:

  • Exposes and negotiates PSEC ingress capabilities.
  • Encodes native ingress policy and updates capability lowering.
  • Integrates selection, validation, Learning Mode, and regression tests.
File Description
src/​backends/​learning_mode/​windows/​src/​secenv.rs Adds cached PSEC capability reporting.
src/​backends/​learning_mode/​windows/​src/​lib.rs Exports the support type.
src/​backends/​appcontainer/​common/​src/​test_env.rs Centralizes a test capability override.
src/​backends/​appcontainer/​common/​src/​base_container_runner.rs Integrates ingress-aware selection and validation.
src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs Builds versioned PSEC ingress policies and compatibility fallbacks.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI review requested due to automatic review settings September 2, 2026 00:04

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Security-sensitive Windows policy negotiation and fallback behavior requires final human and supported-host validation.

Review tier: Balanced
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 00:08

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Native ingress enforcement needs backend-level tests that verify the security boundary on Windows.

Review tier: Balanced
Findings: None

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/backends/appcontainer/common/src/base_container_helpers.rs:350

  • The new tests only inspect the serialized FlatBuffer, so they cannot catch an incorrect support flag/table mapping or verify that Windows actually blocks and permits inbound connections. Existing ProcessContainer network coverage only exercises egress defaults (tests/scripts/run_base_container_network_tests.ps1:33-45) and raw-socket denial (tests/scripts/WinProcessContainer-Tests.ps1:891-926). Please add Windows backend coverage with real listener/client checks for both ingress defaults, host-loopback allow/deny, and the downlevel fallback before relying on this as a security boundary.

Copilot AI review requested due to automatic review settings September 2, 2026 00:13

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Native ingress enforcement needs a support-gated runtime regression test beyond FlatBuffer serialization coverage.

Review tier: Balanced
Findings: None

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/backends/appcontainer/common/src/base_container_helpers.rs:350

  • Add a support-gated runtime regression for native ingress. The new tests only inspect the FlatBuffer; the existing BaseContainer network script exercises egress only, so an OS-contract mismatch could leave inbound traffic unenforced while all current tests pass. Cover both ingress.default and hostLoopback allow/deny behavior with an external listener.

Copilot AI review requested due to automatic review settings September 2, 2026 00:18

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Native OS-dependent network isolation changes require final human validation on supported Windows builds.

Review tier: Balanced
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 00:22

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Security-sensitive Windows network enforcement depends on host-specific PSEC behavior that requires final human validation.

Review tier: Balanced
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 00:25

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Security-sensitive behavior depends on host-specific Windows PSEC support that requires final human and platform validation.

Review tier: Balanced
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 03:55

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Native security enforcement and platform-dependent fallback behavior require final human validation on supported Windows builds.

Review tier: Balanced
Findings: None

Copilot AI review requested due to automatic review settings September 2, 2026 03:58

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Probe failures are misreported as unsupported policy, and native ingress enforcement lacks adequate regression coverage.

Review tier: Balanced
Findings: 1 Medium severity · 1 Low severity

Pre-existing issues (2)
Severity Finding
Medium severity src/​backends/​appcontainer/​common/​src/​base_container_runner.rsis_ok_and collapses a failing QueryProcessSecurityEnvironmentSupport call into ordinary policy… View comment
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment
Issues resolved since last review (2)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — Add an asymmetric serialization test (for example, default: deny with host_loopback: allow).… View resolved comment
Low severity src/​backends/​appcontainer/​common/​src/​base_container_runner.rs — The module documentation still says this runner prefers PSEC 1.0, but the new implementation emits… View resolved comment
Suppressed comments (4)

Previously missed (1) — in code that hasn't changed since the last review.

src/backends/appcontainer/common/src/base_container_runner.rs:7

  • The module documentation still pins the preferred contract to PSEC 1.0, but this implementation emits PSEC 1.1 when ingress support is negotiated. Remove the fixed version so the documented behavior matches runtime selection.

src/backends/appcontainer/common/src/base_container_helpers.rs:389

  • This security-boundary change is only covered by support-selection and FlatBuffer tests. The existing tests/scripts/run_base_container_network_tests.ps1 checks legacy egress behavior, not whether Windows applies PSEC ingress; add a ProcessContainer E2E that skips when the support bit is absent and verifies allowed/denied inbound and host-loopback connectivity.
    if support.ingress_policy {
        network.ingress = policy.network_ingress.as_ref().map(|ingress_policy| {
            let mut ingress = PsecIngressPolicy::default();
            ingress.default_action = psec_filter_action(ingress_policy.default);
            ingress.host_loopback = psec_filter_action(ingress_policy.host_loopback);
            Box::new(ingress)
        });

src/backends/appcontainer/common/src/base_container_helpers.rs:559

  • Both ingress inputs are Allow, so this test still passes if the two assignments are swapped or one source field is reused for both. Make the case asymmetric and assert distinct decoded values.
        request.policy.network_ingress = Some(NetworkIngressPolicy {
            default: NetworkAction::Deny,
            host_loopback: NetworkAction::Allow,

src/backends/appcontainer/common/src/base_container_runner.rs:413

  • A failed support query is collapsed to ordinary incompatibility here. For hostLoopback: allow, dispatch then selects AppContainer and reports an unsupported policy even though the host capability is unknown because probing failed; propagate this error through selection as BackendUnavailable, reserving rejection for a successful query with the ingress bit clear.
        .is_ok_and(|decision| decision.use_process_security_environment)
}

Copilot AI review requested due to automatic review settings September 2, 2026 07:26

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

A support-query API failure is incorrectly classified as a policy rejection.

Review tier: Balanced
Findings: 1 Medium severity · 1 Low severity

Pre-existing issues (2)
Severity Finding
Medium severity src/​backends/​appcontainer/​common/​src/​base_container_runner.rsis_ok_and collapses a failing QueryProcessSecurityEnvironmentSupport call into ordinary policy… View comment
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment
Suppressed comments (1)

src/backends/appcontainer/common/src/base_container_runner.rs:421

  • A failure from QueryProcessSecurityEnvironmentSupport is an API/host failure, not evidence that the request is invalid. Marking it Rejected causes telemetry to report a policy error, while a successful query with the ingress bit clear is already handled separately as a rejection. Classify this variant as BackendUnavailable as well.
        BaseContainerError::ProcessSecurityEnvironmentSupport(_) => FailurePhase::Rejected,
        BaseContainerError::ProcessSecurityEnvironmentApi(_)
        | BaseContainerError::LearningModeApi(_) => FailurePhase::BackendUnavailable,

@bbonaby
Branden Bonaby (bbonaby) force-pushed the user/bbonaby/process-container-ingress-runtime branch from 3c2a9b8 to da69f0f Compare September 2, 2026 16:04
@bbonaby Branden Bonaby (bbonaby) changed the title Enforce native ProcessContainer ingress policy Enforce ProcessContainer ingress policy Sep 2, 2026
@bbonaby
Branden Bonaby (bbonaby) force-pushed the user/bbonaby/process-container-ingress-runtime branch from da69f0f to 2e52d5e Compare September 2, 2026 16:05
@bbonaby
Branden Bonaby (bbonaby) marked this pull request as ready for review September 2, 2026 16:22
Copilot AI review requested due to automatic review settings September 2, 2026 16:22
@bbonaby
Branden Bonaby (bbonaby) requested a review from a team as a code owner September 2, 2026 16:22
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

An OS capability-query failure is incorrectly exposed as a non-retryable policy validation error.

Review tier: Balanced
Findings: 1 Low severity

Pre-existing issues (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment
Issues resolved since last review (1)
Severity Finding
Medium severity src/​backends/​appcontainer/​common/​src/​base_container_runner.rsis_ok_and collapses a failing QueryProcessSecurityEnvironmentSupport call into ordinary policy… View resolved comment
Suppressed comments (1)

src/backends/appcontainer/common/src/base_container_runner.rs:421

  • ProcessSecurityEnvironmentSupport represents a failed OS capability query, not an unsupported policy, yet this maps it to Rejected. The engine converts that phase to policy_validation and treats it as non-retryable (mxc_engine/src/dispatch.rs:96-100), so a host/API failure is reported as a caller policy error. Keep query failures as BackendUnavailable; a successful query with the ingress bit clear is already handled separately as the actual policy rejection.
        BaseContainerError::ProcessSecurityEnvironmentSupport(_) => FailurePhase::Rejected,
        BaseContainerError::ProcessSecurityEnvironmentApi(_)
        | BaseContainerError::LearningModeApi(_) => FailurePhase::BackendUnavailable,

Copilot AI review requested due to automatic review settings September 3, 2026 22:11
@bbonaby
Branden Bonaby (bbonaby) force-pushed the user/bbonaby/process-container-ingress-runtime branch from 8b91d40 to 58cffac Compare September 3, 2026 22:11

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Core removal of the bidirectional private-network capability lacks an effective regression test.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new removal of privateNetworkClientServer is not exercised in the case where that capability…
Pre-existing issues (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment

Comment thread src/backends/appcontainer/common/src/base_container_helpers.rs
Copilot AI review requested due to automatic review settings September 3, 2026 23:34

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Missing ingress support currently falls through to AppContainer and produces the wrong error classification.

Review tier: Balanced
Findings: 2 Low severity

Pre-existing issues (2)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new removal of privateNetworkClientServer is not exercised in the case where that capability… View comment
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment
Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

src/backends/appcontainer/common/src/base_container_runner.rs:240

  • The ProcessContainer OS-support guide documents the PSEC runtime probe and the existing PSE_SUPPORT_FS_DENY gate (docs/process-container/os-version-support.md:53-114), but it does not document this new ingress capability gate or its downlevel behavior. Update that guide to explain when PSEC 1.1 is used, when PSEC 1.0 capability lowering remains valid, and when hostLoopback: allow is rejected.

src/backends/appcontainer/common/src/base_container_runner.rs:908

  • When the support query succeeds but the ingress bit is clear, use_process_security_environment is false and hostLoopback: allow is also SBOX-incompatible, so this probe returns false. The dispatcher then selects an AppContainer fallback instead of reaching the new FailurePhase::Rejected branch in BaseContainerRunner::validate; streaming callers receive backend_error (and may even hit an unrelated fallback/DACL error) rather than the promised unsupported-policy result. Carry this resolved unsupported state through dispatch as a policy rejection, and cover the full dispatcher path rather than only validating a directly constructed BaseContainer runner.
        if decision.use_process_security_environment {
            return Ok(true);
        }
        if !Self::is_legacy_sbox_compatible_with_request(

Copilot AI review requested due to automatic review settings September 3, 2026 23:51

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The canonical ProcessContainer networking guide still documents the removed legacy host-loopback encoding.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity docs/​process-container/​os-version-support.md — This new PSEC 1.1 behavior leaves the canonical ProcessContainer networking guide contradictory:…
Pre-existing issues (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment
Issues resolved since last review (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new removal of privateNetworkClientServer is not exercised in the case where that capability… View resolved comment

Comment on lines +70 to +71
`PSE_SUPPORT_NETWORK_INGRESS`, MXC emits the PSEC 1.1 contract and serializes
`ingress.default` and `ingress.hostLoopback` directly. Otherwise, requests that

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Repository documentation still describes the removed PSEC 1.0 host-loopback lowering.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 3 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The checked-in ProcessContainer documentation still describes the removed PSEC lowering:…
Pre-existing issues (2)
Severity Finding
Low severity docs/​process-container/​os-version-support.md — This new PSEC 1.1 behavior leaves the canonical ProcessContainer networking guide contradictory:… View comment
Low severity src/​backends/​appcontainer/​common/​src/​base_container_helpers.rs — The new enforcement path is covered only by support-selection and FlatBuffer serialization tests;… View comment

Comment thread src/backends/appcontainer/common/src/base_container_helpers.rs
const SECURITY_ENVIRONMENT_API_SET_NAME: &str = "api-win-appmodel-processmodel~securityenvironment";
const SECURITY_ENVIRONMENT_API_SET: &core::ffi::CStr =
c"api-win-appmodel-processmodel~securityenvironment";
const PSE_SUPPORT_FS_DENY: u64 = 0x0000_0000_0000_0001;

@bbonaby Branden Bonaby (bbonaby) Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We'll need to revisit how we can refactor this whole file out of the learning mode module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for sure.

@jsidewhite

Copy link
Copy Markdown
Member
    validate_network_policy_support(request, self.network_policy_support())?;

Isn't this (or rather network_policy_support above) supposed to be the place that determines if this backend supports host loopback?

Why reimplement another custom thing?


Refers to: src/backends/appcontainer/common/src/base_container_runner.rs:2092 in 84da496. [](commit_id = 84da496, deletion_comment = False)

return Ok(());
}
let use_process_security_environment = self.uses_process_security_environment(request);
let process_security_environment_usable = self.is_psec_usable();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is_psec_usable

This actually creates a sandbox, right? (Seems bad)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🕐

Negotiate the Process Security Environment ingress contract from the OS support query, emit PSEC 1.1 only when available, and preserve compatible PSEC 1.0 or SBOX behavior otherwise. Carry failed queries and confirmed unsupported host-loopback policy through dispatch with distinct public error classifications.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3413690e-c10e-4f33-b3c5-0a2715eb1b88
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs-Author-Feedback Issue needs attention from issue or PR author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants