# SysReptor: pentest reports designed in HTML, written in Markdown, rendered to PDF

> SysReptor is a Django and Nuxt application for producing penetration test reports, sold as both self-hosted software and a hosted service. The README is a short pitch, and the tree underneath it is a large JavaScript and Python monorepo.

**Syslifters/sysreptor** — A customizable and powerful penetration testing reporting platform for offensive security professionals. Simplify, customize, and automate your pentest reports with ease.

- Repository: https://github.com/Syslifters/sysreptor
- Website: https://docs.sysreptor.com
- Stars: 2,599 · Forks: 293
- Language: Python
- License: NOASSERTION
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/syslifters-sysreptor

## HTML in, Markdown in, PDF out

The README compresses the product into four lines with a symbol in front of each: design your report in HTML, write it in Markdown, render to PDF, self-hosted or Cloud. That is an accurate summary of a design choice most reporting tools do not make, and the choice has consequences.

Design in HTML means the layout is a real stylesheet with real CSS, so a firm's branding, fonts and table of contents come from the template rather than from fighting a report generator's settings. Write in Markdown means the finding text is stored as text with structure, which keeps findings portable and lets the same content appear in a web view and a PDF. Render to PDF means the output is the artefact a client actually receives.

The description in GitHub's metadata calls it a customizable and powerful penetration testing reporting platform for offensive security professionals, with the goal of simplifying, customizing and automating report creation. The README calls it fully customizable and designed for penetration testers, red teamers and other cybersecurity professionals. Slight wording difference, same product.

The topics are the best single view of what it is actually for: oscp, osed, osep, oswa, oswp, cpts, cdsa, hackthebox and pentest-reports sit alongside cape, chhb, infosectools and offsec. Those are certification and platform names, which tells you the intended buyer is a professional doing client work rather than a developer who wants a generic document generator.

## A JavaScript monorepo with a Python API underneath

The `Dockerfile` at the repository root is where the stack becomes clear, and it opens with two global arguments, `TESTED_API_IMAGE=api` and `PROD_API_IMAGE=api-prod`, then builds from `node:24-alpine3.24`. Each build stage sets its own working directory under `/app/packages/` and copies only the `package.json` files before running `npm install`, so the layer cache survives code changes. That pattern repeats for each package:

```dockerfile
COPY packages/package.json packages/package-lock.json /app/packages/
COPY packages/frontend/package.json /app/packages/frontend/
COPY packages/markdown/package.json /app/packages/markdown/
COPY packages/pdfviewer/package.json /app/packages/pdfviewer/
RUN npm install
```

The named packages tell you the architecture. `frontend` is the application, `markdown` is the report editor, `pdfviewer` is how the rendered result is checked, `excalidraw` is a whiteboard embedded in the product, and `nuxt-base-layer` and `plugin-base-layer` are the shared foundations. `rendering` has its own patches directory, which means it carries patched dependencies, the usual sign of a renderer that needs upstream fixes held locally.

The Python side is `api/`, which is the Django application behind the Nuxt frontend. That split has a practical consequence: a self-hosted install runs two services with their own upgrade paths, and the update scripts at the repository root reflect that. `update.sh`, `post_update.sh` and `upgrade_postgres.sh` are three separate steps, and the presence of a dedicated PostgreSQL upgrade script says the database is treated as state you cannot simply throw away and recreate.

## Plugins, a whiteboard, and a spell checker in the build

Three directories in the tree describe what makes the product more than a form to fill in. `plugins/` is where integrations live. `packages/excalidraw/` is a full drawing tool embedded in the reporting workflow, which for a penetration test report is not decoration: network diagrams and attack flows are standard content, and drawing them by hand in a slide tool before pasting a screenshot is exactly the friction this removes. `languagetool/` is a LanguageTool integration, so the spell and grammar checking of report prose is built in rather than left to a browser extension.

Then there is `demo_data/`, which is the feature that most improves an evaluation. Seeded example reports let you open a populated project and see how findings, attachments and diagrams are actually organised, rather than staring at an empty form. The README points to demo reports in the documentation and to a hosted playground at sysreptor.com/demo, and the presence of `demo_data/` in the repository suggests the playground is fed from something like it.

Taken together, plugins plus a whiteboard plus language checking plus seeded data is a coherent product decision. The bet is that the quality of the report is the thing that wins client work, so effort goes into the document rather than into the findings database. A tool that only stored findings and left formatting to the tester would be cheaper and, for some users, entirely sufficient.

## Open source core, commercial product, and a licence to read closely

The README's link row is where the commercial structure shows: Playground, Ideas, Questions, Documentation, Features and Pricing, Installation, and Buy SysReptor pointing at an ordering portal at portal.sysreptor.com. There is also a Buy link and a pricing page, alongside a project page at sysreptor.com and documentation at docs.sysreptor.com.

So this is not a free tool with a donate button. The self-hosted path and the cloud path are both commercial, and the README says so without pretending otherwise, which is more useful than a repository that hides the commercial layer. For an evaluator, the question is which path you are on: self-hosted gives you the deployment and the upgrades, the cloud gives you neither.

