{"record":{"id":"79cc3c5e26aff1e0","repo":"stablyai/orca","slug":"powershell-returned-malformed-signature-json-er","errorCode":null,"errorMessage":"PowerShell returned malformed signature JSON: ${error.message}","messagePattern":"PowerShell returned malformed signature JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/verify-windows-inner-signature.mjs","lineNumber":72,"sourceCode":"    return []\n  }\n\n  return value\n    .split(/[\\r\\n,;]+/u)\n    .map(normalizeThumbprint)\n    .filter(Boolean)\n}\n\nexport function parseSignatureJson(stdout) {\n  const trimmed = typeof stdout === 'string' ? stdout.trim() : ''\n  if (trimmed === '') {\n    throw new Error('PowerShell did not return signature JSON.')\n  }\n\n  try {\n    return JSON.parse(trimmed)\n  } catch (error) {\n    throw new Error(`PowerShell returned malformed signature JSON: ${error.message}`)\n  }\n}\n\nexport function classifySignature(signature, options = {}) {\n  const expectedSigners = options.expectedSigners ?? parseExpectedSigners()\n  const expectedThumbprints = options.expectedThumbprints ?? parseExpectedThumbprints()\n  const status = typeof signature?.status === 'string' ? signature.status : ''\n  const signerSubject = normalizeSignerSubject(signature?.signerSubject)\n  const signerThumbprint = normalizeThumbprint(signature?.signerThumbprint)\n  const subjectAllowed = expectedSigners.includes(signerSubject)\n  const thumbprintAllowed =\n    expectedThumbprints.length > 0 &&\n    signerThumbprint !== '' &&\n    expectedThumbprints.includes(signerThumbprint)\n\n  if (status !== 'Valid') {\n    return {\n      ok: false,","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/verify-windows-inner-signature.mjs#L54-L90","documentation":"Thrown by parseSignatureJson() when PowerShell returns non-empty stdout but JSON.parse() fails on it. The original JSON.parse error message is appended. This indicates PowerShell produced output, but it is not valid JSON — partial output, interleaved text, or an encoding issue.","triggerScenarios":"getPowerShellSignatureJson() returns stdout that trim()s to a non-empty string but JSON.parse throws. Caused by: PowerShell writing a progress message or banner to stdout before the JSON; ConvertTo-Json truncating due to depth limits; BOM or encoding artifacts breaking the parse; the script hitting an error that writes a partial object.","commonSituations":"A PowerShell profile or module auto-load injecting text into stdout (the script uses -NoProfile to prevent this, but module auto-loading can still occur); ConvertTo-Json depth default (2) being too shallow for nested certificate objects; UTF-16 BOM from PowerShell output encoding; a Windows update changing Get-AuthenticodeSignature output shape.","solutions":["Capture the raw stdout (the error message includes it) and inspect what precedes or breaks the JSON structure.","If the issue is ConvertTo-Json depth, add -Depth 10 to the ConvertTo-Json call in POWERSHELL_SIGNATURE_SCRIPT.","If extra text leaks into stdout, ensure -NoProfile is effective and no module auto-load writes to stdout; consider piping through Out-String or using $PSStyle to disable progress.","Set [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 in the script to avoid encoding issues."],"exampleFix":"// before: depth-limited JSON truncates nested cert data\n} | ConvertTo-Json -Compress\n\n// after: explicit depth + UTF-8 output encoding\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n} | ConvertTo-Json -Compress -Depth 10","handlingStrategy":"try-catch","validationCode":"function preflightJsonOutput(executablePath) {\n  const result = spawnSync('pwsh', ['-NoProfile', '-Command',\n    '[pscustomobject]@{ ok = $true } | ConvertTo-Json -Compress -Depth 10'],\n    { encoding: 'utf8' }\n  )\n  try {\n    JSON.parse(result.stdout)\n  } catch {\n    throw new Error('PowerShell cannot produce valid JSON — check encoding/profile settings')\n  }\n}","typeGuard":"function isParsableJson(value) {\n  if (typeof value !== 'string' || value.trim() === '') return false\n  try { JSON.parse(value); return true } catch { return false }\n}","tryCatchPattern":"try {\n  return parseSignatureJson(stdout)\n} catch (err) {\n  if (err.message.includes('malformed signature JSON')) {\n    // Attempt to extract JSON from mixed output\n    const match = stdout.match(/\\{[\\s\\S]*\\}/u)\n    if (match) {\n      return JSON.parse(match[0])\n    }\n  }\n  throw err\n}","preventionTips":["Add -Depth 10 to ConvertTo-Json to avoid truncation of nested certificate objects.","Set [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 in the PowerShell script.","Keep -NoProfile to prevent profile scripts from polluting stdout."],"tags":["windows","powershell","json","authenticode","signature"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}