feat(pentest): let customers add context to findings so retests are informed#3110
Conversation
…nformed Customers asked to explain findings (accepted-by-design rationale, remediation notes) so a retest doesn't blindly re-flag them (CS request: 'how do i run retest with the additional context i provided instead of another blind pentest'). - add SecurityPenetrationTestFindingContext table (+migration): one note per org+provider issue, grouped by normalized target URL - new /v1/pentest-finding-contexts endpoints: GET list by target (pentest:read), PUT/DELETE per finding (new pentest:update action, granted to owner/admin); MCP tool names + OpenAPI metadata included - createReport now composes Maced's additionalContext from the new optional additionalContext DTO field plus all saved notes for the target, so every re-run is an informed retest - app: permission-gated 'Retest context' editor on FindingDetail, optional run-level context field + auto-share hint on CreateRunPanel - regenerate packages/docs/openapi.json - tests: util/service/controller specs (api), FindingContextSection + CreateRunPanel payload tests (app); fix pre-existing controller spec load failures by mocking permission.guard/@db Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
1 issue found across 29 files
Confidence score: 4/5
- In
apps/api/src/security-penetration-tests/pentest-finding-contexts.service.ts, provider target URLs that are only whitespace can pass validation and be persisted as an empty normalized target, which can create invalid finding context records and downstream confusion/filtering errors — trim and reject blank-after-trim URLs in validation before merging.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
The markdown and PDF reports come from the provider and never showed the customer's finding-context notes — the artifact handed to auditors lost exactly the justifications the notes exist for. - report-appendix.util.ts: render notes as a clearly attributed 'Appendix: Customer context & management responses' — appended section for markdown, appended pages (pdf-lib, NdaPdfService idioms) for PDF; WinAnsi-safe sanitization, word wrap, pagination - getReportOutput/getReportPdf attach the appendix for the run's target; zero notes -> byte-identical passthrough; notes-lookup or PDF-parse failures are logged and the original provider artifact is served unchanged (appendix is additive, never load-bearing) - tests: 11 new (util markdown/pdf/pagination/unicode/corrupt-input + service append/fallback paths), module suite now 95 passing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added in 5f59df7 — customer context now reaches the downloadable reports too. The markdown/PDF reports come from the provider, so customer notes were invisible in the artifact customers hand to auditors. Both downloads now get a clearly attributed "Appendix: Customer context & management responses" — appended section in markdown, appended pages in the PDF (pdf-lib, same idioms as Safety guarantees (the original provider report can never get worse):
11 new tests (appendix rendering, pagination, unicode, corrupt-PDF fallback, service append/fallback paths); module suite at 95 passing. 🤖 Generated with Claude Code |
…upsert Validate the normalized target instead of the raw string so a whitespace-only provider URL can't persist a note with an empty target that no future scan lookup could match (cubic review). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Fixed the cubic finding in 1a45397 — 🤖 Generated with Claude Code |
|
🎉 This PR is included in version 3.79.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Why
Customers want to explain pentest findings — accepted-by-design rationale, remediation notes — so a retest validates against that context instead of blindly re-flagging the same issues. Direct customer ask (Slack):
Key insight
Pentest findings are never stored in our DB (fetched live from Maced), and a re-run has zero memory of previous runs. But Maced's
CreatePentestBodyalready supports anadditionalContextfree-text field that our API never exposed. This PR persists per-finding customer notes on our side and injects them into that field on every new scan of the same target.What changed
DB (
packages/db)SecurityPenetrationTestFindingContextmodel + migration: one note per org + provider issue id, unique on(organization_id, provider_issue_id), grouped by normalized target URL, with anissue_titlesnapshot so notes outlive provider run pruning.API (
apps/api)/v1/pentest-finding-contextsendpoints:GET ?targetUrl=— list notes for a target (pentest:read)PUT /:issueId— upsert a note (pentest:update); validates run ownership and that the issue belongs to the run; target URL taken from Maced, never from the clientDELETE /:issueId— remove a note (pentest:update)createReportcomposes Maced'sadditionalContextfrom a new optionaladditionalContextDTO field plus all stored notes for the normalized target.pentest:updateRBAC action (owner/admin; auditors stay read-only). This also makespentest:updatean available API-key scope so the MCP tools work for agents.@ApiBody, summaries/descriptions within SEO limits, explicit MCP tool names (set-pentest-finding-context,delete-pentest-finding-context,list-pentest-finding-contexts).packages/docs/openapi.json(was stale on main — also picks up previously merged trust-portal/cloud-security endpoints).App (
apps/app)Tests
createReportflow.FindingContextSectiontests (update vs read-only) andCreateRunPanelpayload tests (context included/omitted, auto-share hint).permission.guard/@dbmocks, keepingPERMISSIONS_KEY's real value so decorator metadata stays intact.page.test.tsx/penetration-test-page-client.test.tsx(old "temporal UI" era design) fail identically onmain.Known limitation / follow-ups
findingIdcross-run semantics confirmed.issues.update(status)triage API exists and is unused — candidate for a status-triage UI later.🤖 Generated with Claude Code
Summary by cubic
Lets customers add context to pentest findings and runs so retests and downloaded reports are informed, not blind. Notes and optional run-level text are sent to Maced via
additionalContextand appended to report markdown/PDF as a clearly attributed appendix; upserts now reject whitespace-only provider target URLs.New Features
/v1/pentest-finding-contexts— GET bytargetUrl(pentest:read), PUT/DELETE byissueId(pentest:update); validates run ownership/issue membership and rejects empty/whitespace normalized targets. Docs regenerated inpackages/docs/openapi.jsonwith MCP tools:set-pentest-finding-context,delete-pentest-finding-context,list-pentest-finding-contexts.SecurityPenetrationTestFindingContext(unique per org+provider issue; grouped by normalized target URL withissue_titlesnapshot).createReportcomposes provideradditionalContextfrom the run’s optionaladditionalContextfield plus saved notes for the target; report downloads append “Appendix: Customer context & management responses” to markdown/PDF (no notes -> passthrough; failures -> serve original).pentest:updateaction enables editing (owner/admin, API-key scope).Migration
pentest:updatescope to allow setting/removing notes.Written for commit 1a45397. Summary will update on new commits.