Skip to content

Verify write permissions on settings policy folder#1624

Merged
SteveL-MSFT merged 7 commits into
mainfrom
stevel-msft-secure-settings-policy-path
Jul 14, 2026
Merged

Verify write permissions on settings policy folder#1624
SteveL-MSFT merged 7 commits into
mainfrom
stevel-msft-secure-settings-policy-path

Conversation

@SteveL-MSFT

Copy link
Copy Markdown
Member

Motivation

The dsc settings policy file (dsc.settings.json) is loaded from a system-wide location (/etc/dsc on Linux, %ProgramData%\dsc on Windows). If an unprivileged user can write to that folder, they could inject arbitrary policy settings -- a potential privilege escalation vector. This PR adds a security check so that an insecure folder is detected and its settings are simply not loaded rather than silently trusted.

Approach

get_settings_policy_file_path now validates folder permissions before returning the path:

  • Linux: Checks that the /etc/dsc folder is owned by root (uid 0) and has no group or other write bits set.
  • Windows: Enumerates the DACL on the ProgramData\dsc folder and verifies that only SYSTEM and Administrators have write access (FILE_WRITE_DATA, FILE_APPEND_DATA, WRITE_DAC, WRITE_OWNER).

If the check fails on either platform, a warning is emitted via tracing::warn! indicating the settings file will not be used, and an empty path is returned so execution continues without the policy settings. The process does not exit -- this is a graceful degradation.

Notable details

  • Added Win32_Security and Win32_Security_Authorization features to the workspace windows crate and added windows as a cfg(windows) dependency for dsc-lib.
  • The verify_windows_acl helper returns a bool so the caller can decide what to do on failure, keeping the ACL logic self-contained.
  • i18n strings added to en-us.toml under [util] for the warning messages.
  • A new Pester test (dsc_settings_policy_security.tests.ps1) validates the warning is emitted and exit code remains 0 on both Windows (using icacls to grant Everyone write) and Linux (using chmod 777). Both contexts require elevation and restore original state in AfterAll.

Steve Lee (POWERSHELL HE/HIM) (from Dev Box) and others added 3 commits July 13, 2026 12:22
On Linux, check that only root (uid 0) owns the /etc/dsc folder and
that no group or other write bits are set. On Windows, enumerate the
DACL on the ProgramData\dsc folder and verify that only SYSTEM and
Administrators have write access. If the folder is not secure, emit
a localized error message and exit with code 1.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
When the dsc policy folder has insecure permissions, emit a warning
indicating the settings file will not be used and return an empty path
so execution continues without the policy settings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Adds dsc_settings_policy_security.tests.ps1 that validates on both
Windows and Linux that an insecure dsc policy folder emits a warning
about the settings file not being used, and does not cause a non-zero
exit code. Also fixes minor issue with the t! macro call passing path
to the Windows-specific message.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 13, 2026 20:28

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

This PR hardens loading of the system-wide DSC settings policy (dsc.settings.json) by validating that the policy directory is not writable by unprivileged users, and skipping policy loading (with a warning) when the directory is deemed insecure.

Changes:

  • Added platform-specific policy-folder permission checks (Linux mode/uid validation; Windows DACL validation) and warnings when insecure.
  • Added i18n strings for the new warnings.
  • Added a new Pester test to validate warning emission and non-failing execution when the policy folder is made insecure.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
lib/dsc-lib/src/util.rs Adds Windows ACL validation + Linux ownership/mode validation before using the policy settings file path.
lib/dsc-lib/locales/en-us.toml Adds localized warning strings describing insecure policy folder requirements.
lib/dsc-lib/Cargo.toml Adds windows dependency for Windows-only ACL inspection.
dsc/tests/dsc_settings_policy_security.tests.ps1 Adds Pester coverage for insecure policy folder detection/warning behavior.
Cargo.toml Enables additional windows crate features needed for ACL inspection APIs.
Cargo.lock Locks the added windows crate dependency version.

Comment thread lib/dsc-lib/src/util.rs
Comment thread lib/dsc-lib/src/util.rs
Comment thread lib/dsc-lib/src/util.rs
Comment thread lib/dsc-lib/src/util.rs Outdated
Comment thread lib/dsc-lib/src/util.rs
Comment thread lib/dsc-lib/src/util.rs
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1 Outdated
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1
- Fix clippy explicit-auto-deref: &(*ace).SidStart -> &ace.SidStart
- Fail closed: return false (insecure) when GetNamedSecurityInfoW,
  GetAce, or fs::metadata fails instead of assuming secure
- Treat NULL DACL as insecure (full access to everyone)
- Add GENERIC_WRITE and GENERIC_ALL to the write mask
- Skip inherit-only ACEs that don't apply to the folder itself
- On Linux, emit warning and return empty on metadata failure
- Tests: save/restore original ACL via Get-Acl/Set-Acl on Windows
- Tests: capture original mode with stat on Linux instead of
  hardcoding 755

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

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

😐 Code Coverage Report

Changed Code Coverage

75% (70%+ coverage)

Metric Value
Changed lines analyzed 54
Lines covered by tests 41
Coverage percentage 75%

🔵 Full Codebase Coverage

81% (good)

Metric Value
Total executable lines 18098
Lines covered by tests 14808
Coverage percentage 81%

Changed code coverage measures only Rust lines added/modified in this PR.
Full codebase coverage measures all instrumented Rust lines across the project.

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

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Comment thread lib/dsc-lib/src/util.rs Outdated
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1
Comment thread dsc/tests/dsc_settings_policy_security.tests.ps1 Outdated
Steve Lee (POWERSHELL HE/HIM) (from Dev Box) and others added 2 commits July 13, 2026 14:51
- Handle non-standard allow ACE types (callback, object ACEs): fail
  closed for any ACE type we cannot reliably parse the SID from
- Skip deny ACE types (1, 6, 10) as they restrict rather than grant
- Remove /T from icacls in test to avoid recursively modifying children
- Gate Linux test context on \False to avoid macOS failures
- Extract verify_linux_permissions helper for testability
- Add Rust unit tests for Linux permission checks covering:
  nonexistent path, non-root owned dir, and missing /etc/dsc scenarios

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The 'Confirm settings override priorities' test creates ProgramData\dsc
which on CI inherits broad write access from the parent. The new ACL
validation now rejects that folder. Fix by explicitly setting a secure
ACL (only SYSTEM, Administrators write; Users read) after creating it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@SteveL-MSFT SteveL-MSFT merged commit a3f99c6 into main Jul 14, 2026
24 checks passed
@SteveL-MSFT SteveL-MSFT deleted the stevel-msft-secure-settings-policy-path branch July 14, 2026 00:38
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