diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 0ca0cf2..3044df0 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -64,9 +64,17 @@ $AllowUnverified = ($env:TRACEBLOC_ALLOW_UNVERIFIED -eq '1') # every fetch below carries either the binary we are about to run or the # verifier that authenticates it — neither may negotiate down. PS7+ already # defaults higher; setting it is harmless there. +# +# ASSIGN Tls12, do NOT -bor onto the default: OR-ing Tls12 on LEAVES SSL3/TLS1.0/1.1 +# advertised, so a downgrade stays on the table — the exact thing this floor exists +# to remove. Tls12 alone is the floor and is always negotiable on any host that can +# reach us. We deliberately do NOT also add Tls13: [Enum]::IsDefined is true on +# .NET 4.8 even where Schannel cannot negotiate 1.3 (Win10 21H1, Server 2019), and +# assigning it then THROWS — the empty catch would swallow that and leave the floor +# unset, so a `Tls12 -bor Tls13` attempt can defeat the very floor it decorates +# (cli#528 Bugbot). 1.2 is secure for these fetches; 1.3 is not worth that risk. try { - [Net.ServicePointManager]::SecurityProtocol = - [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch { } # --------------------------------------------------------------------- diff --git a/scripts/tests/install-ps1-verify.sh b/scripts/tests/install-ps1-verify.sh index 7d9bd3e..3bbb674 100755 --- a/scripts/tests/install-ps1-verify.sh +++ b/scripts/tests/install-ps1-verify.sh @@ -77,7 +77,21 @@ else bad 'the cosign bootstrap asks for an asset sigstore does not publish' fi -# ── 5. behavioural tier ───────────────────────────────────────────────────── +# ── 5. the TLS floor is ASSIGNED, not OR-ed onto the default ──────────────── +# `-bor Tls12` onto [Net.ServicePointManager]::SecurityProtocol leaves SSL3/ +# TLS1.0/1.1 advertised, so a fetch can still negotiate down — the exact thing +# the floor exists to remove (cli#528 Bugbot). The floor must ASSIGN the value. +# Collapse newlines first: the old form spanned two lines (`= \n -bor`). +_ps1_flat=$(tr '\n' ' ' < "$INSTALLER") +if printf '%s' "$_ps1_flat" | grep -Eq 'SecurityProtocol[[:space:]]*=[[:space:]]*\[Net\.ServicePointManager\]::SecurityProtocol[[:space:]]*-bor'; then + bad 'the TLS floor OR-s onto the default SecurityProtocol (SSL3/TLS1.0/1.1 stay advertised)' +elif printf '%s' "$_ps1_flat" | grep -Eq 'ServicePointManager\]::SecurityProtocol[[:space:]]*=[[:space:]]*\[Net\.SecurityProtocolType\]::Tls12'; then + ok 'the TLS floor assigns Tls12 directly (weak protocols dropped)' +else + bad 'no assigned TLS 1.2 floor found in the installer' +fi + +# ── 6. behavioural tier ───────────────────────────────────────────────────── # pwsh is preinstalled on GitHub-hosted ubuntu runners. If it is missing we # cannot tell whether the helpers behave, and "cannot tell" is a finding, not a # pass (CLAUDE.md rule 3). Set ALLOW_NO_PWSH=1 to downgrade it on a dev box