Skip to content

Add processContainer.captureDenials config for Windows denial capture#663

Open
richiemsft wants to merge 4 commits into
mainfrom
user/saulg/capture-denials-config
Open

Add processContainer.captureDenials config for Windows denial capture#663
richiemsft wants to merge 4 commits into
mainfrom
user/saulg/capture-denials-config

Conversation

@richiemsft

@richiemsft richiemsft commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a captureDenials object under processContainer that will enable the
Windows learning-mode trace. This is the config-contract half of the
learning-mode denial-capture feature — pure plumbing, no runtime behavior yet.

ShapeprocessContainer.captureDenials: { mode?: "block-and-log" | "allow-and-log", outputPath?: string }:

  • Presence of the object enables capture.
  • mode (optional) selects how each ungranted access check is handled while it
    is recorded. Both modes log every access the policy does not grant; the mode
    only decides whether that access is blocked or allowed:
    • block-and-log (default) — the access stays denied and the denial
      is recorded. Deny-by-default containment is preserved; the safe default.
    • allow-and-log — the access is allowed and recorded (audit mode). This
      relaxes deny-by-default for the run, so it is security-sensitive and the
      runner emits a security warning.
    • Omitting mode defaults to block-and-log. An unknown value is rejected at
      parse time with an error naming both valid modes.
  • outputPath (optional) names where the ETL trace is sealed. The OS model is
    caller-controlled (StopLearningModeTrace(trace, lpOutputPath)), so the
    caller names the path; it is opened under the caller''s own identity. When
    omitted, the runner will fall back to a managed per-run temp file.
  • The path is validated at parse time (must be absolute with an existing parent
    directory) with actionable errors.

What''s in scope (this PR):

  • Wire model (wire::CaptureDenials + wire::CaptureDenialsMode on wire::ProcessContainer).
  • Domain model (CaptureDenialsConfig + CaptureDenialsMode on ContainerPolicy.capture_denials).
  • Parser mapping + validation in config_parser.rs.
  • Regenerated dev schema (schemas/dev/mxc-config.schema.0.8.0-dev.json) and SDK
    wire types (sdk/node/src/generated/wire.ts) via mxc_schema_gen (codegen —
    not hand-edited).
  • Docs (docs/schema.md) + example (tests/examples/29_capture_denials.json).
  • Unit tests (parse/validate/mode) + all schema/version/codegen gates green.

What''s intentionally NOT here (follow-up integration PR):

  • Auto-injection of the learningModeLogging capability when captureDenials
    is set — that reuses the capability recognition from the capabilities PR.
  • The runner trace lifecycle (Start -> run -> Stop -> write ETL) and the
    block-vs-allow enforcement behind each mode — that consumes the
    learning-mode OS API.

Both land in the integration PR stacked on top of the capabilities + consume-API
PRs plus this one.

Related Issues

Validation

  • cargo test -p wxc_common — 466 pass (9 captureDenials tests, incl. 4 mode tests)
  • cargo fmt --all -- --check, cargo clippy -p wxc_common --all-targets -- -D warnings
  • cargo check --workspace --all-targets
  • npm run test:unit (SDK) — 201 pass
  • node scripts/versioning/{validate-configs,check-schema-codegen,check-sdk-types-codegen,check-schema-versions}.js
Microsoft Reviewers: Open in CodeFlow

Introduce a captureDenials object under processContainer that enables the

Windows deny-and-record learning-mode trace. Presence enables capture; an

optional outputPath names where the ETL trace is sealed (validated absolute

with an existing parent), otherwise the runner falls back to a managed

per-run temp file. Config plumbing only: wire model, ContainerPolicy, parser

validation, regenerated dev schema + SDK wire types, docs, and an example.

Capability auto-injection and the runner trace wiring land in the follow-up

integration PR (on top of #622 + #661).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 20, 2026 23:11
@azure-pipelines

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

…K conformance oracle

Mirror the existing learningMode treatment: captureDenials is a wire field the SDK does not surface through the policy API yet, so the compile-time conformance test must include it in the ProcessContainer OnlyInWire allow-list.

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

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.

Pull request overview

Adds the config-contract plumbing for Windows denial capture (“learning-mode” deny-and-record trace) by introducing a new processContainer.captureDenials object that maps from wire → domain model, validates outputPath, and updates schema/docs/examples accordingly.

Changes:

  • Extend the Rust wire model with processContainer.captureDenials: { outputPath?: string } and propagate it into the domain policy model.
  • Add parse-time validation + mapping for captureDenials.outputPath in config_parser.rs, with unit tests.
  • Regenerate the dev JSON schema + Node SDK generated wire types, and update docs + an example config.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/examples/29_capture_denials.json New example configuration demonstrating processContainer.captureDenials.
src/core/wxc_common/src/wire.rs Adds CaptureDenials wire struct and hooks it into ProcessContainer.
src/core/wxc_common/src/models.rs Adds ContainerPolicy.capture_denials: Option<CaptureDenialsConfig> domain field.
src/core/wxc_common/src/config_parser.rs Maps + validates captureDenials (including outputPath) and adds unit tests.
sdk/node/src/generated/wire.ts Codegen update reflecting the new wire schema types.
schemas/dev/mxc-config.schema.0.8.0-dev.json Codegen update adding the CaptureDenials definition and field.
docs/schema.md Updates the schema documentation snippet to include captureDenials.

Comment thread src/core/wxc_common/src/config_parser.rs
Comment thread src/core/wxc_common/src/config_parser.rs Outdated
Comment thread src/core/wxc_common/src/wire.rs
Comment thread tests/examples/29_capture_denials.json
Comment thread docs/schema.md
- validate_capture_denials_output_path now rejects filesystem-root paths (Path::parent()==None), with a new unit test.
- wire.rs doc drops the unverified 'and be writable' claim (validation only checks parent existence); schema + SDK types regenerated.
- Example 29 and docs/schema.md no longer show a C:\\logs path whose parent may not exist (example omits outputPath; docs note the parent must already exist).
- Renamed capture_denials_threads_... test to capture_denials_accepts_... for clarity.

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

Copy link
Copy Markdown
Contributor Author

/azp run

@richiemsft
richiemsft marked this pull request as ready for review July 21, 2026 16:50
@richiemsft
richiemsft requested a review from a team as a code owner July 21, 2026 16:50
@azure-pipelines

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

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Introduce a CaptureDenialsMode enum on the captureDenials config object so a single learning-mode surface chooses between block-and-log (default; deny-by-default preserved) and allow-and-log (audit; relaxes deny-by-default, emits a security warning). Both modes record every ungranted access check; mode only decides block vs allow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants