🩹 [Patch]: Secret crypto operations now fail fast on invalid input with lower per-call overhead#45
Conversation
Super-linter summary
Super-linter detected linting errors For more information, see the GitHub Actions workflow run Powered by Super-linter SPELL_CODESPELL |
There was a problem hiding this comment.
Pull request overview
This PR hardens the Sodium PowerShell module by adding a managed validation layer in the C# interop bridge, centralizing module initialization with cached constants, validating input shapes earlier in public commands, clearing sensitive buffers in finally blocks, and making runtime selection deterministic by process architecture.
Changes:
- Added validated wrappers around all native libsodium P/Invoke calls and constrained DLL search paths in
PSModule/Sodium/Sodium.cs. - Introduced
Initialize-Sodiumwith module-scoped cached size constants and refactored public crypto commands to use them, plus added explicit length validation andfinally-block buffer clearing. - Switched platform/runtime selection to
RuntimeInformation.ProcessArchitectureand aligned the Visual C++ Redistributable check to the active architecture; madebuild.ps1fail fast on publish errors.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| PSModule/Sodium/Sodium.cs | Wraps native imports in a Native inner class with buffer length validation and constrained DLL search paths. |
| PSModule/build.ps1 | Sets $ErrorActionPreference = 'Stop', builds with -c Release, checks $LASTEXITCODE, and ensures Pop-Location in finally. |
| src/main.ps1 | Resolves runtime identifier from ProcessArchitecture for Linux/macOS/Windows and centralizes module import. |
| src/functions/private/Assert-VisualCRedistributableInstalled.ps1 | Adds Architecture parameter, validates Installed != 0, and uses -ErrorAction SilentlyContinue. |
| src/functions/private/Initialize-Sodium.ps1 | New helper that initializes Sodium once and caches public/private/seal byte sizes. |
| src/variables/private/Initialized.ps1 | Declares module-scoped Sodium state and size variables. |
| src/functions/public/New-SodiumKeyPair.ps1 | Uses cached sizes, disposes SHA256, clears sensitive buffers in finally. |
| src/functions/public/Get-SodiumPublicKey.ps1 | Removes duplicate [CmdletBinding()], validates private-key length, clears the key buffer. |
| src/functions/public/ConvertTo-SodiumSealedBox.ps1 | Uses cached sizes, validates public key length, clears plaintext in finally. |
| src/functions/public/ConvertFrom-SodiumSealedBox.ps1 | Validates short sealed boxes and key lengths with explicit messages; clears sensitive buffers in finally. |
| tests/Sodium.Tests.ps1 | Adds regression tests for short sealed box and wrong-length private key. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
Secret encryption and decryption operations in Sodium now validate malformed inputs earlier, return clearer errors for invalid key and payload shapes, and avoid repeated initialization overhead during repeated command usage.
Changed: Repeated crypto calls now incur less overhead
Public crypto commands now initialize Sodium once per module session and reuse cached key and sealed-box size constants instead of re-querying those values for every invocation. This reduces repeated setup cost in CI and automation scenarios that process many secrets.
Fixed: Invalid key and sealed payload shapes now fail fast with clear errors
Get-SodiumPublicKeynow rejects wrong-length private keys before key derivation, andConvertFrom-SodiumSealedBoxnow rejects sealed payloads shorter than the required Sodium overhead. This prevents low-level failures and returns actionable validation messages earlier in the command flow.Changed: Runtime loading behavior is now more deterministic across platforms
Runtime selection now resolves from process architecture across Windows, Linux, and macOS, and Windows support validation aligns with the active process architecture, improving predictable module startup behavior on mixed environments.
Technical Details
PSModule/Sodium/Sodium.csaround native interop calls, including buffer size checks before unmanaged execution.Initialize-Sodiumand module-scoped cached constants viasrc/functions/private/Initialize-Sodium.ps1andsrc/variables/private/Initialized.ps1.src/functions/public/*to use centralized initialization, enforce explicit input-length checks, and clear sensitive byte arrays infinallyblocks.src/main.ps1to useRuntimeInformation.ProcessArchitecture.src/functions/private/Assert-VisualCRedistributableInstalled.ps1to validate architecture-specific runtime installation/version conditions.PSModule/build.ps1to fail fast on per-runtime publish failures.tests/Sodium.Tests.ps1for short sealed-box payloads and wrong-length private keys.