Skip to content

Commit da7e527

Browse files
yotsudaclaude
andcommitted
release: v1.7.7
- Authenticode-sign Windows binaries (closes #46) - Bundle Ude.NetStandard license texts (LGPL-2.1 compliance) - Fix status line truncation for pipelines with leading whitespace - Build-AllPlatforms.ps1 gains -Sign switch (interactive PFX passphrase) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3f6b7ca commit da7e527

11 files changed

Lines changed: 1446 additions & 10 deletions

File tree

Build-AllPlatforms.ps1

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ param(
77
[ValidateSet('Dll', 'WinX64', 'LinuxX64', 'OsxX64', 'OsxArm64')]
88
[string[]]$Target,
99
[string]$Configuration = 'Release',
10-
[string]$OutputBase
10+
[string]$OutputBase,
11+
[switch]$Sign,
12+
[string]$PfxPath = 'C:\MyProj\vault\yotsuda.pfx',
13+
[string]$TimestampUrl = 'http://timestamp.digicert.com'
1114
)
1215

1316
$ErrorActionPreference = 'Stop'
@@ -101,6 +104,14 @@ if ('Dll' -in $Target) {
101104
Write-Host " Copied: PowerShell.MCP.psd1" -ForegroundColor Green
102105
Write-Host " Copied: PowerShell.MCP.psm1" -ForegroundColor Green
103106

107+
# Copy third-party license notices (LGPL-2.1 obligation for Ude.NetStandard)
108+
Copy-Item (Join-Path $PSScriptRoot 'THIRD_PARTY_NOTICES.md') -Destination $OutputBase -Force
109+
$licensesSrc = Join-Path $PSScriptRoot 'licenses'
110+
$licensesDst = Join-Path $OutputBase 'licenses'
111+
if (Test-Path $licensesDst) { Remove-Item $licensesDst -Recurse -Force }
112+
Copy-Item $licensesSrc -Destination $licensesDst -Recurse -Force
113+
Write-Host " Copied: THIRD_PARTY_NOTICES.md" -ForegroundColor Green
114+
Write-Host " Copied: licenses\" -ForegroundColor Green
104115

105116
Write-Host ""
106117
}
@@ -156,6 +167,57 @@ if ($proxyTargets) {
156167
Write-Host ""
157168
}
158169

170+
# =============================================================================
171+
# Authenticode-sign Windows binaries (PowerShell.MCP.dll + Proxy.exe)
172+
# =============================================================================
173+
# WDAC / Device Guard environments block unsigned binaries. Signing with our
174+
# self-signed cert lets IT add the cert as a trusted publisher once instead of
175+
# whitelisting per-version SHA-256 hashes (which break on every update).
176+
# See issue #46.
177+
178+
$signTargets = @()
179+
if ('Dll' -in $Target) {
180+
$signTargets += Join-Path $OutputBase 'PowerShell.MCP.dll'
181+
}
182+
if ('WinX64' -in $Target) {
183+
$signTargets += Join-Path $OutputBase 'bin\win-x64\PowerShell.MCP.Proxy.exe'
184+
}
185+
186+
if ($signTargets -and $Sign) {
187+
Write-Host "[Sign] Authenticode-signing Windows binaries..." -ForegroundColor Yellow
188+
189+
if (-not (Test-Path $PfxPath)) {
190+
Write-Error " PFX not found at $PfxPath. Cannot sign."
191+
exit 1
192+
}
193+
194+
$pfxPassword = Read-Host " Enter PFX password" -AsSecureString
195+
$cert = Get-PfxCertificate -FilePath $PfxPath -Password $pfxPassword
196+
197+
foreach ($file in $signTargets) {
198+
if (-not (Test-Path $file)) {
199+
Write-Warning " Missing: $file — skipping"
200+
continue
201+
}
202+
$result = Set-AuthenticodeSignature `
203+
-FilePath $file `
204+
-Certificate $cert `
205+
-HashAlgorithm SHA256 `
206+
-TimestampServer $TimestampUrl `
207+
-IncludeChain NotRoot
208+
if ($result.Status -eq 'Valid') {
209+
Write-Host " Signed: $(Split-Path $file -Leaf)" -ForegroundColor Green
210+
} else {
211+
Write-Error " Sign failed for $file : $($result.StatusMessage)"
212+
exit 1
213+
}
214+
}
215+
Write-Host ""
216+
} elseif ($signTargets) {
217+
Write-Host "[Sign] Skipping signing (pass -Sign to enable, e.g. for publish builds)." -ForegroundColor Gray
218+
Write-Host ""
219+
}
220+
159221
# =============================================================================
160222
# Summary: Verify built files
161223
# =============================================================================
@@ -169,6 +231,11 @@ if ('Dll' -in $Target) {
169231
'PowerShell.MCP.psd1',
170232
'PowerShell.MCP.psm1',
171233
'Ude.NetStandard.dll',
234+
'THIRD_PARTY_NOTICES.md',
235+
'licenses\Ude.NetStandard\COPYING',
236+
'licenses\Ude.NetStandard\MPL-1.1.txt',
237+
'licenses\Ude.NetStandard\gpl-2.0.txt',
238+
'licenses\Ude.NetStandard\lgpl-2.1.txt',
172239
'en-US\PowerShell.MCP-help.xml'
173240
)
174241
}
@@ -201,12 +268,14 @@ $allowedFiles = @(
201268
'PowerShell.MCP.dll',
202269
'PowerShell.MCP.psd1',
203270
'PowerShell.MCP.psm1',
204-
'Ude.NetStandard.dll'
271+
'Ude.NetStandard.dll',
272+
'THIRD_PARTY_NOTICES.md'
205273
)
206274

207275
$allowedDirs = @(
208276
'bin',
209-
'en-US'
277+
'en-US',
278+
'licenses'
210279
)
211280

212281
$unexpectedItems = @()
@@ -253,8 +322,9 @@ if (Test-Path $binPath) {
253322
# Check en-US directory
254323
$enUSPath = Join-Path $OutputBase 'en-US'
255324
if (Test-Path $enUSPath) {
325+
$allowedHelpFiles = @('PowerShell.MCP-help.xml', 'PowerShell.MCP.dll-Help.xml')
256326
Get-ChildItem $enUSPath -File | ForEach-Object {
257-
if ($_.Name -ne 'PowerShell.MCP.dll-Help.xml') {
327+
if ($_.Name -notin $allowedHelpFiles) {
258328
$unexpectedItems += "en-US\$($_.Name)"
259329
}
260330
}

PowerShell.MCP.Proxy/PowerShell.MCP.Proxy.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<TargetFramework>net9.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8-
<Version>1.7.6.0</Version>
8+
<Version>1.7.7.0</Version>
99
<NoWarn>$(NoWarn);NETSDK1206</NoWarn>
1010

1111
<!-- Single File デプロイ設定 -->

PowerShell.MCP/PowerShell.MCP.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7-
<Version>1.7.6.0</Version>
7+
<Version>1.7.7.0</Version>
88
<NoWarn>$(NoWarn);NETSDK1206</NoWarn>
99
</PropertyGroup>
1010

PowerShell.MCP/Resources/MCPPollingEngine.ps1

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,18 @@ if (-not (Test-Path Variable:global:McpTimer)) {
323323
# Split by newline, pipe character, and limit to 30 chars
324324
$pipelineSummary = ""
325325
if ($Pipeline) {
326-
# Split by newline first, take first line
327-
$firstPart = ($Pipeline -split "[\r\n]")[0].Trim()
326+
# Strip leading whitespace/newlines so a pipeline like
327+
# "\nWrite-Host hi" doesn't become "..." (or empty when
328+
# the pipeline is whitespace-only) on the status line.
329+
$trimmedPipeline = $Pipeline.Trim()
330+
# Split by newline first, take first non-empty line
331+
$firstPart = ($trimmedPipeline -split "[\r\n]")[0].Trim()
328332
# Split by pipe character, take first segment
329333
$firstPart = ($firstPart -split "\|")[0].Trim()
330334
# Truncate to 30 chars if needed
331335
if ($firstPart.Length -gt 30) {
332336
$pipelineSummary = $firstPart.Substring(0, 27) + "..."
333-
} elseif ($firstPart.Length -lt $Pipeline.TrimEnd().Length) {
337+
} elseif ($firstPart.Length -lt $trimmedPipeline.Length) {
334338
# Was truncated by newline or pipe
335339
$pipelineSummary = $firstPart + "..."
336340
} else {

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ PowerShell.MCP complements your existing MCP setup by providing a flexible, gene
108108
- Every command visible and auditable
109109
- Integrates with existing security policies
110110

111+
**🔒 Secrets stay with you, not the AI**
112+
- Interactive prompts (`Read-Host -AsSecureString`, `Get-Credential`, MFA codes) hide input from the AI
113+
- Enter passphrases for code-signing, `gpg`, `ssh-add`, `sudo`, cloud CLI MFA — keystrokes go to the program, never to AI's output stream
114+
- AI orchestrates the workflow ("build, sign, push the tag"); you supply the secret at the right moment
115+
- Impossible with stdin-piped MCP shells, where the AI must somehow feed the secret in
116+
111117
## Architecture
112118

113119
Four tools provide maximum flexibility with minimum complexity:
@@ -424,6 +430,25 @@ Generates interactive HTML maps with markers, descriptions, and optional 3D disp
424430
- **External Command Colors**: Color output from some CLI tools may not be preserved (git colors are supported).
425431
- **Command History**: AI-executed single-line commands are added to console history. Multi-line commands are intentionally excluded to avoid history bloat.
426432

433+
## Enterprise Deployment (WDAC / Device Guard)
434+
435+
Starting with v1.7.7, `PowerShell.MCP.dll` and `PowerShell.MCP.Proxy.exe`
436+
(win-x64) are Authenticode-signed with the **yotsuda code-signing
437+
certificate**, shared across all yotsuda OSS projects.
438+
439+
For installation instructions (personal PC, AD GPO deployment, WDAC policy
440+
configuration) and the public certificate file itself, see:
441+
442+
**[github.com/yotsuda/code-signing](https://github.com/yotsuda/code-signing)**
443+
444+
The certificate thumbprint is also published in each GitHub release's notes.
445+
446+
```powershell
447+
# Quick verify on installed binaries
448+
Get-AuthenticodeSignature `
449+
"$((Get-Module PowerShell.MCP -ListAvailable).ModuleBase)\bin\win-x64\PowerShell.MCP.Proxy.exe"
450+
```
451+
427452
## Disclaimer
428453

429454
This software is provided "AS IS" without warranty of any kind, either expressed or implied.

Staging/PowerShell.MCP.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
RootModule = 'PowerShell.MCP.psm1'
1313

1414
# Version number of this module.
15-
ModuleVersion = '1.7.6'
15+
ModuleVersion = '1.7.7'
1616

1717
# Supported PSEditions
1818
CompatiblePSEditions = @('Core')

THIRD_PARTY_NOTICES.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Third Party Notices
2+
3+
PowerShell.MCP redistributes the following third-party components.
4+
See [LICENSE](LICENSE) for the PowerShell.MCP license itself (MIT).
5+
6+
---
7+
8+
## Ude.NetStandard
9+
10+
- **Version:** 1.2.0
11+
- **Source:** https://github.com/yinyue200/ude
12+
- **NuGet:** https://www.nuget.org/packages/Ude.NetStandard/
13+
- **Author:** yinyue200 (and original Mozilla Universal Charset Detector contributors)
14+
- **License:** Triple-licensed under MPL 1.1 / GPL 2.0 / LGPL 2.1
15+
(recipient may choose any one; PowerShell.MCP redistributes under LGPL 2.1)
16+
17+
PowerShell.MCP bundles `Ude.NetStandard.dll` (compiled binary, unmodified
18+
from the official NuGet package) for character set detection. The DLL is
19+
loaded via dynamic linking; users may replace the bundled copy with their
20+
own build of Ude.NetStandard.
21+
22+
The full text of all three licenses is included under
23+
[`licenses/Ude.NetStandard/`](licenses/Ude.NetStandard/).

licenses/Ude.NetStandard/COPYING

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
See license directory

0 commit comments

Comments
 (0)