{ "_schema_version": "1.0", "_description": "PSProxmoxVE stable findings ledger. IDs are permanent (F001, F002...). Resolved findings are never deleted — they are marked resolved with evidence. If a finding reappears, it is marked regressed and retains its original ID.", "last_updated": "2026-03-23", "last_scan_date": "2026-03-23", "counters": { "next_id": 84, "total_open": 12, "total_resolved": 70, "total_regressed": 0, "open": 12, "resolved": 70, "wont_fix": 1 }, "findings": [ { "id": "F001", "title": "No PSGallery publish workflow", "category": "psgallery", "severity": "critical", "status": "resolved", "first_detected": "2026-03-19", "files": [ ".github/workflows/" ], "description": "No CI/CD workflow for publishing to PSGallery. Cannot automate releases.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "C1", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "publish.yml workflow added, triggered on tag push with Publish-Module and GitHub Release creation", "verified_by": "scan" } }, { "id": "F002", "title": "README says 'not PSGallery'", "category": "psgallery", "severity": "critical", "status": "resolved", "first_detected": "2026-03-19", "files": [ "README.md" ], "description": "README installation section says module is not on PSGallery, contradicting publication goal.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "C2", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "README updated with Install-Module PSProxmoxVE instructions", "verified_by": "scan" } }, { "id": "F003", "title": "No ReleaseNotes in manifest PSData", "category": "psgallery", "severity": "critical", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/PSProxmoxVE.psd1" ], "description": "PSGallery strongly recommends ReleaseNotes in module manifest PSData section.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "C3", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "ReleaseNotes added to PSData section of manifest", "verified_by": "scan" } }, { "id": "F004", "title": "No HelpMessage on any cmdlet parameter", "category": "code_quality", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "Get-Help shows no parameter descriptions because HelpMessage attribute is missing on all [Parameter] attributes.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H1", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "HelpMessage present on virtually all parameters across all 83 cmdlets", "verified_by": "scan" } }, { "id": "F005", "title": "No WriteVerbose in cmdlets except Connection", "category": "code_quality", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "Users cannot see which API calls are being made. Only Connection cmdlets use WriteVerbose.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H2", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "WriteVerbose used extensively throughout all cmdlets", "verified_by": "scan" } }, { "id": "F006", "title": "Missing CONTRIBUTING.md", "category": "community", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "CONTRIBUTING.md" ], "description": "No contributor guide with dev setup, coding standards, test instructions, or PR process.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H3", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "CONTRIBUTING.md created with prerequisites, building, tests, coding standards, PR process", "verified_by": "scan" } }, { "id": "F007", "title": "Missing SECURITY.md", "category": "community", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "SECURITY.md" ], "description": "No vulnerability disclosure policy.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H4", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "SECURITY.md created with vulnerability disclosure policy and 48h response SLA", "verified_by": "scan" } }, { "id": "F008", "title": "No WriteWarning on -SkipCertificateCheck", "category": "security", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Connection/ConnectPveServerCmdlet.cs" ], "description": "Users may not realize they are disabling TLS certificate verification.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H5", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "WriteWarning emitted with man-in-the-middle advisory when SkipCertificateCheck is used", "verified_by": "scan" } }, { "id": "F009", "title": "Reset-PveVm uses hardcoded verb string literal", "category": "code_quality", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/ResetPveVmCmdlet.cs" ], "description": "Reset-PveVm uses [Cmdlet(\"Reset\", ...)] instead of VerbsCommon.Reset, inconsistent with all other cmdlets.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H6", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Now uses VerbsCommon.Reset constant", "verified_by": "scan" }, "decisions_ref": "D012" }, { "id": "F010", "title": "Missing GitHub issue and PR templates", "category": "community", "severity": "high", "status": "resolved", "first_detected": "2026-03-19", "files": [ ".github/ISSUE_TEMPLATE/", ".github/pull_request_template.md" ], "description": "No structured issue reporting or PR process templates.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "H8", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Bug report (YAML), feature request (YAML), and PR template added", "verified_by": "scan" } }, { "id": "F011", "title": "Stop-PveVm and Reset-PveVm lack ConfirmImpact.High", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/StopPveVmCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Vms/ResetPveVmCmdlet.cs" ], "description": "Stopping or resetting VMs can cause data loss but these cmdlets don't prompt for confirmation by default.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M1", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "ConfirmImpact.High added to both Stop-PveVm and Reset-PveVm", "verified_by": "scan" }, "decisions_ref": "D007" }, { "id": "F012", "title": "No ValidateRange on VmId parameters", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "PVE requires VMID 100-999999999 but no ValidateRange attribute enforces this.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M2", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "ValidateRange(100, 999999999) added to all VmId parameters", "verified_by": "scan" }, "decisions_ref": "D011" }, { "id": "F013", "title": "Container snapshots not supported", "category": "api_coverage", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/" ], "description": "Snapshots are only implemented for VMs, not LXC containers, despite PVE supporting both.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M3", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "4 container snapshot cmdlets added: Get/New/Remove/Restore-PveContainerSnapshot", "verified_by": "scan" } }, { "id": "F014", "title": "No integration tests for network modifications", "category": "testing", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "tests/PSProxmoxVE.Tests/Integration/" ], "description": "Network CRUD (create/modify/delete/apply) is tested only at Pester level, not end-to-end.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M4", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Integration tests added for network create/modify/delete/apply with revert", "verified_by": "scan" } }, { "id": "F015", "title": "No CODE_OF_CONDUCT.md", "category": "community", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "CODE_OF_CONDUCT.md" ], "description": "Expected for open-source projects to establish community standards.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M5", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Contributor Covenant v2.1 adopted", "verified_by": "scan" } }, { "id": "F016", "title": "No .gitattributes file", "category": "community", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ ".gitattributes" ], "description": "Line ending consistency across platforms not enforced.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M6", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": ".gitattributes added with line ending normalization, csharp diff, binary markers", "verified_by": "scan" } }, { "id": "F017", "title": "CS1591 suppressed in Core project", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE.Core/PSProxmoxVE.Core.csproj" ], "description": "Public API lacks XML documentation because CS1591 warning is suppressed.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M7", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "CS1591 no longer suppressed, XML doc comments added to all public types", "verified_by": "scan" } }, { "id": "F018", "title": "No badges in README", "category": "psgallery", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "README.md" ], "description": "No build status, PSGallery version, or license badges to improve discoverability and trust.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M8", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Build, Unit Tests, License badges added to README", "verified_by": "scan" } }, { "id": "F019", "title": "CHANGELOG has only [Unreleased] section", "category": "psgallery", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "CHANGELOG.md" ], "description": "No versioned release entries in CHANGELOG, no release history.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M9", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "0.1.0-preview versioned entry added to CHANGELOG", "verified_by": "scan" } }, { "id": "F020", "title": "Invoke-PveVmGuestExec lacks ShouldProcess", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/InvokePveVmGuestExecCmdlet.cs" ], "description": "Executes commands inside a VM (a mutating operation) but does not implement SupportsShouldProcess.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "M10", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "SupportsShouldProcess added; all destructive/mutating cmdlets now implement it", "verified_by": "scan" } }, { "id": "F021", "title": "No IconUri in manifest PSData", "category": "psgallery", "severity": "low", "status": "open", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/PSProxmoxVE.psd1" ], "description": "Improves PSGallery listing appearance. Cosmetic only.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L1", "status": "new" }, { "scan_date": "2026-03-21", "local_id": "L1", "status": "open" }, { "scan_date": "2026-03-22", "local_id": "L1", "status": "open" }, { "scan_date": "2026-03-22", "local_id": "L1", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F022", "title": "No online help (MAML/platyPS)", "category": "psgallery", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/" ], "description": "Get-Help -Online does not work. No MAML help file for cmdlet documentation.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L2", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "MAML help file (PSProxmoxVE.dll-Help.xml) present with 75 cmdlet documentation files in docs/cmdlets/", "verified_by": "scan" } }, { "id": "F023", "title": "No firewall cmdlets", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Firewall/" ], "description": "No cmdlets for creating/managing firewall rules at cluster, node, or VM level. Critical gap for security automation.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L3", "status": "new" }, { "scan_date": "2026-03-21", "local_id": "H1", "status": "open" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "21 cluster-level firewall cmdlets added covering rules, groups, aliases, IP sets, options, and refs", "verified_by": "self-reported" } }, { "id": "F024", "title": "No backup/vzdump cmdlets", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Backup/" ], "description": "Essential for DR automation. No cmdlets for creating backups, managing schedules, or restoring.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L4", "status": "new" }, { "scan_date": "2026-03-21", "local_id": "H2", "status": "open" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "6 backup cmdlets added: New-PveBackup, Get/New/Set/Remove-PveBackupJob, Get-PveBackupInfo", "verified_by": "self-reported" } }, { "id": "F025", "title": "No pool management cmdlets", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Pools/" ], "description": "Required for multi-tenant environments. No cmdlets for creating/managing resource pools.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L5", "status": "new" }, { "scan_date": "2026-03-21", "local_id": "M2", "status": "open" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "4 pool cmdlets added: Get/New/Set/Remove-PvePool", "verified_by": "self-reported" } }, { "id": "F026", "title": "new Random() used for multipart boundary generation", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE.Core/Client/PveHttpClient.cs" ], "description": "Not cryptographically secure. Low risk for multipart boundaries but could use RandomNumberGenerator.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L6", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "RandomNumberGenerator now used for boundary generation", "verified_by": "scan" } }, { "id": "F027", "title": "No alias support in module", "category": "psgallery", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/PSProxmoxVE.psd1" ], "description": "Some users prefer short aliases for frequently used cmdlets.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L7", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "7 aliases defined in module manifest AliasesToExport", "verified_by": "scan" } }, { "id": "F028", "title": "No tagged releases or GitHub Releases", "category": "psgallery", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ ".github/workflows/publish.yml" ], "description": "No GitHub Releases configured, no release workflow, no tagged releases in git history.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L8", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "publish.yml creates GitHub Releases via softprops/action-gh-release on tag push", "verified_by": "scan" } }, { "id": "F029", "title": "No container migration cmdlet", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/" ], "description": "VMs have Move-PveVm for migration but containers have no equivalent.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L9", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "Move-PveContainer cmdlet added for container migration", "verified_by": "scan" } }, { "id": "F030", "title": "No SDN subnet management cmdlets", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-19", "files": [ "src/PSProxmoxVE/Cmdlets/Network/" ], "description": "SDN zones and VNets exist but subnets are missing.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": "L10", "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-21", "evidence": "3 SDN subnet cmdlets added: Get/New/Remove-PveSdnSubnet", "verified_by": "scan" } }, { "id": "F031", "title": "Hardcoded test password in CI workflow and Terraform", "category": "security", "severity": "low", "status": "open", "first_detected": "2026-03-19", "files": [ ".github/workflows/integration-tests.yml", "tests/infrastructure/variables.tf" ], "description": "PVE_PASSWORD: 'Testpass123!' in integration-tests.yml and variables.tf. Masked via ::add-mask::. Disposable nested test VM. Accepted risk.", "scan_history": [ { "scan_date": "2026-03-19", "local_id": null, "status": "new" }, { "scan_date": "2026-03-21", "local_id": null, "status": "open" }, { "scan_date": "2026-03-22", "local_id": "S1/S2", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F032", "title": "Infinite loop task-polling in VM snapshot and network cmdlets", "category": "code_quality", "severity": "critical", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Network/InvokePveNetworkApplyCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Snapshots/NewPveSnapshotCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Snapshots/RestorePveSnapshotCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Snapshots/RemovePveSnapshotCmdlet.cs" ], "description": "while(true) with no timeout in InvokePveNetworkApply, NewPveSnapshot, RestorePveSnapshot, RemovePveSnapshot private WaitForTask methods. Cmdlets hang forever if task stalls.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ1-CQ4", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "All four cmdlets now use TaskService.WaitForTask with timeout enforcement, failure detection, and WriteProgress support", "verified_by": "self-reported" }, "decisions_ref": "D001" }, { "id": "F033", "title": "Infinite poll loop in InvokePveVmGuestExec", "category": "code_quality", "severity": "critical", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/InvokePveVmGuestExecCmdlet.cs" ], "description": "while(true) polling exec-status with no timeout. Cmdlet hangs forever if guest exec never completes.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ5", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Added Timeout parameter with Stopwatch + TimeoutException", "verified_by": "self-reported" }, "decisions_ref": "D001" }, { "id": "F034", "title": "RemovePveRoleCmdlet missing ConfirmImpact.High", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Users/RemovePveRoleCmdlet.cs" ], "description": "Deleting roles is a significant, potentially disruptive operation but does not prompt for confirmation.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ17/M1", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "ConfirmImpact = ConfirmImpact.High added", "verified_by": "self-reported" }, "decisions_ref": "D007" }, { "id": "F035", "title": "Pool/CephPool parameter conflict in NewPveStorageCmdlet", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Storage/NewPveStorageCmdlet.cs" ], "description": "New-PveStorage allows specifying both Pool and CephPool parameters simultaneously, which is invalid.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ6", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Runtime validation added with ThrowTerminatingError if both Pool and CephPool specified", "verified_by": "self-reported" } }, { "id": "F036", "title": "Duplicated WaitForTask methods across cmdlets", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "4 VM/network cmdlets had copy-pasted private WaitForTask implementations instead of using the shared TaskService.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ7", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "All cmdlets now use TaskService.WaitForTask", "verified_by": "self-reported" }, "decisions_ref": "D001" }, { "id": "F037", "title": "~54 cmdlets missing OutputType attribute", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "Approximately 54 cmdlets lack [OutputType] attribute, degrading IntelliSense and pipeline type inference.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ9", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "All 169 cmdlets now have [OutputType] attributes", "verified_by": "self-reported" }, "decisions_ref": "D006" }, { "id": "F038", "title": "Firewall VmId defaults to 0 instead of nullable", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Firewall/" ], "description": "Firewall cmdlet VmId parameter uses int with default 0 instead of nullable int, making it impossible to distinguish unset from VM 0.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ10", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "VmId changed to nullable int pattern", "verified_by": "self-reported" }, "decisions_ref": "D011" }, { "id": "F039", "title": "Bare catch blocks in PveHttpClient, PveCmdletBase, VmService, ContainerService, GetPveVmCmdlet", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE.Core/Client/PveHttpClient.cs", "src/PSProxmoxVE/Cmdlets/PveCmdletBase.cs", "src/PSProxmoxVE.Core/Services/VmService.cs", "src/PSProxmoxVE.Core/Services/ContainerService.cs" ], "description": "Multiple bare catch {} blocks swallow exceptions silently, hiding errors and making debugging difficult.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ11-CQ14", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "All bare catches replaced with filtered catch (Exception ex) when (...) clauses that exclude OOM/SOE and are specific to PveApiException/HttpRequestException where appropriate", "verified_by": "self-reported" }, "decisions_ref": "D005" }, { "id": "F040", "title": "Broad exception catches in status polling", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/PveCmdletBase.cs", "src/PSProxmoxVE.Core/Services/VmService.cs", "src/PSProxmoxVE.Core/Services/ContainerService.cs" ], "description": "Filtered catch(Exception ex) when(...) clauses are better than bare catches but still catch broadly. Could be more specific exception types.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ8", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "CQ8/M6", "status": "open" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "report_id": "scan-4", "verified_by": "scan", "evidence": "PveCmdletBase.cs:149 uses 'when (ex is not OutOfMemoryException and not StackOverflowException)'. ContainerService.cs:44 and VmService.cs:48 filter to 'PveApiException or HttpRequestException'. All catch(Exception) blocks in cmdlets call ThrowTerminatingError (correct PS pattern). No bare catches found anywhere in src/." } }, { "id": "F041", "title": "~95 cmdlets not sealed", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "Approximately 95 cmdlet classes are not sealed, allowing unintended inheritance.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ18", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "All 169 cmdlets are now sealed", "verified_by": "self-reported" }, "decisions_ref": "D008" }, { "id": "F042", "title": "SuspendPveVmCmdlet missing ConfirmImpact.High", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/SuspendPveVmCmdlet.cs" ], "description": "Suspending a VM can cause issues but does not prompt for confirmation.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ19", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "ConfirmImpact.High added to SuspendPveVmCmdlet", "verified_by": "self-reported" }, "decisions_ref": "D007" }, { "id": "F043", "title": "RestartPveVmCmdlet missing ConfirmImpact declaration", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/RestartPveVmCmdlet.cs" ], "description": "Restarting a VM is disruptive but does not set ConfirmImpact.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ20", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "ConfirmImpact.High added to RestartPveVmCmdlet", "verified_by": "self-reported" }, "decisions_ref": "D007" }, { "id": "F044", "title": "Dual JSON serialization attributes (JsonProperty + JsonPropertyName)", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE.Core/Models/" ], "description": "Model classes have both Newtonsoft [JsonProperty] and System.Text.Json [JsonPropertyName] attributes. Only Newtonsoft is used at runtime.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ21", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "[JsonPropertyName] attributes removed, only [JsonProperty] (Newtonsoft) remains", "verified_by": "self-reported" }, "decisions_ref": "D009" }, { "id": "F045", "title": "HttpClient per-call pattern bypasses connection pooling", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/" ], "description": "38 cmdlets create new PveHttpClient per operation instead of going through services, bypassing connection pooling.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ11", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "CQ11/M1", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "IPveHttpClient interface extracted to Client/IPveHttpClient.cs. All 14 services now accept IPveHttpClient via constructor injection, enabling shared client instances. PveHttpClient implements IPveHttpClient." } }, { "id": "F046", "title": "Significant integration test coverage gaps", "category": "testing", "severity": "medium", "status": "open", "first_detected": "2026-03-21", "files": [ "tests/PSProxmoxVE.Tests/Integration/" ], "description": "Many cmdlets lack end-to-end integration tests. 64 of 169 cmdlets untested in integration as of latest scan.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "M3/M4", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "M2", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F047", "title": "Publishable projects multi-target beyond netstandard2.0", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/PSProxmoxVE.csproj", "src/PSProxmoxVE.Core/PSProxmoxVE.Core.csproj" ], "description": "Both publishable projects (PSProxmoxVE.csproj, PSProxmoxVE.Core.csproj) target netstandard2.0;net10.0;net48 but D009 requires publishable projects to target only netstandard2.0. Multi-targeting inflates the published module and may ship framework-specific assemblies unnecessarily.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ6", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "CQ6/H3", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "decisions_ref": "D010", "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "PSProxmoxVE.csproj and PSProxmoxVE.Core.csproj now target netstandard2.0 only. All #if NET48/NETSTANDARD2_0 conditionals removed from PveHttpClient.cs. build.yml restructured. Test project retains net10.0+net48." } }, { "id": "F048", "title": "Sync-over-async via GetAwaiter().GetResult()", "category": "code_quality", "severity": "medium", "status": "wont_fix", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE.Core/" ], "description": "~216 call sites use .GetAwaiter().GetResult(). Standard for PS binary modules but carries theoretical deadlock risk. Accepted tradeoff for PS 5.1 compatibility.", "notes": "Accepted tradeoff: PowerShell binary modules targeting netstandard2.0 for PS 5.1 Desktop compatibility have no async pipeline. .GetAwaiter().GetResult() is the standard pattern used by all major PS binary modules. No deadlock risk in practice because PveHttpClient uses ConfigureAwait(false).", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ7", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "CQ7", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "wont_fix" } ] }, { "id": "F049", "title": "Auth header names are magic strings", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE.Core/Client/PveHttpClient.cs" ], "description": "Auth header names (PVEAPIToken=, CSRFPreventionToken) are inline string literals instead of named constants.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "CQ2/CQ22", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Extracted to const string ApiTokenPrefix and CsrfHeaderName fields", "verified_by": "self-reported" }, "decisions_ref": "D013" }, { "id": "F050", "title": "URL-encode snapshot/node names in API paths", "category": "security", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE.Core/Services/SnapshotService.cs", "src/PSProxmoxVE.Core/Services/ContainerService.cs" ], "description": "Snapshot names and node names in URL paths are not URL-encoded. Low risk as values come from validated/system sources, but defense-in-depth recommends encoding.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "S1/M5", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Uri.EscapeDataString() now used consistently across all services", "verified_by": "self-reported" }, "decisions_ref": "D003" }, { "id": "F051", "title": "SetPveVmGuestPassword uses plain string not SecureString", "category": "security", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Vms/SetPveVmGuestPasswordCmdlet.cs" ], "description": "Guest password parameter is a plain string instead of SecureString, inconsistent with Connect-PveServer's credential handling.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "S1", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Now uses SecureString with Marshal.SecureStringToGlobalAllocUnicode + ZeroFreeGlobalAllocUnicode in try/finally", "verified_by": "self-reported" }, "decisions_ref": "D002" }, { "id": "F052", "title": "Debug script contains hardcoded API token and IP", "category": "security", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "debug/Capture-UploadDiff.ps1" ], "description": "debug/Capture-UploadDiff.ps1 contained a hardcoded API token and PVE host IP.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "S2", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "Replaced with placeholder tokens: , @!=", "verified_by": "self-reported" } }, { "id": "F053", "title": "HA subsystem 0% coverage", "category": "api_coverage", "severity": "low", "status": "open", "first_detected": "2026-03-21", "files": [], "description": "21 HA endpoints + 5 new PVE 9.0 endpoints. Essential for production clusters. Resources, groups, status, and rules.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "L3", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "H1", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F054", "title": "Ceph subsystem 0% coverage", "category": "api_coverage", "severity": "low", "status": "open", "first_detected": "2026-03-21", "files": [], "description": "40 endpoints for OSD, MON, pool, status operations. Critical for hyperconverged infrastructure.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "L3", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "H2", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F055", "title": "Access groups and domains cmdlets missing", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Users/" ], "description": "No cmdlets for /access/groups or /access/domains CRUD. Useful for LDAP/AD integration.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "L4", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "8 cmdlets added: Get/New/Set/Remove-PveGroup and Get/New/Set/Remove-PveDomain plus Set-PvePassword", "verified_by": "self-reported" } }, { "id": "F056", "title": "PSGallery version badge missing", "category": "psgallery", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "README.md" ], "description": "README should show PSGallery version badge after first publish.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "L5", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "PSGallery badge present in README badges", "verified_by": "self-reported" } }, { "id": "F057", "title": "SDN IPAM/DNS/Controller cmdlets missing", "category": "api_coverage", "severity": "low", "status": "resolved", "first_detected": "2026-03-21", "files": [ "src/PSProxmoxVE/Cmdlets/Network/" ], "description": "SDN zones/VNets/subnets covered but IPAM, DNS, and controller management missing.", "scan_history": [ { "scan_date": "2026-03-21", "local_id": "L6", "status": "new" }, { "scan_date": "2026-03-22", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-22", "evidence": "12 cmdlets added: Get/New/Remove/Set for SdnIpam, SdnDns, SdnController plus Invoke-PveSdnApply", "verified_by": "self-reported" } }, { "id": "F058", "title": "Infinite loop task-polling in container snapshot and storage cmdlets", "category": "code_quality", "severity": "critical", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/NewPveContainerSnapshotCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Containers/RemovePveContainerSnapshotCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Containers/RestorePveContainerSnapshotCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Storage/InvokePveStorageDownloadCmdlet.cs", "src/PSProxmoxVE/Cmdlets/Storage/SendPveFileCmdlet.cs" ], "description": "while(true) with no timeout in NewPveContainerSnapshot, RemovePveContainerSnapshot, RestorePveContainerSnapshot, InvokePveStorageDownload, and SendPveFile. Same anti-pattern that was fixed in VM snapshot cmdlets. Cmdlets hang forever if task stalls.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ1-CQ5/C1", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "C1", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "decisions_ref": "D001", "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "All 5 cmdlets now use TaskService.WaitForTask (NewPveContainerSnapshotCmdlet.cs:67, RemovePveContainerSnapshotCmdlet.cs:59, RestorePveContainerSnapshotCmdlet.cs:62, InvokePveStorageDownloadCmdlet.cs:74, SendPveFileCmdlet.cs:134). No while(true) task-polling loops remain in any of these files." } }, { "id": "F059", "title": "VM/CT-level firewall 0% coverage", "category": "api_coverage", "severity": "medium", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "~44 combined endpoints for per-VM and per-CT firewall rules. Cluster-level is covered (21 cmdlets) but VM/CT-level is not.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "M3", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F060", "title": "Cluster config 0% coverage", "category": "api_coverage", "severity": "medium", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "10 endpoints for cluster create/join/node management. Fundamental for multi-node cluster automation.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "M4", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F061", "title": "PVE 9.0 endpoints 0% coverage", "category": "api_drift", "severity": "medium", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "42 new PVE 9.0 endpoints available (HA rules, SDN fabrics, bulk actions, OCI registry). None implemented.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "M5", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F062", "title": "RestartPveContainerCmdlet missing ConfirmImpact.High", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/RestartPveContainerCmdlet.cs" ], "description": "RestartPveVmCmdlet has ConfirmImpact.High but the container counterpart does not. Inconsistent.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ9", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "decisions_ref": "D007", "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "RestartPveContainerCmdlet.cs:15 now has ConfirmImpact = ConfirmImpact.High, matching RestartPveVmCmdlet." } }, { "id": "F063", "title": "SuspendPveContainerCmdlet missing ConfirmImpact.High", "category": "code_quality", "severity": "medium", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/SuspendPveContainerCmdlet.cs" ], "description": "SuspendPveVmCmdlet has ConfirmImpact.High but the container counterpart does not. Inconsistent.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ10", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "decisions_ref": "D007", "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "SuspendPveContainerCmdlet.cs:14 now has ConfirmImpact = ConfirmImpact.High, matching SuspendPveVmCmdlet." } }, { "id": "F064", "title": "System.Management.Automation pinned to 7.4.0", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE/PSProxmoxVE.csproj" ], "description": "Consider updating when migrating to .NET 10 target framework.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ12/L2", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "decisions_ref": "D010", "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "net10.0 ItemGroup with System.Management.Automation 7.5.0 removed from PSProxmoxVE.csproj as part of F047 netstandard2.0-only migration. Publishable project now uses PowerShellStandard.Library 5.1.1 unconditionally." } }, { "id": "F065", "title": "No config.yml for issue templates", "category": "community", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ ".github/ISSUE_TEMPLATE/" ], "description": "No .github/ISSUE_TEMPLATE/config.yml to control blank issue creation.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L3", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": ".github/ISSUE_TEMPLATE/config.yml exists with blank_issues_enabled: false and contact_links to Discussions." } }, { "id": "F066", "title": "No CODEOWNERS file", "category": "community", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ "CODEOWNERS" ], "description": "Documents ownership for PR auto-assignment. Low priority for single-maintainer project.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L4", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "CODEOWNERS file exists (15 bytes) in repo root." } }, { "id": "F067", "title": "Disk management 0% coverage", "category": "api_coverage", "severity": "low", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "18 endpoints for LVM, ZFS, SMART, wipe operations. Needed for storage provisioning.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L5", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F068", "title": "Notifications subsystem 0% coverage", "category": "api_coverage", "severity": "low", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "32 cluster notification endpoints. New in PVE 8.1+, essential for monitoring/alerting automation.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L6", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F069", "title": "ACME/Certificates 0% coverage", "category": "api_coverage", "severity": "low", "status": "open", "first_detected": "2026-03-22", "files": [], "description": "23 combined endpoints for TLS certificate management and ACME.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L7", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" } ] }, { "id": "F070", "title": "Verify netstandard2.0 loads on Windows PowerShell 5.1", "category": "psgallery", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ ".github/workflows/publish.yml" ], "description": "Publish workflow builds only netstandard2.0 but manifest declares Desktop compatible with DotNetFrameworkVersion 4.8. Should add PS 5.1 smoke test.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "L8", "status": "new" }, { "scan_date": "2026-03-22", "local_id": "L8", "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "publish.yml now includes smoke-test-ps51 job on windows-latest that imports the netstandard2.0 module in Windows PowerShell 5.1 (shell: powershell) and verifies command count >= 150. Publish job depends on smoke test passing." } }, { "id": "F071", "title": "Missing Uri.EscapeDataString in cmdlet URL constructions", "category": "security", "severity": "medium", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE/Cmdlets/Templates/GetPveTemplateCmdlet.cs" ], "description": "GetPveTemplateCmdlet.cs:52 uses nodes/{node}/qemu without Uri.EscapeDataString on the node variable. All other previously cited cmdlets (~14) have been fixed. 1 instance remains.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ-NEW1", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "decisions_ref": "D003", "notes": "Reduced from ~15 files to 1 in scan-5. All network, snapshot, container snapshot, storage, and CloudInit cmdlets now use EscapeDataString.", "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "GetPveTemplateCmdlet.cs:53 now uses Uri.EscapeDataString(node) in the API path. Added using System; directive." } }, { "id": "F072", "title": "Unnecessary System.Text.Json dependency in Core.csproj", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ "src/PSProxmoxVE.Core/PSProxmoxVE.Core.csproj" ], "description": "System.Text.Json 8.0.5 referenced for netstandard2.0/net48 targets despite D008 Newtonsoft-only policy. No [JsonPropertyName] attributes or System.Text.Json namespaces in source. Dependency appears unused and adds to assembly surface area.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CQ-NEW2", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "decisions_ref": "D008", "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "System.Text.Json no longer referenced in PSProxmoxVE.Core.csproj. grep -c System.Text.Json returns 0." } }, { "id": "F073", "title": "build.yml references net9.0 but test project targets net10.0", "category": "code_quality", "severity": "high", "status": "resolved", "first_detected": "2026-03-22", "files": [ ".github/workflows/build.yml", "tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj" ], "description": "build.yml workflow builds and tests with --framework net9.0 but the test project now targets net10.0;net48. The workflow will fail because the test csproj no longer has a net9.0 target.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "PG-NEW1", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "decisions_ref": "D009", "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "build.yml now references --framework net10.0 at lines 51-53. No net9.0 references remain in build.yml." } }, { "id": "F074", "title": "Publish workflow smoke test threshold too low", "category": "psgallery", "severity": "medium", "status": "resolved", "first_detected": "2026-03-22", "files": [ ".github/workflows/publish.yml" ], "description": "Publish workflow checks module has >= 60 commands but module exports ~169 cmdlets. Threshold should be ~150 to catch regressions that drop significant cmdlets.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "PG-NEW2", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "publish.yml:58 checks commands.Count -lt 150 (was 60). With 169 exported cmdlets, threshold of 150 catches regressions while allowing minor variance." } }, { "id": "F075", "title": "~88 cmdlets lack markdown help documentation", "category": "psgallery", "severity": "medium", "status": "resolved", "first_detected": "2026-03-22", "files": [ "docs/cmdlets/" ], "description": "Only 81 of ~169 exported cmdlets have markdown help docs in docs/cmdlets/. Newer cmdlets added since initial documentation pass are missing.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "PG-NEW3", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "fixed" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-5", "verified_by": "scan", "evidence": "170 markdown help docs in docs/cmdlets/ for 169 exported cmdlets. All cmdlets now have documentation." } }, { "id": "F076", "title": "No dependabot or renovate for dependency updates", "category": "community", "severity": "low", "status": "resolved", "first_detected": "2026-03-22", "files": [ ".github/" ], "description": "No .github/dependabot.yml or renovate.json for automated dependency update PRs. NuGet and GitHub Actions versions will drift without manual monitoring.", "scan_history": [ { "scan_date": "2026-03-22", "local_id": "CM-NEW1", "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "open" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": ".github/dependabot.yml created with nuget (weekly) and github-actions (weekly) ecosystems targeting main branch." } }, { "id": "F077", "title": "GetPveTaskListCmdlet VmId parameter missing ValidateRange", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-23", "files": [ "src/PSProxmoxVE/Cmdlets/Tasks/GetPveTaskListCmdlet.cs" ], "description": "Optional VmId parameter (int?, line 29) lacks [ValidateRange(100, 999999999)] attribute. Per D010, all VmId parameters must have ValidateRange regardless of whether mandatory or optional.", "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "decisions_ref": "D010", "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "GetPveTaskListCmdlet.cs:29 now has [ValidateRange(100, 999999999)] on the VmId parameter, matching D010 convention." } }, { "id": "F078", "title": "No service-layer or PveHttpClient unit tests", "category": "testing", "severity": "medium", "status": "resolved", "first_detected": "2026-03-23", "files": [ "tests/PSProxmoxVE.Core.Tests/" ], "description": "Zero xUnit tests for any of the 14 service classes (VmService, ContainerService, StorageService, etc.) or PveHttpClient. Model deserialization tests exist but no tests for API call construction, error handling, or business logic in services.", "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "196 new service unit tests across 10 test files in tests/PSProxmoxVE.Core.Tests/Services/. All 14 services now have IPveHttpClient constructor injection enabling Moq-based testing. Total test count: 382 (was 186)." } }, { "id": "F079", "title": "unit-tests.yml uses dotnet SDK 9.0.x, inconsistent with build.yml 10.0.x", "category": "code_quality", "severity": "low", "status": "resolved", "first_detected": "2026-03-23", "files": [ ".github/workflows/unit-tests.yml" ], "description": "unit-tests.yml:31 installs dotnet-version 9.0.x while build.yml uses 10.0.x. The unit-tests workflow only builds netstandard2.0 and net48 so this works functionally, but the SDK versions should be consistent across workflows.", "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "decisions_ref": "D009", "resolution": { "scan_date": "2026-03-23", "report_id": "remediation-1", "verified_by": "code_change", "evidence": "unit-tests.yml line 31 changed from dotnet-version 9.0.x to 10.0.x, matching build.yml and the test project net10.0 TFM." } }, { "id": "F080", "title": "Restart-PveContainer CI failure: ConfirmImpact.High blocks non-interactive CI", "category": "ci_integration", "severity": "high", "status": "resolved", "first_detected": "2026-03-23", "files": [ "src/PSProxmoxVE/Cmdlets/Containers/RestartPveContainerCmdlet.cs", "tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1" ], "description": "Restart-PveContainer now has ConfirmImpact.High (F062 fix) which prompts for confirmation in non-interactive CI. The integration test at line 983 does not pass -Confirm:$false, causing a NullReferenceException when the cmdlet tries to read the confirmation response.", "ci_context": { "workflow": "integration-tests.yml", "run_id": "23454616043", "run_url": "https://github.com/goodolclint/PSProxmoxVE/actions/runs/23454616043", "job_name": "integration (9)", "platform": "ubuntu-latest/pwsh", "pve_version": "pve9", "conclusion": "failure", "run_date": "2026-03-23T18:51:46Z" }, "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-6-fix", "verified_by": "code_change", "evidence": "Added -Confirm:$false to Restart-PveContainer call at Integration.Tests.ps1:983. All other destructive cmdlet calls in the integration test already had -Confirm:$false." } }, { "id": "F081", "title": "Copy-PveContainer CI failure: cascading from Restart-PveContainer failure", "category": "ci_integration", "severity": "medium", "status": "resolved", "first_detected": "2026-03-23", "files": [ "tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1" ], "description": "Copy-PveContainer test fails with PveApiException: Cannot do full clones on a running container without snapshots. Container was still running because Restart-PveContainer (F080) failed to restart it. Test ordering dependency.", "ci_context": { "workflow": "integration-tests.yml", "run_id": "23454616043", "run_url": "https://github.com/goodolclint/PSProxmoxVE/actions/runs/23454616043", "job_name": "integration (9)", "platform": "ubuntu-latest/pwsh", "pve_version": "pve9", "conclusion": "failure", "run_date": "2026-03-23T18:51:46Z" }, "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-6-fix", "verified_by": "code_change", "evidence": "Cascading failure from F080. With Restart-PveContainer now passing -Confirm:$false, the container will be properly stopped before the clone test runs." } }, { "id": "F082", "title": "PVE 8 integration: Docker container image not found", "category": "ci_integration", "severity": "low", "status": "open", "first_detected": "2026-03-23", "files": [ ".github/workflows/integration-tests.yml" ], "description": "PVE 8 integration job fails at Initialize containers step — Docker image ghcr.io/goodolclint/psproxmoxve-integration: not found. The container-image build job may have failed or the image was not pushed for this commit.", "ci_context": { "workflow": "integration-tests.yml", "run_id": "23454616043", "run_url": "https://github.com/goodolclint/PSProxmoxVE/actions/runs/23454616043", "job_name": "integration (8)", "platform": "self-hosted/docker", "pve_version": "pve8", "conclusion": "failure", "run_date": "2026-03-23T18:51:46Z" }, "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" } ] }, { "id": "F083", "title": "CONTRIBUTING.md references .NET SDK 9.0+ (should be 10.0+)", "category": "community", "severity": "low", "status": "resolved", "first_detected": "2026-03-23", "files": [ "CONTRIBUTING.md" ], "description": "CONTRIBUTING.md line 9 says \".NET SDK 9.0+\" but all workflows use dotnet SDK 10.0.x and the test project targets net10.0. Contributors following CONTRIBUTING.md will install the wrong SDK version.", "scan_history": [ { "scan_date": "2026-03-23", "local_id": null, "status": "new" }, { "scan_date": "2026-03-23", "local_id": null, "status": "resolved" } ], "resolution": { "scan_date": "2026-03-23", "report_id": "scan-6-fix", "verified_by": "code_change", "evidence": "CONTRIBUTING.md line 9 changed from .NET SDK 9.0+ to .NET SDK 10.0+, matching all CI workflows and test project TFM." } } ] }