Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/aw/actions-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"version": "v7.0.1",
"sha": "043fb46d1a93c77aae656e7c1c64a875d1fc6a0a"
},
"github/gh-aw-actions/setup-cli@v0.86.2": {
"repo": "github/gh-aw-actions/setup-cli",
"version": "v0.86.2",
"sha": "6aab9e5b5c91c615506061f09bedd81a23babe3c"
},
"github/gh-aw-actions/setup@v0.86.2": {
"repo": "github/gh-aw-actions/setup",
"version": "v0.86.2",
Expand Down
15 changes: 15 additions & 0 deletions .github/scripts/TestPrepareVallyEvaluation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,21 @@ def test_comment_posting_cannot_erase_evaluator_verdict
assert_match(/retries:\s+3/, post_comment)
end

def test_pr_content_checkouts_explicitly_accept_fork_refs_without_credentials
skip "skill-validation workflow not supplied" unless SKILL_VALIDATION_WORKFLOW

workflow = File.read(SKILL_VALIDATION_WORKFLOW)
checkouts = workflow.scan(
/ - name: Checkout PR content\n.*?(?=\n - name:|\n [a-zA-Z0-9_-]+:|\z)/m
)

assert_equal 4, checkouts.length
checkouts.each do |checkout|
assert_match(/persist-credentials:\s+false/, checkout)
assert_match(/allow-unsafe-pr-checkout:\s+true/, checkout)
end
end

def test_rejects_vcs_metadata_destination
write_fixture("fixture.txt")
write_spec(
Expand Down
74 changes: 74 additions & 0 deletions .github/scripts/Validate-CiScanManifest.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,68 @@ Describe 'CI scanner issue payload gate' {
$plan.issues[0].Body.Contains('runoniOS_MauiReleaseTrimFull') | Should -BeFalse
}

It 'canonicalizes apostrophes from the exact production test fingerprint' {
$productionFingerprint = "ci-scan|main|maui-pr-devicetests|collectionview header footer doesn't leak|leak test failed|maccatalyst"
$canonicalFingerprint = 'ci-scan|main|maui-pr-devicetests|collectionview header footer doesnt leak|leak test failed|maccatalyst'
$body = (New-TestBody -Pipeline 'maui-pr-devicetests' -BuildId 123457).
Replace('- **Branch**: net11.0', '- **Branch**: main')
$manifest = New-CompleteManifest
$manifest.pipelines[1].signatures = @(
(New-TestSignature `
-Pipeline 'maui-pr-devicetests' `
-BuildId 123457 `
-SourceLogIds @(2001) `
-Fingerprint $productionFingerprint `
-Body $body)
)
$evidenceRoot = New-DefaultEvidenceRoot
New-TestEvidence `
-Root $evidenceRoot `
-Pipeline 'maui-pr-devicetests' `
-BuildId 123457 `
-LogId 2001
$expectedBuilds = New-ExpectedBuilds `
-MainResult 'succeeded' `
-MainFailedRecordCount 0 `
-MainRequiredLogIds @()
$expectedBuilds[1].result = 'failed'
$expectedBuilds[1].failed_record_count = 1
$expectedBuilds[1].required_log_ids = @(2001)
$expectedBuilds[1].failed_leaf_log_ids = @(2001)

$plan = Test-CiScanManifest `
-Manifest $manifest `
-ExpectedBuilds $expectedBuilds `
-TrustedEvidencePath $evidenceRoot `
-ScannerId 'ci-scan'

$plan.pipelines[1].signatures[0].fingerprint | Should -BeExactly $canonicalFingerprint
$plan.issues[0].Fingerprint | Should -BeExactly $canonicalFingerprint
$plan.issues[0].Body |
Should -Match "(?m)^<!-- ci-scan-fingerprint: $([regex]::Escape($canonicalFingerprint)) -->$"
}

It 'applies the fingerprint length limit after apostrophe canonicalization' {
$prefix = 'ci-scan-net11|net11.0|maui-pr|'
$suffix = '|assertion failed|windows'
$scenario = [string]::new([char]'a', 512 - $prefix.Length - $suffix.Length)
$canonicalFingerprint = $prefix + $scenario + $suffix
$productionFingerprint = $prefix + "'" + [char]0x2018 + [char]0x2019 + $scenario + $suffix
$manifest = New-CompleteManifest -MainSignatures @(
(New-TestSignature -Fingerprint $productionFingerprint)
)

$productionFingerprint.Length | Should -BeGreaterThan 512
$canonicalFingerprint.Length | Should -Be 512

$plan = Test-CiScanManifest `
-Manifest $manifest `
-TrustedEvidencePath (New-DefaultEvidenceRoot)

$plan.pipelines[0].signatures[0].fingerprint | Should -BeExactly $canonicalFingerprint
$plan.issues[0].Fingerprint | Should -BeExactly $canonicalFingerprint
}

It 'rejects fingerprints that collide after trusted case canonicalization' {
$productionFingerprint = 'ci-scan|main|maui-pr|runoniOS_MauiReleaseTrimFull|ios-simulator-boot-timeout|ios-simulator-64'
$canonicalFingerprint = $productionFingerprint.ToLowerInvariant()
Expand All @@ -506,6 +568,18 @@ Describe 'CI scanner issue payload gate' {
Should -Throw "*Duplicate fingerprint '$canonicalFingerprint'*"
}

It 'rejects fingerprints that collide after apostrophe canonicalization' {
$withApostrophe = "ci-scan-net11|net11.0|maui-pr|test doesn't leak|assertion failed|windows"
$canonicalFingerprint = 'ci-scan-net11|net11.0|maui-pr|test doesnt leak|assertion failed|windows'
$manifest = New-CompleteManifest -MainSignatures @(
(New-TestSignature -Fingerprint $withApostrophe -Disposition 'existing' -IssueNumber 36827),
(New-TestSignature -Fingerprint $canonicalFingerprint -Disposition 'existing' -IssueNumber 36828)
)

{ Test-CiScanManifest -Manifest $manifest } |
Should -Throw "*Duplicate fingerprint '$canonicalFingerprint'*"
}

<#
A fingerprint is embedded verbatim in the canonical marker, but the marker is
matched AFTER ConvertTo-SafeIssueBody neutralizes the body. A GitHub issue/PR URL
Expand Down
16 changes: 13 additions & 3 deletions .github/scripts/Validate-CiScanManifest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -601,16 +601,26 @@ function Assert-ValidFingerprint {
[Parameter(Mandatory = $true)][object]$ScannerConfig
)

if ($Fingerprint.Length -gt 512) {
# Apostrophes in test names carry no identity information and cannot be
# represented in the publisher-owned HTML marker alphabet. Normalize only
# the common apostrophe code points, then retain the strict safety gate for
# every other unsupported character.
$normalizedFingerprint = $Fingerprint.
Replace("'", '').
Replace([string][char]0x2018, '').
Replace([string][char]0x2019, '')

if ($normalizedFingerprint.Length -gt 512) {
throw 'Fingerprint exceeds 512 characters.'
}
if ($Fingerprint -cnotmatch '^[A-Za-z0-9][A-Za-z0-9 ._:/+()\-|]*$') {

if ($normalizedFingerprint -cnotmatch '^[A-Za-z0-9][A-Za-z0-9 ._:/+()\-|]*$') {
throw "Fingerprint contains unsafe characters."
}

# Casing is not a trust decision. Canonicalize the accepted ASCII alphabet at
# the trusted boundary so prompt compliance cannot determine marker identity.
$canonicalFingerprint = $Fingerprint.ToLowerInvariant()
$canonicalFingerprint = $normalizedFingerprint.ToLowerInvariant()
$parts = @($canonicalFingerprint.Split('|'))
if ($parts.Count -ne 6 -or @($parts | Where-Object { [string]::IsNullOrWhiteSpace($_) }).Count -gt 0) {
throw 'Fingerprint must contain exactly six non-empty pipe-delimited fields.'
Expand Down
115 changes: 112 additions & 3 deletions .github/scripts/Validate-CiScanPublisher.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ Describe 'CI scanner compiled publisher invariants: <_.Name>' -ForEach $script:D
It 'separates historical issue evidence from current frozen recurrence proof' {
$script:TwinLock | Should -Match 'historical proof from the run'
$script:TwinLock | Should -Match 'canonical-fingerprint-and-distinctive-current-evidence'
$script:TwinLock | Should -Match 'canonical-stable-identity-and-distinctive-current-evidence'
$script:TwinLock | Should -Match 'hasDistinctiveRecurrencePattern'
$script:TwinLock | Should -Match 'hasHistoricalErrorPattern'
$script:TwinLock | Should -Match 'assertUnambiguousCanonicalRecurrence'
Expand Down Expand Up @@ -863,8 +864,7 @@ issuesToCreate.push(issue);
$publisherSource = $publisherSource.Replace($needle, $replacement)
}
if ($RequireCurrentEvidenceInExistingBody) {
$pattern = '(?m)^(?<indent>\s*)getEvidenceProof\(entry\);\r?\n' +
'\k<indent>const exactMarker = `<!-- ci-scan-fingerprint: \$\{entry\.fingerprint\} -->`;'
$pattern = '(?m)^(?<indent>\s*)getEvidenceProof\(entry\);\r?$'
[regex]::Matches($publisherSource, $pattern).Count | Should -Be 1
$publisherSource = [regex]::Replace(
$publisherSource,
Expand All @@ -876,7 +876,6 @@ issuesToCreate.push(issue);
"${indent}if (!hasTrustedEvidenceLine(body, currentEvidenceProof.hashes)) {"
"${indent} throw new Error(``Existing issue #`${entry.issue_number} does not contain a full current trusted evidence line.``);"
"${indent}}"
"${indent}const exactMarker = ``<!-- ci-scan-fingerprint: `${entry.fingerprint} -->``;"
) -join "`n"
})
}
Expand Down Expand Up @@ -1415,6 +1414,116 @@ Unique current raw failure line
@($result.created).Count | Should -Be 0
}

It 'reuses the exact issue 37559 marker across category and platform separator drift' {
$evidenceLine = '2026-08-16T16:43:15.9839713Z Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$matchPattern = 'Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$plan = New-ExistingPlan `
-IssueNumber 37559 `
-EvidenceLine $evidenceLine `
-FingerprintIdentity 'layoutshouldbecorrectonfirstnavigation' `
-Pipeline 'maui-pr-uitests' `
-FailureCategory 'visual-comparison-failure' `
-Platform 'android-api-36' `
-MatchPattern $matchPattern
$entry = $plan.pipelines[2].signatures[0]
$historicalFingerprint = $entry.fingerprint.Replace(
'|visual-comparison-failure|android-api-36',
'|snapshot different than baseline|android api 36')
$existing = New-ExistingIssueStub -Number 37559 -Body @"
<!-- ci-scan-fingerprint: $historicalFingerprint -->
<!-- ci-scan-match-count: 2 hits in failure.log -->
<!-- ci-scan-evidence-key: $($entry.evidence_key) -->
- **Pipeline**: maui-pr-uitests
## Error Message
$evidenceLine
"@

$result = Invoke-Publisher `
-Plan $plan `
-ExistingIssues @{ '37559' = $existing }

$result.ok | Should -BeTrue
$result.error | Should -BeNullOrEmpty
@($result.created).Count | Should -Be 0
}

It 'rejects a historical marker whose stable platform identity changed' {
$evidenceLine = '2026-08-16T16:43:15.9839713Z Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$matchPattern = 'Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$plan = New-ExistingPlan `
-IssueNumber 37559 `
-EvidenceLine $evidenceLine `
-FingerprintIdentity 'layoutshouldbecorrectonfirstnavigation' `
-Pipeline 'maui-pr-uitests' `
-FailureCategory 'visual-comparison-failure' `
-Platform 'android-api-36' `
-MatchPattern $matchPattern
$entry = $plan.pipelines[2].signatures[0]
$historicalFingerprint = $entry.fingerprint.Replace(
'|visual-comparison-failure|android-api-36',
'|snapshot different than baseline|ios')
$existing = New-ExistingIssueStub -Number 37559 -Body @"
<!-- ci-scan-fingerprint: $historicalFingerprint -->
<!-- ci-scan-match-count: 2 hits in failure.log -->
<!-- ci-scan-evidence-key: $($entry.evidence_key) -->
- **Pipeline**: maui-pr-uitests
## Error Message
$evidenceLine
"@

$result = Invoke-Publisher `
-Plan $plan `
-ExistingIssues @{ '37559' = $existing }

$result.ok | Should -BeFalse
$result.error | Should -BeLike '*different or malformed trusted markers*'
@($result.created).Count | Should -Be 0
}

It 'rejects multiple current category aliases that claim the same canonical owner' {
$evidenceLine = '2026-08-16T16:43:15.9839713Z Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$matchPattern = 'Snapshot different than baseline: LayoutShouldBeCorrectOnFirstNavigation.png (6.01% difference)'
$plan = New-ExistingPlan `
-IssueNumber 37559 `
-EvidenceLine $evidenceLine `
-FingerprintIdentity 'layoutshouldbecorrectonfirstnavigation' `
-Pipeline 'maui-pr-uitests' `
-FailureCategory 'visual-comparison-failure' `
-Platform 'android-api-36' `
-MatchPattern $matchPattern
$entry = $plan.pipelines[2].signatures[0]
$historicalFingerprint = $entry.fingerprint.Replace(
'|visual-comparison-failure|android-api-36',
'|snapshot different than baseline|android api 36')
$secondEntry = [pscustomobject]@{
fingerprint = $entry.fingerprint.Replace(
'|visual-comparison-failure|',
'|snapshot-comparison-failure|')
disposition = 'existing'
issue_number = 37559
match_pattern = $entry.match_pattern
evidence_key = $entry.evidence_key
evidence_line_hashes = $entry.evidence_line_hashes
}
$plan.pipelines[2].signatures = @($entry, $secondEntry)
$existing = New-ExistingIssueStub -Number 37559 -Body @"
<!-- ci-scan-fingerprint: $historicalFingerprint -->
<!-- ci-scan-match-count: 2 hits in failure.log -->
<!-- ci-scan-evidence-key: $($entry.evidence_key) -->
- **Pipeline**: maui-pr-uitests
## Error Message
$evidenceLine
"@

$result = Invoke-Publisher `
-Plan $plan `
-ExistingIssues @{ '37559' = $existing }

$result.ok | Should -BeFalse
$result.error | Should -BeLike '*Existing canonical fingerprint*referenced by both*'
@($result.created).Count | Should -Be 0
}

It 'fails closed when canonical recurrence has duplicate open marker owners' {
$plan = New-ExistingPlan -FingerprintIdentity 'unique current'
$entry = $plan.pipelines[0].signatures[0]
Expand Down
Loading
Loading