On licensing, there is a real ambiguity to flag. GitHub reports no license identifier for the repository, which in GitHub's terms means no recognised licence file was detected, while the tree does contain a `LICENSE` file. Before you deploy this internally, or fork it, or ship a client report template based on it, read that `LICENSE` file yourself. A repository with a commercial product and an unrecognised licence field is exactly the case where you want the actual text in front of you rather than an inference. Do not assume MIT, and do not assume no restrictions either.

The repository also carries `SECURITY.md`, `CONTRIBUTING.md` and `CHANGELOG.md`, and `.gitlab-ci.yml` rather than a GitHub Actions workflow, so continuous integration runs on GitLab.

## Release numbering that reads like a calendar

GitHub reports the repository as Python, not archived, last pushed 2026-09-24, on the `main` branch. The releases are named 2026.82 published 2026-09-23, 2026.75 on 2026-09-16 and 2026.68 on 2026-08-19.

Those are calendar version numbers in the CalVer style, where the year leads and the second number counts releases within the year. Read that way, the sequence is about two releases a month: 68 in August, 75 in early September, 82 by the end of September. That is a fast cadence for an application with a database behind it, and it has an operational meaning. You will be upgrading regularly, so the `update.sh`, `post_update.sh` and `upgrade_postgres.sh` scripts are part of the product rather than an afterthought.

It also means the changelog is the document to read before each upgrade, and `CHANGELOG.md` sits at the repository root for that purpose. For a security consultancy with client data in the instance, knowing what changed in 2026.82 before applying it is not optional.

The documentation at docs.sysreptor.com is where the installation guide lives, and the README's Getting started list points there rather than duplicating steps, which is the right call for a deployment with this many moving parts.

## Against the alternatives, and where it stops being the answer

The realistic comparison is not against another pentest tool, because most of those produce findings and leave reporting to you. It is against a general document tool, and the difference is the specialisation. A word processor or a Markdown-to-PDF converter will render a finding list perfectly well, costs nothing, and needs no deployment. What it will not give you is finding-level structure with recurring fields, an attachments system, embedded diagrams, a spell checker wired to the content, plugin hooks, and a consistent house style applied automatically across every report.

For a solo tester writing two reports a year, that difference is not worth a server to run and an upgrade cycle to track. The value scales with repetition: the more reports you produce and the more consistency a client base expects, the more the template automation pays for itself.

There is also the self-hosting tax to name plainly. This is a two-service deployment with a PostgreSQL database, an upgrade script sequence and a version cadence of roughly monthly. If nobody on your team wants to own that, the cloud path exists precisely so you do not have to, and the honest comparison becomes price against your own time rather than features against features.

Start with the playground at sysreptor.com/demo and the demo reports in the documentation. If the output looks like something you would send a client, the deployment question is worth having; if it does not, no configuration setting will change that.

## Conclusion

SysReptor fits a consultancy that produces many client-facing reports and wants the document, not just the data, to be under its own control. It does not fit a solo tester who writes once a quarter and would rather use a word processor, since the setup is a real deployment with upgrades attached. GitHub reports the last push on 2026-09-24 with release 2026.82 published 2026-09-23, a calendar-versioned cadence that implies frequent releases, and the playground at sysreptor.com/demo is the fastest way to judge the output before installing anything.

## FAQ

### What does SysReptor actually produce?

PDF reports, designed in HTML and written in Markdown, which the README lays out as its four-step summary along with self-hosted or cloud deployment. The tree backs that up with a `rendering` package for the output, a `pdfviewer` package for inspecting it, and an `excalidraw` package for diagrams inside the report. Findings are stored as structured text rather than as laid-out pages.

### Is SysReptor free to self-host?

The README links a Features and Pricing page and an ordering portal at portal.sysreptor.com alongside the installation docs, so both the self-hosted and cloud paths are commercial. GitHub reports no licence identifier for the repository, and there is a `LICENSE` file in the tree, so read that file before deploying internally or forking. The documentation at docs.sysreptor.com has the installation guide.

### How often does SysReptor release, and what does upgrading involve?

Releases use calendar versioning: 2026.82 on 2026-09-23, 2026.75 on 2026-09-16 and 2026.68 on 2026-08-19, roughly monthly. The repository root carries `update.sh`, `post_update.sh` and `upgrade_postgres.sh`, so a self-hosted upgrade is a scripted sequence rather than a single command, and `CHANGELOG.md` is worth reading first.

## Sources

- [Issues](https://github.com/Syslifters/sysreptor/issues)
- [Project website](https://docs.sysreptor.com)
- [README](https://github.com/Syslifters/sysreptor/blob/main/README.md)
- [Releases](https://github.com/Syslifters/sysreptor/releases)
- [Syslifters/sysreptor on GitHub](https://github.com/Syslifters/sysreptor)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/syslifters-sysreptor
