diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2a21aa..6c0ac6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,47 +6,82 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
## Unreleased
+- `Start-InfisicalProcess`: switched stdout/stderr capture to event-based `OutputDataReceived`/`ErrorDataReceived` with `BeginOutputReadLine`/`BeginErrorReadLine` (removed `Task`/`ReadToEndAsync`/`GetAwaiter().GetResult()` to eliminate PowerShell `SynchronizationContext` deadlock risk). Restored the original `do { log; sleep } while (!HasExited)` polling pattern using `Thread.Sleep(pollInterval)` so verbose "has been running for X" / "Checking again in Y" messages fire at the configured cadence even when no `-ExecutionTimeout` is supplied.
+- `Start-InfisicalProcess`: TimeSpan values in verbose logs and on the result now use a friendly format ("`7 seconds, and 364 milliseconds`", "`1 minute, and 30 seconds`", "`N/A`" when zero) matching the legacy `Start-ProcessWithOutput` `GetTimeSpanMessage` scriptblock. Added `DurationFriendly` property to `InfisicalProcessResult` and a "The command execution took X" verbose line at completion.
+
+## 2026.06.06.2227
+
+- Build produced from commit d3c7b83da717.
+
+## Unreleased (carried forward)
+
+## 2026.06.06.2221
+
+- Build produced from commit d3c7b83da717.
+
+## Unreleased (carried forward)
+
+## 2026.06.06.2207
+
+- Build produced from commit d3c7b83da717.
+
+## Unreleased (carried forward)
+
+## 2026.06.06.2206
+
+- Build produced from commit d3c7b83da717.
+
+## Unreleased (carried forward)
+
+## 2026.06.06.2155
+
+- Build produced from commit d3c7b83da717.
+
+## Unreleased (carried forward)
+
+- Added `Start-InfisicalProcess` cmdlet: launches a child process with `InfisicalSecret` objects (pipeline or `-Secret`) decrypted directly into `ProcessStartInfo.Environment`, with optional `-Prefix`, additional `-EnvironmentVariables`, stdout/stderr capture, `-AcceptableExitCodeList` validation, `-ParsingExpression` regex parsing, `-ExecutionTimeout`/`-ExecutionTimeoutInterval` polling, `-NoWait`, `-WindowStyle`/`-CreateNoWindow` parameter sets, `-Priority`, `-StandardInputObjectList`, `-SecureArgumentList`, `-LogOutput`, `-ContinueOnError`, and `ShouldProcess` support. Secret plaintext is never written to user or machine scope. `build.ps1` `CmdletsToExport` and `Test-ModuleImports` expected list now contain 42 cmdlets.
+
## 2026.06.06.2138
- Build produced from commit 318db7048017.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.2040
- Build produced from commit 1270c9099cae.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.0240
- Build produced from commit b438abf18f18.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.0215
- Build produced from commit 82f99ea7d4a4.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.0205
- Build produced from commit 86968c18cb15.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.0117
- Build produced from commit cffda99591c9.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
## 2026.06.05.0015
- Build produced from commit fb27ab8a8503.
-## Unreleased (carried forward)
+## Unreleased (carried forward)
- Fixed `ParameterNameConflictsWithAlias` registration error on `Get-InfisicalCertificateApplication`, `Get-InfisicalCertificateApplicationEnrollment`, and `New-InfisicalScepDynamicChallenge`. The cmdlets each declared an `[Alias]` entry that matched the parameter's own name, which PowerShell rejects at bind time and made the cmdlets unusable.
diff --git a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
index bf7d41e..7b31ff4 100644
--- a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
+++ b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
@@ -1654,4 +1654,51 @@ $WriteInfisicalScepMdmProfileToWmiResult = Write-InfisicalScepMdmProfileToWmi @W
+
+
+ Start-InfisicalProcess
+ Starts a child process with Infisical secrets injected directly into its environment block.
+ Start
+ InfisicalProcess
+
+
+ Launches the executable specified by -FilePath, captures stdout/stderr, validates the exit code against -AcceptableExitCodeList, and optionally parses output with -ParsingExpression. InfisicalSecret objects supplied via -Secret (pipeline or by name) are decrypted into the ProcessStartInfo.Environment dictionary only, never written to the user or machine scope; -Prefix prepends a string to each injected variable name. -EnvironmentVariables adds additional non-secret values. -ExecutionTimeout, -NoWait, -CreateNoWindow, -WindowStyle, -Priority, -StandardInputObjectList, -SecureArgumentList, -LogOutput, and -ContinueOnError mirror the semantics of the upstream Start-ProcessWithOutput helper. Honors -WhatIf and -Confirm.
+
+
+ Notes
+
+ Secret values exist as plain strings only within the child process environment block; they are never persisted to the calling shell, the user scope, or the machine scope. Use -SecureArgumentList to mask sensitive command-line arguments in verbose output.
+
+
+
+
+ EXAMPLE 1
+ Get-InfisicalSecret -SecretPath '/build' | Start-InfisicalProcess -FilePath 'dotnet.exe' -ArgumentList @('publish','-c','Release') -AcceptableExitCodeList @('0') -CreateNoWindow
+ Decrypts every secret at /build, exposes each one as a process environment variable, and runs dotnet publish with no visible window.
+
+
+ EXAMPLE 2
+ $Secrets = Get-InfisicalSecret -SecretPath '/runtime'
+Start-InfisicalProcess -FilePath 'node.exe' -ArgumentList @('app.js') -Secret $Secrets -Prefix 'APP_' -ExecutionTimeout ([TimeSpan]::FromMinutes(5)) -LogOutput
+ Injects the /runtime secrets as APP_-prefixed environment variables, runs node app.js, and forcibly terminates the process after five minutes if it has not exited.
+
+
+ EXAMPLE 3
+ $StartInfisicalProcessParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' -ArgumentList ([System.StringComparer]::OrdinalIgnoreCase)
+$StartInfisicalProcessParameters.FilePath = 'pwsh.exe'
+$StartInfisicalProcessParameters.ArgumentList = @('-NoProfile','-Command','Write-Host $env:DEPLOY_TOKEN.Length')
+$StartInfisicalProcessParameters.Secret = Get-InfisicalSecret -SecretPath '/deploy'
+$StartInfisicalProcessParameters.Prefix = 'DEPLOY_'
+$StartInfisicalProcessParameters.AcceptableExitCodeList = @('0')
+$StartInfisicalProcessParameters.CreateNoWindow = $True
+$StartInfisicalProcessParameters.SecureArgumentList = $True
+$StartInfisicalProcessParameters.LogOutput = $True
+$StartInfisicalProcessParameters.Verbose = $True
+
+$StartInfisicalProcessResult = Start-InfisicalProcess @StartInfisicalProcessParameters
+ Splatted invocation that runs pwsh with DEPLOY_-prefixed secrets in scope, masks the command line in verbose output, and echoes both stdout and stderr to the verbose stream after exit.
+
+
+
+
diff --git a/README.md b/README.md
index 605b084..8c85102 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ Import-Module -Name .\Module\PSInfisicalAPI
## Cmdlets
-The module exports 37 cmdlets. Discovery cmdlets (`Get-Infisical*`) use a `List` (default) / single-record parameter-set pair: invoking without the identity parameter returns the collection, supplying the identity parameter returns one record.
+The module exports 42 cmdlets. Discovery cmdlets (`Get-Infisical*`) use a `List` (default) / single-record parameter-set pair: invoking without the identity parameter returns the collection, supplying the identity parameter returns one record.
### Session
@@ -99,6 +99,12 @@ The module exports 37 cmdlets. Discovery cmdlets (`Get-Infisical*`) use a `List`
| `Export-InfisicalScepMdmProfile` | Writes a SCEP MDM profile to disk as a SyncML payload suitable for MDM delivery. |
| `Write-InfisicalScepMdmProfileToWmi`| Submits a SCEP MDM profile to the local MDM Bridge WMI provider to trigger enrollment. |
+### Process
+
+| Cmdlet | Purpose |
+| ------------------------ | -------------------------------------------------------------------------------------------------- |
+| `Start-InfisicalProcess` | Launches a child process with Infisical secrets injected directly into its environment block, capturing stdout/stderr and validating the exit code. |
+
Use `Get-Help -Full` for parameter details and `Get-Help about_PSInfisicalAPI` for the module overview.
## Quick start
diff --git a/build.ps1 b/build.ps1
index 8de86d7..26fdb71 100644
--- a/build.ps1
+++ b/build.ps1
@@ -144,7 +144,8 @@ function Write-Manifest {
'New-InfisicalScepDynamicChallenge',
'Get-InfisicalScepMdmProfile',
'Export-InfisicalScepMdmProfile',
- 'Write-InfisicalScepMdmProfileToWmi'
+ 'Write-InfisicalScepMdmProfileToWmi',
+ 'Start-InfisicalProcess'
)
AliasesToExport = @()
VariablesToExport = @()
@@ -209,7 +210,7 @@ if (`$cmds.Count -eq 0) {
throw "No cmdlets were exported by the PSInfisicalAPI module."
}
-`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificateProfile','Get-InfisicalCertificatePolicy','Get-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate','Get-InfisicalCertificateApplication','Get-InfisicalCertificateApplicationEnrollment','New-InfisicalScepDynamicChallenge','Get-InfisicalScepMdmProfile','Export-InfisicalScepMdmProfile','Write-InfisicalScepMdmProfileToWmi')
+`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificateProfile','Get-InfisicalCertificatePolicy','Get-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate','Get-InfisicalCertificateApplication','Get-InfisicalCertificateApplicationEnrollment','New-InfisicalScepDynamicChallenge','Get-InfisicalScepMdmProfile','Export-InfisicalScepMdmProfile','Write-InfisicalScepMdmProfileToWmi','Start-InfisicalProcess')
foreach (`$expected in `$expectedCmds) {
if (-not (Get-Command -Name `$expected -Module PSInfisicalAPI -ErrorAction SilentlyContinue)) {
throw "Cmdlet not found: `$expected"
diff --git a/docs/DesignSpec.md b/docs/DesignSpec.md
index eeff9c9..b0000ad 100644
--- a/docs/DesignSpec.md
+++ b/docs/DesignSpec.md
@@ -1491,6 +1491,48 @@ No warnings should be emitted.
---
+# 16.6 Start-InfisicalProcess
+
+Signature:
+
+```text
+Start-InfisicalProcess
+ -FilePath
+ [-WorkingDirectory ]
+ [-ArgumentList ]
+ [-AcceptableExitCodeList ]
+ [-WindowStyle ]
+ [-CreateNoWindow]
+ [-NoWait]
+ [-Priority ]
+ [-ExecutionTimeout ]
+ [-ExecutionTimeoutInterval ]
+ [-StandardInputObjectList