mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-20 06:00:06 +08:00
* fix(core): enforce owner-only Windows ACLs on sensitive files and dirs set_dir_owner_only/set_file_owner_only were unconditional no-ops on Windows, so the CLI's mTLS client private key, OIDC/edge tokens, cached SSH keys, and the gateway's key-encryption key relied entirely on inherited NTFS ACLs with no OpenShell-applied restriction. Apply an owner-only DACL via SetEntriesInAclW/SetNamedSecurityInfoW with PROTECTED_DACL_SECURITY_INFORMATION to strip inherited ACEs, matching the 0700/0600 guarantee already provided on Unix. is_file_permissions_too_open now also works on Windows instead of being Unix-only, closing the detection gap alongside the prevention gap. Signed-off-by: Prashant Khodade <pkhodade@nvidia.com> (cherry picked from commit 71560e947f85819efbcddf70ddda94befab62b0b) * fix(core): treat a NULL DACL as too open in is_file_permissions_too_open has_foreign_trustee conflated a NULL DACL with an unreadable/invalid ACL and returned Some(false) (not too open) for both. Per the Win32 contract, a NULL DACL means the object grants full access to everyone -- the most permissive state possible -- so it must be flagged as too open. Split the null and invalid-ACL branches: null now returns Some(true), invalid ACL keeps the existing unreadable-ACL fallback (None, which the caller maps to false via unwrap_or). Adds a regression test that constructs a real NULL DACL via a SetNamedSecurityInfoW helper confined to the windows_acl module, consistent with the existing unsafe-FFI confinement in that module. Found by CodeRabbit review on MR !113. Signed-off-by: Prashant Khodade <pkhodade@nvidia.com> (cherry picked from commit 46e635a4ef1d6937cdb088f46aa85baee3d6ad28) * fix(core): close three false-negative gaps in the Windows ACL audit restrict_to_current_user() updated only the DACL, leaving a foreign owner's implicit WRITE_DAC right intact -- they could later replace the DACL we just set. Query OWNER_SECURITY_INFORMATION and take ownership in the same SetNamedSecurityInfoW call; if the caller can't (a genuinely foreign-owned object), the call now fails instead of silently leaving the object insecure. is_file_permissions_too_open() mapped every Win32 inspection failure (missing READ_CONTROL, an invalid ACL, a token-query failure) to "not too open" via unwrap_or(false). Fail closed instead: an inspection failure is a security false-negative risk, not a green light. has_foreign_trustee()'s ACE loop only recognized plain ACCESS_ALLOWED_ACE_TYPE and treated every other type as non-granting. Windows also defines access-allowed object, callback, and callback-object ACE variants that can grant rights to a foreign trustee; this audit doesn't parse their wider layouts, so their mere presence is now conservatively flagged as too open instead of silently skipped. Also updates architecture/gateway.md, which still described the SQLite file-tightening behavior only in terms of Unix mode 0o600, to distinguish it from the owner-only DACL behavior on Windows. Addresses review comments on PR #3495. Signed-off-by: Prashant Khodade <pkhodade@nvidia.com> * fix(core): conditional owner claim and audit owner in Windows ACL helpers restrict_to_current_user: query the current owner before calling SetNamedSecurityInfoW. Include OWNER_SECURITY_INFORMATION only when the path has a foreign owner -- requesting it unconditionally fails with ACCESS_DENIED (0x80070005) on standard credentials even when the current user is already the owner, because WRITE_OWNER is not implied by object ownership. A foreign-owned path still triggers an ownership claim and fails hard if the claim is denied, preserving the security contract. has_foreign_trustee: request OWNER_SECURITY_INFORMATION alongside DACL_SECURITY_INFORMATION and reject paths with a foreign owner immediately, before inspecting the DACL. A foreign owner has implicit WRITE_DAC rights and can replace any DACL we set, so a clean DACL is not sufficient evidence of safety on a foreign-owned object. architecture/gateway.md: clarify that the Windows path-hardening behavior sets mode 0o600 on Unix and applies a protected owner-only DACL on Windows, with conditional ownership claim and fail-hard semantics for foreign-owned objects. Signed-off-by: Prashant Khodade <pkhodade@nvidia.com> --------- Signed-off-by: Prashant Khodade <pkhodade@nvidia.com>
67 lines
2.2 KiB
TOML
67 lines
2.2 KiB
TOML
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
[package]
|
|
name = "openshell-core"
|
|
description = "Shared library for OpenShell - proto definitions, config, and errors"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
|
|
[dependencies]
|
|
async-trait = "0.1"
|
|
openshell-extension-core = { path = "../openshell-extension-core" }
|
|
glob = { workspace = true }
|
|
prost = { workspace = true }
|
|
prost-types = { workspace = true }
|
|
tonic = { workspace = true, features = ["channel", "tls-aws-lc"] }
|
|
tonic-prost = { workspace = true }
|
|
tonic-types = { workspace = true }
|
|
tokio = { workspace = true }
|
|
tokio-stream = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
miette = { workspace = true }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
sha2 = { workspace = true }
|
|
tracing = { workspace = true }
|
|
url = { workspace = true }
|
|
ipnet = "2"
|
|
rustls = { workspace = true }
|
|
rustls-pemfile = { workspace = true }
|
|
base64 = { workspace = true }
|
|
chrono = { version = "0.4", default-features = false, features = ["clock", "std"], optional = true }
|
|
reqwest = { workspace = true, features = ["blocking", "rustls-tls-native-roots-no-provider"], optional = true }
|
|
tar = { version = "0.4", optional = true }
|
|
tempfile = { version = "3", optional = true }
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
nix = { workspace = true }
|
|
rustix = { workspace = true }
|
|
|
|
[target.'cfg(windows)'.dependencies]
|
|
windows = { workspace = true }
|
|
|
|
[features]
|
|
default = ["telemetry"]
|
|
## Compile in anonymous telemetry emission support. On by default; disable with
|
|
## `--no-default-features` (plus any other features you need) for a build that
|
|
## contains no telemetry endpoint, no HTTP client, and no emission code at all.
|
|
driver-extraction = ["dep:tar", "dep:tempfile"]
|
|
telemetry = ["dep:reqwest", "dep:chrono", "reqwest?/blocking"]
|
|
## OAuth2 token request helpers used by supervisor and gateway.
|
|
oauth = ["dep:reqwest"]
|
|
|
|
[build-dependencies]
|
|
tonic-prost-build = { workspace = true }
|
|
protoc-bin-vendored = { workspace = true }
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|
|
rcgen = { workspace = true }
|
|
|
|
[lints]
|
|
workspace = true
|