How this started
A user on a call with our Success team asked a question:
Is there any way to see all my projects and issues on a map?
The short answer at the time was No.
But it’s a genuinely useful thing for teams running engagements across multiple offices, data centers, facilities, or regions. At the same time, it’s probably not widespread enough for it to make it into the product.
But then I thought, can I vibe code this? Turns out I could!
What is this?
A small open-source companion tool that:
- Reads from your Dradis Pro API
- Plots each project as a dot on a North America map
- Colors each dot by the most severe tag found in that project. One Critical finding turns the dot purple regardless of how many Lows sit alongside it.
It runs entirely on your machine — a local Node.js server proxies all API calls, so your token never touches a browser, and the data never leaves your network. Think of it as a lightweight, self-hosted dashboard you can spin up in a couple of minutes.
How it uses Dradis
The tool uses three REST API endpoints:
-
GET /pro/api/projects— lists all projects -
GET /pro/api/issueswithDradis-Project-Idheader — fetches issues per project -
GET /pro/api/document_propertieswithDradis-Project-Idheader — reads thedradis.coordinatesproperty to place the project on the map
Tag colors are read directly from tag.color in the API response — no hardcoded mappings. Severity ordering (critical → high → medium → low → info) determines the dominant color for each map marker.
Enabling coordinates
For a project to appear on the map, add a dradis.coordinates document property under Project Configuration → Document Properties:
dradis.coordinates: 40.7128N, 74.0060W
Accepted formats:
40.7128° N, 74.0060° W (degrees with cardinal)
40.7128N, 74.0060W (cardinal, no degree symbol)
40.7128, -74.0060 (decimal, negative = West/South)
lat:40.7128, lon:-74.0060 (labeled)
Projects without this property are silently skipped — nothing breaks if only some projects have coordinates.
Installation
Prerequisites: Node.js 18 or later
1. Clone from GitHub
git@github.com:dradis/dradis-map.git
cd dradis-map
2. Install dependencies
npm install
This pulls in Express, Helmet, Morgan, and a couple of other small packages. No database, no Docker required.
3. Configure your credentials
cp .env.example .env
Open .env and fill in your values:
DRADIS_HOST=https://your-dradis-instance.example.com
DRADIS_TOKEN=your_api_token_here
Your API token is in Account Settings → API token inside Dradis.
Self-signed certificates: if your Dradis instance uses a self-signed cert (common for local or on-prem installs), uncomment one of these lines:
# Quickest option — safe on a trusted local network:
TRUST_SELF_SIGNED=true
# More secure — point to your exported certificate:
CA_CERT_PATH=/path/to/dradis-ca.pem
To export your cert: click the padlock in your browser → Certificate → Export as PEM.
4. Start the server
npm run dev # development — auto-restarts on file changes
npm start # production
Open http://localhost:3000 and click Load Data.
Architecture notes (for the curious)
A few decisions worth calling out for anyone who wants to extend or audit this:
-
Token never reaches the browser. The Express server handles all Dradis API calls server-side. The frontend only talks to
localhost. -
Bound to 127.0.0.1 only. The server won’t accept connections from the network — it’s a local tool.
-
Nonce-based CSP. A cryptographic nonce is generated per request and injected into both the
Content-Security-Policyheader and the served HTML, eliminatingunsafe-inlinefromscript-src. -
Input validation on API routes. Project IDs are validated as positive integers before they touch any upstream request.
-
Tag color values from the API are validated. All tag color values from the API pass through a hex validator (
/^#[0-9a-fA-F]{3,8}$/) before being injected into any HTML style attribute or SVG attribute, covering issue pills, map markers, tooltips, and the legend. -
Graceful shutdown. SIGTERM/SIGINT handlers let in-flight requests drain before the process exits, which matters if you run this under PM2 or systemd.
The project structure follows a layered pattern if you want to add endpoints or adapt it for a different region:
server.js ← entry point: config, middleware, startup
src/
services/dradisClient.js ← all Dradis API communication (no Express dependency)
routes/api.js ← Express router (receives client via DI)
public/
index.html ← full frontend: D3 map + sidebar UI
Relation to Echo and the Claude Code skills
This tool was built using Claude as a coding assistant. The work is similar in spirit to the Claude Code skills post: using an LLM to do the heavy lifting on something that would otherwise be tedious to build from scratch.
We’ve just incorporated a whole lot of instructions for LLMs to the Dradis repo, covering architecture, code style, conventions and much more.
It complements Echo well; Echo improves what’s inside your issues, and this visualizes where those issues are.
What’s next / ideas
We’d be happy to help you make these changes, or you’re free to build on this base:
-
World map support — the current projection is Albers/North America. Swapping to a world projection would be a small change to the D3 setup.
-
Filtering by tag — click a tag in the legend to show only projects with that severity.
-
Click through to Dradis — clicking a marker could open the project directly in your Dradis instance.
If you were the one who asked about this on that call, this one’s for you ![]()
And if others have been wondering the same thing, hopefully this scratches the itch. Questions, ideas, and feedback welcome below.
