Set up in one command: penthera init
Starter. For “is my app safe to ship?”
Start here
New to Penthera? Run it with no arguments in your project folder:npx penthera with no
arguments does not start the wizard. It prints three commands to run instead,
penthera init --yes --dry-run, penthera init --yes and penthera --repo .,
and exits 2.
What it does
1. Detect. Offline, read-only:- whether this is a git repository (and which branch);
- the web framework, from
package.json,requirements.txtorpyproject.toml; - lockfiles:
package-lock.json,npm-shrinkwrap.json,uv.lock,poetry.lock,pdm.lock,Pipfile.lock,requirements.txt; - agent config:
.mcp.json,.claude/,.cursor/,CLAUDE.md,AGENTS.md,skills/; - a dev server on localhost ports 3000, 5173, 8000 or 8080 (a TCP connect to 127.0.0.1 and ::1, nothing else);
- whether the Penthera pre-commit hook or a Penthera GitHub workflow is already there.
2,4), or press Enter:
- AI tooling then asks whether to include
~/.claudeand~/.cursortoo (default no). - The running app is only listed when a dev server answered, is never preselected, and is only scanned after you confirm it is yours (default no). It runs the standard safe checks: no attack payloads.
- With offline mode off,
depsalso reads npm registry metadata and the URL scan may download the Retire.js database. Nothing else changes.
penthera agents), the three things to fix first in plain
language, and the report folder:
node_modules, Dependencies shows – not checked: 0 of 61 packages installed or cached, with the fix: npm ci --ignore-scripts installs the packages
without running their code, so the next run can read them. When only some are
missing, the grade covers what was read and the line says how many were not.
Every report lands in reports/penthera-<date>/: code, deps, agents and
app as JSON and Markdown, plus summary.md and summary.json.
4. Set up. Each step is a yes/no:
Steps that are already done (a hook or workflow that exists,
reports/ already
ignored) are skipped and say so.
5. What next. The commands to rerun each check, check staged changes, run
the fix loop or open the dashboard.
Before you launch
When you know what you want, run the checks directly. Start the app locally, then:*, a login with no rate limit. penthera fix --plan then prints a diff
per fix it knows. Nothing is written until you apply a plan
(fixes).
--yes and --dry-run
--yes answers every question with its safe default: the code, dependency and
AI tooling checks that apply, offline, then the hook, the workflow and
.gitignore. It never scans a URL, never runs the fix loop and never opens the
dashboard, even when a dev server is running.
--dry-run runs detection and asks the questions, then prints what it would
run and write instead of doing it. Combine them for a plan with no prompts:
penthera --yes and penthera --dry-run (no other arguments) are the same as
penthera init --yes and penthera init --dry-run.
What it does not do
- It is not a penetration test by a person. It checks known classes of problem. It will not find a flaw in your business logic, such as a coupon that can be applied twice.
- It does not fix IDOR or auth design for you. It points at the route. The fix is yours.
- It does not watch production yet. Scheduled checks are on the roadmap.
- A clean scan is not proof of safety. Every finding has a confidence label, and probes that could not run are listed as inconclusive rather than passed.
- Its accuracy is measured only on labs we wrote ourselves: precision 0.88 (95% CI 0.69 to 0.96) and recall 0.91 (95% CI 0.73 to 0.98) on 24 findings (results). Accuracy on real apps is not measured yet. That is experiment E1.
What it never does
- Commit, push, open a pull request, or touch a remote. The workflow file is written for you to review and commit yourself.
- Write outside the project: reports,
.gitignoreand the workflow go under the project root (the git top level when there is one), the hook into the repository’s hooks folder. - Contact anything but localhost, unless you turn offline mode off or confirm the running app.
penthera --repo ., penthera deps):
they exit 1 on high or critical findings.
The pinned SHA is the last release tagged before this version
(ACTION_PIN in src/cli/onboarding.js); Dependabot’s github-actions
updates keep it current in your repo.
Known issue: in every release from 1.5.0 to 2.0.0, the action’s mode: deps
exits before it scans, and the job still reports success, with no comment and
no SARIF. The v2.0.0 pin that this version writes has the same problem.
2.1.0-rc.1 has the fix, so mode: deps works with a pin to 2.1.0-rc.1 or later,
and init writes such a pin from the first release after 2.1.0-rc.1. Until
then, move the pin in your workflow to the 2.1.0-rc.1 release commit.