{"slug": "show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali", "title": "Show HN: PentestCanvas – Pentesting Workspace; with Claude and Kali", "summary": "A developer released PentestCanvas, a single-user desktop penetration-testing workspace built on Electron that pairs an investigation canvas with Claude and Kali Linux tooling, and that keeps captured proof inside its source Test rather than in standalone evidence records. The app requires Node 22.16+ for development, runs on Ubuntu 24.04+ including WSL with Electron system libraries such as libnspr4, libnss3 and libgbm1, and serves only the production bundle on a loopback port where every HTTP route and terminal WebSocket requires a fresh desktop credential held in Electron's main process. PentestCanvas ships a built-in synthetic sample engagement with two test paths and a reviewed finding, and its commands print only local fixtures, so the demonstration needs no API key or model call.", "body_md": "A local investigation workspace for penetration testers. Start with a target, a test, or existing proof. Keep your evidence and build the report as you work.\n\nA real agent session running synthetic fixtures, recording results, and updating the canvas. Playback is shortened.\n\n| Investigation canvas | Proof kept inside the test | \n|---|---|\n| **Reviewable finding** | **Report with evidence** | \n\n<sub>All data shown is the built-in synthetic sample engagement; no live system was tested.</sub>\n\nOn Ubuntu 24.04+ (including WSL), install Electron's system libraries once:\n\n```\nsudo apt-get update\nsudo apt-get install libnspr4 libnss3 libasound2t64 libgtk-3-0t64 libgbm1\n```\n\nWSL also needs a graphical session such as WSLg. `./run.sh` checks for missing\nshared libraries before building and launching the app.\n\n```\nnpm run setup\nnpm start\n```\n\nThis opens the standalone Electron app. Node 22.16+ is required for development; packaged builds include their runtime. Build a runnable directory with `npm run package`, or an installer/AppImage with `npm run dist` (output: `release/`). Docker and the Codex CLI are optional external tools. The current PTY and Docker integration require Linux; the investigation UI and evidence workflow do not require either tool.\n\nThe desktop serves only the production bundle on a loopback port assigned to the OS profile. Every HTTP route and terminal WebSocket requires a fresh desktop credential held in Electron's main process. Foreign origins and hosts are rejected; there is no wildcard CORS. The renderer uses a sandbox, context isolation, no Node integration, and a restrictive Content Security Policy. External navigation and popups are blocked.\n\nThis is a single-user desktop application: the OS profile owns the database. Terminal agents receive revocable credentials scoped to the selected engagement and cannot access settings, integration inventory, other engagements, or whole-document replacement. Linux containers reach the authenticated service through a private Unix-socket relay; CONNECT proxy access also requires a credential. The desktop credential is never passed to terminal subprocesses.\n\n`npm run dev` also launches Electron with a production build. `npm run dev:web` is an explicit frontend-only developer tool, restricted to loopback; it is not the desktop runtime. A manually launched API fails closed unless `PENTEST_CANVAS_TOKEN` is set to a random value of at least 64 characters. Browser-only acceptance scripts written for the old unauthenticated server must be adapted before use.\n\nAlready-running legacy Vite/API processes must be stopped by their operator after switching to the desktop app; editing these files does not secure an old process still running in memory.\n\nChoose **Open sample engagement** in the sidebar. It creates a separate, clearly labeled synthetic assessment with two test paths, captured example responses, and a reviewed finding ready to view in Report. Its commands only print local fixtures. The demonstration needs no API key or model call.\n\nThe investigation now keeps captured proof inside its source Test. Open a Test to read attempts, keep excerpts, write a one-sentence result, and choose an assessment. Standalone imported evidence remains available. Existing evidence IDs, report references, and immutable run history are preserved.\n\nNew steps automatically arrange horizontally: host → enumeration → discovered endpoints → endpoint tests → findings → follow-up tests. Each Test with evidence has an **Open proof** control on its card. Tests owning proof cannot be removed while that proof remains. Use **Builds on** inside a Test to combine multiple earlier findings or tests. `node tests/branching-desktop.mjs` verifies this complete flow through the real UI with synthetic local responses.\n\nUse **Discover surfaces** to paste enumeration results one per line and select which ports, services, or endpoints become targets. Duplicate entries under the same target are skipped. Each discovery links back to the Test and starts with unconfirmed scope.\n\n**Next move** creates another Test, records gained **Access**, or tracks an **Objective**. Tests started from Access inherit it as a prerequisite. Candidate or expired access blocks dependent recorded runs; verification requires captured proof. Access records are capability descriptions and credential references, not a credential vault or automatic session injector. Objectives expose their incoming investigation path and require proof before being marked reached. Connections describe dependencies, not automatic proof that an exploit chain succeeded.\n\n**Hide dead ends** removes refuted Tests from the canvas view without deleting their attempts. They remain accessible through search, branches, and Coverage. Findings and their reports continue to use selected proof, including proof embedded inside Tests.\n\nRun `node tests/investigation-desktop.mjs` for the isolated desktop workflow check.\n\n- **Target:** add the host, application, endpoint, or account under test. Scope is available from the toolbar.\n- **Test:** paste a command and choose where it runs. Every attempt has its own durable command, timestamp, output, environment, and exit state. Completion opens a spacious output reader: select an excerpt and keep it as evidence, or reopen an earlier attempt. A successful execution does not validate a vulnerability.\n- **Evidence:** select useful output and keep it, paste proof from another tool, or import a text capture/image. Captured content is read-only and has a SHA-256 fingerprint. Manually supplied proof is labeled separately from recorded runs.\n- **Finding:** attach evidence, describe impact, reproduction, severity, and remediation. Explicitly review it to include it in the report. Material changes invalidate that review.\n- **Report:** reviewed findings update automatically. The executive summary remains independently editable. Export full Markdown with embedded images or use Print / PDF. Previous free-form report drafts remain downloadable.\n\nTests with saved results open on their output; **Run again** reveals the command and execution environment. Output without recorded execution details is labeled plainly and can be kept as manually supplied evidence. Cards show badges only for active work, capture, review, or inclusion in the report.\n\nEvidence can be added to an existing finding, so multiple tests can support one issue. **Continue investigation** creates a follow-up test or discovered target from a test, evidence item, or finding. Discovery does not change the agreed scope.\n\nA question about an existing finding creates one reusable follow-up Test after that finding. Its command, result, and assessment remain together. Evidence is added only when the tester chooses to keep proof; another Finding is added only for a materially different issue.\n\nThe Add menu lets you start anywhere. Connect a target to a test/finding to assign it; connect evidence to a finding to attach it. Search with Ctrl/⌘ K, use Focus for a local view, and Arrange to tidy the canvas. Ctrl/⌘ Enter runs the open test when a target and execution environment are selected. Escape closes the output reader or inspector. Multiple labeled connections between the same nodes are supported; double-click a connection to rename it.\n\nThe desktop UI uses bundled DejaVu Sans with a compact navigation rail, neutral surfaces, and teal accents. Reports use the same typography; commands and raw output use DejaVu Sans Mono. Font license information ships with the app.\n\n**Investigation** is the main workspace: add targets, run tests, and follow evidence on the canvas. Open **Coverage** in its toolbar to find targets without tests, unassessed questions, and tests missing a target. Search targets or tests and open any item directly in the inspector; the graph stays in place. Coverage also links captured excerpts. An executed command alone does not count as a supported hypothesis.\n\n**Findings** is the review queue, with links to missing proof or details. **Report** is the delivery view for reviewed findings.\n\n**Export evidence** downloads a JSON package containing the report, reviewed finding references, selected evidence (including images), SHA-256 hashes, and source run metadata. Unselected run output and unrelated notes are excluded. Keep this downloaded package as the delivery record; the app does not manage releases.\n\nEngagements, settings, and run records live in Electron’s per-user application data directory (`~/.config/pentest-canvas` on Linux by default). On the first launch from this checkout, an existing `data/pentest-canvas.db` is copied using a consistent SQLite snapshot; the original remains intact. Saved integration settings and API key are also copied if present. Set `PENTEST_CANVAS_PROFILE` to use a separate profile without importing checkout data. The assigned port is retained across launches to preserve browser recovery storage; if another process occupies it, startup fails with an error. Packaged builds exclude all user data and secrets. The standalone API test/development entry point accepts `PENTEST_CANVAS_DB`. Browser saves merge disjoint changes with newer server state. Same-field conflicts stop saving and keep the local copy, with download/retry/load-saved controls. Unsaved work has a browser recovery copy. Browser layout changes cannot silently replace a different field edited by Codex.\n\nExisting data keeps its original IDs and notes. Old findings begin unreviewed; capture and attach proof before including them. Historical output is labeled as legacy evidence because original run metadata is unavailable. On a backend restart, unfinished runs become interrupted rather than falsely successful.\n\nOpen the collapsed, black-and-white Codex terminal when needed. It uses the real Codex CLI locally or in the active container and requires the saved OpenAI API key. No model call is required for the main workflow.\n\nThe agent saves a Test before each experiment, uses `canvas run TEST_ID @/tmp/run.json` for authorized recorded execution (`command` and explicit `environment`), and updates the assessment after each attempt. Retries stay on the same Test; new questions become connected follow-ups. Cards and run states refresh across all app pages without a manual context-send action. Negative results and failed attempts remain in the record.\n\nThe `canvas` CLI can inspect/update nodes, read recorded runs (`canvas runs TEST_ID`), and capture exact excerpts (` canvas capture '{\"runId\":\"...\",\"excerpt\":\"...\",\"title\":\"...\"}'`). Findings proposed by Codex still need human review. Arbitrary commands typed in the Codex terminal are not automatically attributed to a recorded test; use the Test inspector for the durable run workflow.\n\nCodex also receives the canvas geometry and visual conventions. `canvas view` returns current positions, card bounds, relationships, and browser viewport; `canvas image /tmp/canvas.png` retrieves a browser-generated schematic overview for an image viewer. It is explicitly labeled as a schematic, and stale images are rejected. `canvas connect` adds labeled relationships; `canvas layout` moves cards with collision handling and optional expected-position guards. Agent changes still pass through the same evidence and review rules.\n\n```\nnpm run build\nnpm test\nnpm run test:desktop\n```\n\nThe desktop smoke test requires a graphical session and the Linux GUI libraries required by Electron. It launches an isolated temporary profile with Chromium sandboxing enabled.\n\nSecurity regression tests use a temporary database and random loopback port. They replay anonymous reads/writes, foreign-origin requests, source-file probes, terminal upgrades, proxy access, and cross-engagement agent access without touching existing engagements.\n\nThis remains a local single-user prototype. HTTP/control and terminal APIs require capability credentials; the OS profile is the user boundary, and there are no multi-user accounts. A review marker is a workflow gate, not an authenticated signature. Docker profiles are network arrangements, not a complete enforcement layer for rules of engagement. Do not expose the control API as a multi-user service.\n\nThe new Test workflow requires an explicit environment and will not fall back to the host when its chosen container is unavailable. The optional terminal has a separate execution path. Unrecorded `/api/run`, Distill, the dormant copilot/CVE agent, and its usage accounting have been removed. Captured excerpts are not automatically redacted; review sensitive content before including a finding. Files are currently inline (supported images/text under 4 MB per import), with a 12 MB API body limit, so this is not yet a large artifact repository. PDF export uses the browser's print renderer; DOCX and release snapshot management are not implemented.\n\nThe recorder adds a synthetic engagement to the selected profile. `REAL_PROFILE=1` uses the existing desktop profile and its saved settings; close the app before recording.\n\n```\nREAL_PROFILE=1 LEAN_DEMO=1 FRAMES=/tmp/canvas-demo-frames npm run demo:record -- /tmp/canvas-demo tests/agent-demo-steps.mjs\nnode tests/render-demo.mjs /tmp/canvas-demo-frames docs/media/agent-demo.gif 1280 500\n```\n\nRun `npm run test:terminal` for desktop checks of collapse/reopen, focus, resize, setup progress, errors, and retry.", "url": "https://wpnews.pro/news/show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali", "canonical_source": "https://github.com/andrearitossa/pentest-canvas", "published_at": "2026-11-06 11:53:05+00:00", "updated_at": "2026-11-06 12:20:14.950613+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools"], "entities": ["PentestCanvas", "Electron", "Claude", "Kali Linux", "Ubuntu 24.04", "WSL", "Codex CLI", "Node 22.16"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali", "markdown": "https://wpnews.pro/news/show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali.md", "text": "https://wpnews.pro/news/show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali.txt", "jsonld": "https://wpnews.pro/news/show-hn-pentestcanvas-pentesting-workspace-with-claude-and-kali.jsonld"}}