--- name: dependency-audit-erp description: Scan lỗ hổng NuGet + npm cho SOLUTION_ERP (.NET 10 + 2 FE React). Chạy dotnet list package --vulnerable + npm audit cho fe-admin/fe-user, report CVE + decide upgrade path. Respect pin constraint (MediatR 12.4.1 cannot upgrade to 14, Swashbuckle 6.9.0 cannot upgrade to 7+, Node 20.x only for CI). when-to-use: - "dependency audit" - "npm audit" - "dotnet vulnerable" - "scan CVE" - "nâng cấp package" - "security dependencies" - "deps scan CI" --- # Dependency Audit — SOLUTION_ERP > **Context:** Phase 5.1 security backlog explicit — "Dependencies scan CI (`dotnet list package --vulnerable --include-transitive`, `npm audit --audit-level=high`)". Chưa hook vào workflow, có thể chạy manual. ## Commands (chạy từ root repo) ### Backend .NET ```powershell # Restore trước khi scan (first time / sau pull) dotnet restore # Scan top-level + transitive vulnerable dotnet list src/Backend/SolutionErp.Api/SolutionErp.Api.csproj package --vulnerable --include-transitive # Scan cả solution dotnet list SolutionErp.slnx package --vulnerable --include-transitive # Outdated check (khác vulnerable — chỉ cảnh báo version cũ) dotnet list SolutionErp.slnx package --outdated ``` **Output interpretation:** - `> High` / `> Critical` severity → fix ngay (pin lên patch/minor version không breaking) - `> Moderate` → plan trong sprint tới - `> Low` → track, không rush ### Frontend 2 app ```powershell # fe-admin cd fe-admin npm audit --audit-level=high npm audit --json > ../tmp/fe-admin-audit.json # detail cd .. # fe-user cd fe-user npm audit --audit-level=high npm audit --json > ../tmp/fe-user-audit.json cd .. ``` Hoặc chạy song song từ 1 lệnh: ```powershell cd fe-admin; npm audit --audit-level=high; cd ..; cd fe-user; npm audit --audit-level=high; cd .. ``` ## ⚠️ Pin constraints — KHÔNG auto-upgrade dù có CVE/outdated Đọc `docs/gotchas.md` trước khi bấm `npm audit fix` hoặc `dotnet add package`. Những pin sau đây có lý do rõ ràng: ### Backend pins | Package | Current | Lý do không upgrade | Gotcha # | |---|---|---|---| | `MediatR` | **12.4.1** | v14 breaking — `AddMediatR` fail resolve `IMediator` | #1 | | `Swashbuckle.AspNetCore` | **6.9.0** | v10+ yêu cầu `Microsoft.OpenApi` 2.x — breaking `Swashbuckle.AspNetCore.Models` namespace | #2 | | `Microsoft.AspNetCore.OpenApi` | **removed** | Conflict Swashbuckle, dùng riêng 1 trong 2 | #2 | | `Microsoft.EntityFrameworkCore` | **10.x** | Pin theo .NET 10 SDK (`global.json` 10.0.104) | — | | `Microsoft.AspNetCore.Identity` | **10.x** | Pin theo .NET 10 — `AddIdentityCore` không có `AddDefaultTokenProviders` | #8 | ### Frontend pins | Package | Current | Lý do pin | |---|---|---| | `typescript` | **6.x** | `erasableSyntaxOnly` cấm enum → đã rewrite const-object pattern, rollback = rewrite lại (#3) | | `vite` | **8.x** | rolldown native binding cần fresh `node_modules` trên CI (gotcha npm ci fail) | | `@microsoft/signalr` | **8.0.7** | SignalR hub version parity với ASP.NET Core 10 — test kỹ trước khi bump | | `react` | **19** | Auto-scaffolded, đã style-adapt cho | | Node engine | **`>=20`** | CI pin `20.x` qua `.nvmrc` (NamGroup bài học, gotcha #5) | ## Workflow khi fix vulnerability ``` 1. Đọc CVE detail: npm audit (--json) hoặc https://github.com/advisories/GHSA-xxxx 2. Check có phải transitive dep không? - Direct → bump trong package.json / .csproj, test build - Transitive → check ancestor package, có newer không 3. Nếu ancestor fix available nhưng là major version: - Đánh giá breaking change (đọc CHANGELOG) - Nếu yes → defer + document, dùng npm overrides hoặc dotnet transitive constraint 4. Test local: - BE: dotnet build + dotnet run → /health/ready healthy - FE: npm run build + npm run dev → login flow + CRUD smoke test 5. Commit [CLAUDE] Infra: bump for CVE-xxxx 6. Watch CI xanh ``` ## CI integration (TODO — Phase 5.1 backlog) Dự kiến thêm vào `.gitea/workflows/deploy.yml` step: ```yaml - name: Deps audit shell: pwsh run: | dotnet list SolutionErp.slnx package --vulnerable --include-transitive 2>&1 | Tee-Object -Variable nugetOut if ($nugetOut -match 'has the following vulnerable packages') { Write-Error "NuGet vulnerabilities found" exit 1 } cd fe-admin; npm audit --audit-level=high; if ($LASTEXITCODE -ne 0) { exit 1 }; cd .. cd fe-user; npm audit --audit-level=high; if ($LASTEXITCODE -ne 0) { exit 1 }; cd .. ``` Gate nên set `continue-on-error: true` lần đầu → monitor 1 tuần → enable blocking. ## Output template (khi manual chạy) ```markdown # Deps audit — {YYYY-MM-DD} ## NuGet - Critical: 0 - High: 0 - Moderate: 0 - Low: 0 ## npm fe-admin - Critical: 0 - High: 0 - Moderate: N (liệt kê) ## npm fe-user - Critical: 0 - High: 0 - ... ## Action items - [ ] Bump X from a.b.c → a.b.d (patch, safe) — CVE-xxxx - [ ] Defer Y (v3 → v4 breaking, plan Phase N) - [ ] Override Z via npm overrides (transitive, no direct bump) ``` Lưu vào `docs/changelog/deps-audit-{YYYY-MM-DD}.md` nếu có action. ## Related - `docs/gotchas.md` — 56 bẫy package compat / CI / IIS / Identity / per-NV refactor / SQLite tie-break đã gặp - `docs/changelog/migration-todos.md` Phase 5.1 — checklist deps scan CI - `SolutionErp.slnx` + `global.json` — .NET version pin