penthera 1.6.1 → 1.8.0-rc.1

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.
Files changed (161) hide show
  1. package/CHANGELOG.md +296 -0
  2. package/README.md +217 -322
  3. package/SECURITY.md +8 -6
  4. package/bin/scan.js +2 -2
  5. package/docs/examples/github-actions-scan.yml +1 -1
  6. package/docs/examples/pr-dependency-review.yml +1 -1
  7. package/lib/adaptive-probes.js +3 -3
  8. package/lib/agents/hidden-content.js +122 -11
  9. package/lib/agents/index.js +26 -6
  10. package/lib/agents/lock.js +33 -5
  11. package/lib/agents/rules.js +33 -4
  12. package/lib/crawler.js +4 -15
  13. package/lib/deps/capabilities.js +21 -5
  14. package/lib/deps/index.js +46 -7
  15. package/lib/deps/iocs.js +74 -0
  16. package/lib/deps/lockfile.js +3 -8
  17. package/lib/deps/online.js +8 -3
  18. package/lib/deps/popular-packages.json.gz +0 -0
  19. package/lib/deps/popular-pypi.json.gz +0 -0
  20. package/lib/deps/python/capabilities.js +16 -3
  21. package/lib/deps/python/index.js +5 -1
  22. package/lib/deps/python/lockfiles.js +11 -5
  23. package/lib/deps/python/source.js +75 -26
  24. package/lib/deps/python/toml.js +15 -3
  25. package/lib/deps/source.js +28 -9
  26. package/lib/deps/typosquat.js +30 -5
  27. package/lib/fix/apply.js +253 -34
  28. package/lib/fix/index.js +7 -4
  29. package/lib/fix/model.js +25 -5
  30. package/lib/fix/util.js +6 -2
  31. package/lib/fuzzer.js +3 -3
  32. package/lib/git.js +65 -0
  33. package/lib/hook/index.js +157 -73
  34. package/lib/hook/policy.js +10 -4
  35. package/lib/install/index.js +4 -7
  36. package/lib/machine.js +0 -13
  37. package/lib/memory/store.js +11 -4
  38. package/lib/nuclei-loader.js +0 -25
  39. package/lib/plugins.js +1 -1
  40. package/lib/recon.js +12 -31
  41. package/lib/references.json +44 -0
  42. package/lib/retirejs.js +4 -4
  43. package/lib/rules/allowed_signers +13 -0
  44. package/lib/rules/core/agent-exec.json +29 -0
  45. package/lib/rules/core/agent-instructions.json +17 -0
  46. package/lib/rules/core/pack.json +30 -0
  47. package/lib/rules/core/pack.json.sig +6 -0
  48. package/lib/rules/core/secrets.json +161 -0
  49. package/lib/rules/core/templates.json +52 -0
  50. package/lib/rules/index.js +107 -0
  51. package/lib/rules/ioc-2025-2026/files.json +43 -0
  52. package/lib/rules/ioc-2025-2026/hosts.json +35 -0
  53. package/lib/rules/ioc-2025-2026/pack.json +25 -0
  54. package/lib/rules/ioc-2025-2026/pack.json.sig +6 -0
  55. package/lib/rules/ioc-2025-2026/packages.json +1048 -0
  56. package/lib/rules/pack.js +362 -0
  57. package/lib/rules/regex-guard.js +81 -9
  58. package/lib/rules/sshsig.js +205 -0
  59. package/lib/templates.js +24 -20
  60. package/lib/tmp.js +21 -0
  61. package/lib/whitebox/frameworks.js +37 -1
  62. package/lib/whitebox/secrets.js +117 -41
  63. package/package.json +11 -4
  64. package/scripts/rules/build-pack.mjs +80 -0
  65. package/scripts/rules/check-bundled.mjs +30 -0
  66. package/scripts/rules/sign-pack.sh +32 -0
  67. package/skills/penthera/SKILL.md +31 -17
  68. package/src/agent/git.js +147 -14
  69. package/src/agent/loop.js +165 -46
  70. package/src/cli/agent.js +11 -5
  71. package/src/cli/deps.js +1 -3
  72. package/src/cli/detect.js +132 -0
  73. package/src/cli/fix.js +26 -8
  74. package/src/cli/hook.js +2 -1
  75. package/src/cli/onboarding.js +436 -6
  76. package/src/cli/prompt.js +42 -0
  77. package/src/cli/report-outputs.js +1 -0
  78. package/src/cli/rules.js +144 -0
  79. package/src/cli/ui.js +43 -10
  80. package/src/cli.js +41 -5
  81. package/src/report/evidence.js +105 -21
  82. package/src/report/md-escape.js +8 -0
  83. package/src/scan-url.js +2 -2
  84. package/src/ui/api/data.js +69 -6
  85. package/src/ui/api/demo.js +13 -0
  86. package/src/ui/api/routes.js +45 -11
  87. package/src/ui/api/runs.js +32 -7
  88. package/src/ui/security.js +20 -23
  89. package/src/ui/server.js +52 -27
  90. package/src/ui/static/app.css +671 -575
  91. package/src/ui/static/favicon.svg +1 -1
  92. package/src/ui/static/fonts/DepartureMono-LICENSE.txt +93 -0
  93. package/src/ui/static/fonts/DepartureMono-Regular.woff2 +0 -0
  94. package/src/ui/static/index.html +10 -40
  95. package/src/ui/static/js/api.js +114 -6
  96. package/src/ui/static/js/app.js +144 -107
  97. package/src/ui/static/js/center.js +501 -0
  98. package/src/ui/static/js/charts.js +99 -18
  99. package/src/ui/static/js/copy.js +95 -62
  100. package/src/ui/static/js/dialog.js +152 -0
  101. package/src/ui/static/js/dom.js +0 -38
  102. package/src/ui/static/js/left.js +46 -0
  103. package/src/ui/static/js/menubar.js +170 -0
  104. package/src/ui/static/js/onboarding.js +104 -0
  105. package/src/ui/static/js/panels.js +186 -0
  106. package/src/ui/static/js/right.js +151 -0
  107. package/src/ui/static/js/state.js +66 -0
  108. package/src/ui/static/logo.svg +10 -0
  109. package/src/ui/static/mark.svg +3 -0
  110. package/src/utils/http.js +162 -13
  111. package/docs/METHODOLOGY.md +0 -321
  112. package/docs/commands/README.md +0 -23
  113. package/docs/commands/action.md +0 -21
  114. package/docs/commands/agents.md +0 -38
  115. package/docs/commands/deps.md +0 -115
  116. package/docs/commands/fix.md +0 -53
  117. package/docs/commands/hook.md +0 -69
  118. package/docs/commands/install.md +0 -53
  119. package/docs/commands/scan.md +0 -100
  120. package/docs/commands/skill.md +0 -58
  121. package/docs/compare/README.md +0 -25
  122. package/docs/compare/github.md +0 -60
  123. package/docs/compare/semgrep.md +0 -54
  124. package/docs/compare/snyk.md +0 -62
  125. package/docs/compare/socket.md +0 -78
  126. package/docs/compare/zap.md +0 -59
  127. package/docs/compliance-cra.md +0 -141
  128. package/docs/compliance-nis2.md +0 -168
  129. package/docs/dashboard.md +0 -244
  130. package/docs/evidence.md +0 -162
  131. package/docs/funding/due-diligence-checklist.md +0 -79
  132. package/docs/funding/nlnet-ngi-zero-draft.md +0 -273
  133. package/docs/funding/partner-one-pager.md +0 -84
  134. package/docs/funding/sponsor-tiers.md +0 -81
  135. package/docs/index.md +0 -81
  136. package/docs/internal-audit.md +0 -83
  137. package/docs/local-loop.md +0 -276
  138. package/docs/marketing.md +0 -151
  139. package/docs/owasp-wstg-coverage.md +0 -79
  140. package/docs/plan.md +0 -101
  141. package/docs/privacy.md +0 -38
  142. package/docs/references.bib +0 -549
  143. package/docs/references.md +0 -78
  144. package/docs/release-plan.md +0 -228
  145. package/docs/research/socket-positioning-notes.md +0 -183
  146. package/docs/use-cases/README.md +0 -14
  147. package/docs/use-cases/agencies.md +0 -71
  148. package/docs/use-cases/ai-coding-teams.md +0 -81
  149. package/docs/use-cases/eu-sme-compliance.md +0 -68
  150. package/docs/use-cases/open-source-maintainers.md +0 -75
  151. package/docs/use-cases/solo-founder.md +0 -65
  152. package/lib/deps/popular-packages.json +0 -1
  153. package/lib/deps/popular-pypi.json +0 -1
  154. package/src/ui/static/js/views/ai.js +0 -68
  155. package/src/ui/static/js/views/deps.js +0 -96
  156. package/src/ui/static/js/views/evidence.js +0 -115
  157. package/src/ui/static/js/views/findings.js +0 -165
  158. package/src/ui/static/js/views/history.js +0 -92
  159. package/src/ui/static/js/views/overview.js +0 -184
  160. package/src/ui/static/js/views/run.js +0 -349
  161. package/src/ui/static/js/views/settings.js +0 -67
package/CHANGELOG.md CHANGED
@@ -4,6 +4,270 @@ All notable changes to Penthera are documented here. Versioning follows [SemVer]
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.8.0-rc.1] - 2026-10-20
8
+
9
+ Release candidate for 1.8.0, published on npm's `next` dist-tag
10
+ (`npm install penthera@next`). It becomes 1.8.0 on `latest` after it has run
11
+ on real projects without a blocking issue.
12
+
13
+ ### Security
14
+
15
+ Fixes from a second independent review. Most also apply to 1.7.0; upgrading
16
+ is recommended.
17
+
18
+ - **Dependency scans fail closed.** An npm or Python package that could not be
19
+ read in full (a code file over 64 MB, more files than the reader takes, an
20
+ archive with inconsistent sizes or other structural anomalies, a matched
21
+ artifact that cannot be opened) is now `unscanned`: a high "could not be
22
+ scanned" finding that `penthera install` always holds for approval. The
23
+ Python scanner gained this state. Wheels are capped on the bytes actually
24
+ inflated. Pax global headers that set a size or path are refused. Deeply
25
+ nested `uv.lock`/`poetry.lock` files are a parse error, not a crash.
26
+ - **The fix loop and `fix --apply` run git hardened.** Commit and tag signing,
27
+ signing programs, attribute files and every configured filter driver are
28
+ overridden on every call (`--attr-source` on git 2.40+). Pathspecs are
29
+ literal. Writes are refused when the repository's own config sets
30
+ `filter.*`, `gpg.*` or `include.*`, or on git older than 2.31; the loop then
31
+ does not start, and its one message names the key and how to go on.
32
+ - **The fix loop keeps your uncommitted work.** Dirty files are read with
33
+ `status -z` and re-checked right before every write and commit. Reverts
34
+ restore the exact bytes from before the fix, and only while the file still
35
+ holds what penthera wrote (otherwise the fix is a `conflict` and the file is
36
+ left alone). Commits use `--only`. Plans that touch untracked or ignored
37
+ files are skipped, and every revert step runs even when one fails.
38
+ - **`applyDiff` is all-or-nothing and writes only regular files in the repo.**
39
+ Duplicate and nested paths are refused, a failed apply puts back what it
40
+ wrote, files are replaced through a temp file (never written through a hard
41
+ link), NTFS stream names and 8.3 aliases are refused, and added lines may not
42
+ contain control characters. Approval prompts show control characters as
43
+ escapes.
44
+ - **The pre-commit hook checks everything it should.** Staged content is read
45
+ by object id from NUL-separated output, type changes are included, files
46
+ with NUL bytes are scanned, and a staged file over 16 MB blocks the commit
47
+ (or warns, with `"largeFiles": "warn"`). `hook install` no longer writes
48
+ through a symlinked `pre-commit`.
49
+ - **Secret scanning checks every match.** A placeholder no longer hides a real
50
+ secret of the same rule later in the file. Only regular files are read, with
51
+ a per-file size cap.
52
+ - **Dashboard sessions are bound to the page.** The one-time token travels in
53
+ the URL fragment and is exchanged for a per-tab session sent as an
54
+ `Authorization` header; no cookie is set or accepted. Approvals carry the
55
+ sha256 of the diff shown, and a cut diff says so and needs an explicit
56
+ acknowledgement. A symlinked default `reports/` is refused and every write
57
+ re-checks the folder. Event ids keep counting past the buffer; requests,
58
+ bodies (413), finished runs and open streams are bounded. `--open` no
59
+ longer puts the token on a command line.
60
+ - **Evidence bundles** are built in a private folder and renamed into place,
61
+ and verification never follows a symlinked folder and caps what it reads.
62
+ - **HTTP responses are bounded.** Every body is read with a size cap (counted
63
+ after decompression) and a deadline that covers the body, not just the
64
+ headers. `--offline` compares host and port, and cross-origin redirects drop
65
+ credentials and do not replay request bodies.
66
+ - **Linear-time matching on untrusted text.** Agent-config exec patterns and
67
+ other agent and hook checks no longer backtrack on long input. The rule-pack
68
+ regex guard refuses ambiguous alternation and optional items inside repeated
69
+ groups and end-anchored rescans; community templates use the same guard.
70
+ - **Hostile repos no longer hang or crash scans**: a FIFO is never read, and
71
+ deeply nested JSON is handled; one unreadable agent config becomes a finding
72
+ instead of aborting the run.
73
+ - `--fix-model` never sends a file from outside the repo as context.
74
+ - Installing the hook through pre-commit.com no longer runs the test suite:
75
+ the `prepack` script is gone (publishing still runs `npm test`).
76
+ - Workflows that push or only read no longer keep credentials in the checkout.
77
+ - **The fix loop cannot game its own checker.** A fix diff, from a local
78
+ model or a recipe, may not edit tests, test runner config or the test
79
+ script, Penthera's policy, suppressions, baseline, lock or memory, CI
80
+ workflows, git hooks or lockfiles; `applyDiff` refuses it with `PROTECTED`
81
+ and says to make that change by hand. The loop verifies only against the
82
+ checker the run began with. "Could not fix" is now a recorded outcome
83
+ (`gave_up` in memory, `loopRun.gaveUp`, a summary line): the finding is not
84
+ retried in that run, and a give-up never counts against a recipe. Older
85
+ Penthera versions report a memory chain with `gave_up` events as malformed.
86
+
87
+ ### Added
88
+
89
+ - Release checks in CI (`.github/workflows/install-matrix.yml`): the packed
90
+ tarball is installed into an empty project and run with `npx penthera` on
91
+ Linux, macOS and Windows with Node 22 and 24 (setup wizard dry run, deps,
92
+ agents, repo scan, the pre-commit hook on a real commit, the dashboard's
93
+ token check, bundled rule pack signatures). An upgrade job installs 1.7.0
94
+ from npm, writes memory and dashboard state, upgrades to the tarball and
95
+ checks the old memory chain still verifies and grows. All of it runs under a
96
+ network guard that fails on anything past loopback.
97
+ - Docs as tests: `scripts/docs-commands.mjs` checks every command in the
98
+ README, `docs/` and the skill against `--help` and runs the offline ones on a
99
+ fixture, in `npm test` and against the installed package.
100
+ - Provenance check in CI (`scripts/ci/provenance.mjs`): every commit in a pull
101
+ request that names an AI co-author must carry an `AI-Assisted` line, and the
102
+ other way round.
103
+
104
+ ### Fixed
105
+
106
+ - Windows: `npx penthera` / `penthera init` in a git repository failed with
107
+ "Refusing to write outside the project" for its own `reports/` folder, because
108
+ git prints the repo root with forward slashes. Git roots are now native paths.
109
+ Found by the new Windows install checks.
110
+ - `penthera --help` lists `--rules-signers` and `--allow-unsigned-rules`. Both
111
+ worked and were documented in `docs/rule-packs.md`, but the help left them
112
+ out.
113
+ - `penthera ui`, Advanced mode: a run's transcript no longer shows a stray
114
+ "null" under its title.
115
+
116
+ ### Changed
117
+
118
+ - **`penthera ui` redesigned for people who are not programmers.** A first
119
+ visit runs a three-screen setup (what Penthera does, Simple or Advanced, the
120
+ project and a first check). Simple mode, the default, leads every project
121
+ with a one-sentence verdict ("Not ready to ship: 1 critical problem to fix
122
+ first."), lists problems in plain words, explains each one as what is wrong,
123
+ how sure and what to do, and tells a run as one sentence. Advanced keeps
124
+ everything, now as project tabs (Findings, Dependencies, AI tooling, History,
125
+ Proof) with a severity by confidence triage matrix. A menu bar replaces the
126
+ prompt bar and carries every action with its shortcut and the run status;
127
+ runs start from a New scan window; every change waits in its own window
128
+ (`y`, `n`, `q`). New look: a 1-bit "System" register of tiled windows, dither
129
+ patterns instead of greys, `#0000ed` as the one accent, Departure Mono (OFL,
130
+ self-hosted) for chrome, the serif Penthera wordmark, and a halftone field
131
+ whose density is the open risk. Both themes pass WCAG AA in every state.
132
+ `scripts/dashboard-screenshots.mjs` regenerates the docs screenshots.
133
+ - Smaller npm package: 797 kB to 657 kB packed, 2.3 MB to 1.7 MB unpacked. The
134
+ package ships only `docs/examples/` (the documentation lives on GitHub, and
135
+ README links resolve there), and the popular-package lists for the typosquat
136
+ check are stored gzipped. No behaviour change.
137
+ - Code cleanup, no behaviour change: one git runner (`lib/git.js`), one
138
+ temp-folder helper, one Markdown table-cell escape and one JSON fetch
139
+ helper replace their copies; unused exports and helpers are gone. CI now
140
+ runs `npm run lint` (ESLint, dev-only, minimal rules). Still one runtime
141
+ dependency.
142
+
143
+ ### Docs
144
+
145
+ - **Penthera is described as an open R&D project with a usable tool:** "an
146
+ open-source cyber security agent you can use today, and verify yourself."
147
+ The README, `docs/index.md`, `package.json`, the plugin and marketplace
148
+ manifests, the Agent Skill (trigger phrases kept), the GitHub Action and the
149
+ repository description carry the approved wording. The README has a "How it
150
+ is measured" section (method, evidence, tool) with Wilson intervals next to
151
+ the benchmark numbers, and stays under 14 KB.
152
+ - **One roadmap, one research plan.** `ROADMAP.md` now says what ships next,
153
+ starting with the 1.8.0 feature freeze. `docs/vision-2.0.md` is the research
154
+ plan and holds the quality gates from `docs/plan.md`. `docs/plan.md`,
155
+ `docs/release-plan.md` (v1.2 to v1.4) and the Socket positioning notes moved
156
+ to `docs/archive/`.
157
+ - **Every user-facing page names the question it answers**, for a starter ("is
158
+ my app safe to ship?") or a pro ("how do I put it in CI?"), and
159
+ `docs/index.md` has a Start here path from starter to pro.
160
+ - **Voice guide** (`docs/voice.md`): plain words, short sentences, numbers with
161
+ intervals over adjectives, limits next to claims, no hype. Every user-facing
162
+ page was edited against it.
163
+ - **Release cadence** in CONTRIBUTING: at most one minor release every 2 to 4
164
+ weeks, always through an `-rc.N` on npm's `next` tag, patches for fixes only,
165
+ and a feature freeze before each minor. Current freeze: 1.8.0 = main + #63.
166
+ - Fixed stale facts: SECURITY.md's supported versions (1.2.x to 1.7.x), README
167
+ anchors that no longer existed, Agent Skill links into `docs/` that broke in
168
+ the npm package since the docs stopped shipping there, and the partner brief
169
+ and due diligence notes that still called shipped features "in review".
170
+ - Limitations stated in full: the methodology's "Known limitations" now covers
171
+ every module (deps, AI tooling, fix loop), the evidence (small sample, wide
172
+ intervals, same-team benchmark, single labeller, uncalibrated confidence
173
+ labels), reproducibility, AI-assisted development, and compliance output. The
174
+ 2.0 research program adds "Threats to validity".
175
+ - GenAI disclosure: `docs/genai.md` states how Penthera is built with
176
+ generative AI (models, scale, review gates, licensing, logs), the README has a
177
+ short "How Penthera is built" section (107 of 117 non-merge commits up to
178
+ v1.7.0 written with Claude), and CONTRIBUTING requires an
179
+ `AI-Assisted` trailer on AI-assisted commits. Follows NLnet's generative AI
180
+ policy.
181
+ - `docs/MANIFESTO.md`: what Penthera is today (and is not), seven design
182
+ decisions with their costs and what would change them, and an FAQ. Written to
183
+ be challenged in Discussions.
184
+ - **After the 2026 agent incidents:** `docs/research/agent-incidents-2026.md`
185
+ says what the OpenAI–Hugging Face and Anthropic evaluation incidents mean
186
+ for Penthera, with sources and caveats. `docs/agents-safely.md` is a
187
+ one-page checklist for running AI agents. `docs/research/spec-harness-rules.md`
188
+ specifies planned `harness-*`, `sandbox-*` and `scorer-*` rules (not built
189
+ yet), and the research plan adds E7 and a draft pre-registration for E8
190
+ (do harness guardrails reduce judge tampering?).
191
+ - README: a "Building in public" section linking the CHANGELOG, the freeze, the
192
+ research in progress and the roadmap. Counts refreshed (57 references);
193
+ `npm run docs:numbers` now also counts the secret patterns in the core rule
194
+ pack (20, as the README says, not 8).
195
+ - `docs/genai.md` covers commits since v1.7.0 and how the agents that build
196
+ Penthera are contained; the manifesto says the fix loop cannot edit what
197
+ judges it.
198
+ - `docs/vision-2.0.md`: the plan for 2.0, covering the biggest gaps, an AI roadmap
199
+ (models propose, deterministic checks decide; local models first) and a
200
+ pre-registered research program with sample sizes and safety rules.
201
+ - **An 80-second walkthrough video** (`assets/walkthrough.mp4`, with a poster
202
+ and `walkthrough.vtt` captions) shows `npx penthera`, an offline scan of the
203
+ mock server, `penthera ui --demo` in Simple and Advanced mode, one fix
204
+ approved and the owner report. It is linked from the README and
205
+ `docs/index.md`. `scripts/media/walkthrough.mjs` renders it from demo data
206
+ only, and the Demo media workflow re-renders it on every release.
207
+ - **The terminal GIFs are re-rendered** in the dashboard's black and white
208
+ look. `scan.tape` now writes the README hero (`assets/demo.gif`) directly
209
+ and scans with `--offline`. The `agents` and `deps --diff` tapes rendered a
210
+ "Cannot find module" error, because they ran `bin/penthera.js` by a
211
+ relative path after changing folder; they use an absolute path now.
212
+
213
+ ## [1.7.0] - 2026-10-19
214
+
215
+ One view and one command. `npx penthera` now sets Penthera up in a project:
216
+ it detects what is there, asks what to check, runs it offline and offers the
217
+ hook, the PR workflow and the dashboard. `penthera ui` is a single view with
218
+ side panels. The README is rewritten, and the methodology and references
219
+ follow APA 7.
220
+
221
+ ### Added
222
+
223
+ - **`penthera init`, the setup wizard** (also `npx penthera` with no arguments
224
+ in a terminal). It detects the project offline (git, framework, npm and
225
+ Python lockfiles, agent config, a dev server on localhost, an existing hook
226
+ or workflow), asks one checklist question, runs the code, dependency and AI
227
+ tooling checks (and the running app, only after you confirm it is yours),
228
+ then shows the grade per area, the three things to fix first and one report
229
+ folder, `reports/penthera-<date>/`. It then offers, one yes/no each, the
230
+ pre-commit hook, a `.github/workflows/penthera.yml` pinned to the release
231
+ commit SHA (shown as a diff first), `reports/` in `.gitignore`, the fix loop
232
+ and the dashboard. `--yes` takes the safe defaults and never scans a URL,
233
+ runs the fix loop or opens the dashboard; `--dry-run` prints the plan.
234
+ Nothing is committed or pushed. See [docs/commands/init.md](docs/commands/init.md).
235
+
236
+ ### Changed
237
+
238
+ - **`penthera ui` is one view, like the Claude Code desktop app.** A
239
+ collapsible left sidebar lists projects (grade, open findings, last scan)
240
+ and recent runs grouped by project, with "+ New scan" on top and settings
241
+ behind a gear. The centre is one scrolling stream: the selected project's
242
+ header (grade, severity bar, trend sparkline), what changed since the last
243
+ scan, "Fix first" and the findings; a running scan or fix loop streams there
244
+ as a transcript with Apply / Skip / Stop inline on each diff. A prompt-style
245
+ bar starts scans, dependency checks, AI tooling audits and the fix loop. The
246
+ collapsible right panel stacks Environment (egress, folder, git branch),
247
+ Memory, Dependencies, AI tooling, Evidence and Changes cards, and shows a
248
+ finding's detail when you pick one. `[` and `]` toggle the side panels, which
249
+ become drawers at narrow widths. Calmer chrome, one primary action at a time;
250
+ the themes, `--demo` and every security property are unchanged. New
251
+ `GET /api/env` reads the branch through the agent's hardened git runner.
252
+ - `penthera-scan` keeps the URL-first wizard that `penthera` used to open.
253
+
254
+ ### Docs
255
+
256
+ - README rewritten in the voice of "Penthera: Cyber Security Agent". The
257
+ dashboard screenshots now sit directly under the demo GIF; "Get started" leads
258
+ with one command (`npx penthera`); features are grouped as before you deploy,
259
+ what you build with, and after you ship; and a new "Research and
260
+ methodology" section gives the method, the benchmark numbers, and how to cite
261
+ Penthera. About 12 KB, down from 19 KB.
262
+ - `docs/references.md` is rendered in APA 7th edition style from
263
+ `docs/references.bib`, sorted by first author within each topic, with an
264
+ anchor per BibTeX key. Editors for the three Springer proceedings and the NDSS
265
+ proceedings titles were added from Crossref. A test covers the formatter.
266
+ - `docs/METHODOLOGY.md` uses APA in-text citations, opens with an abstract and
267
+ a "How to cite" block that mirrors `CITATION.cff`, and now cites every
268
+ reference. A test fails if a citation does not resolve or a reference is
269
+ never cited, and the internal audit checks the "How to cite" version.
270
+
7
271
  ## [1.6.1] - 2026-10-19
8
272
 
9
273
  The GitHub Action gets its Marketplace name. Nothing else changes.
@@ -82,6 +346,38 @@ reproduced; each fix has a regression test that fails without it.
82
346
 
83
347
  ### Added
84
348
 
349
+ - **Signed rule packs** (`lib/rules/`, [docs/rule-packs.md](docs/rule-packs.md)):
350
+ detection data (secret formats, hidden-instruction and exec patterns, IOC
351
+ lists, typosquat targets, Nuclei-compatible templates) ships as versioned
352
+ directories. Each pack has a `pack.json` index of SHA-256 hashes, signed
353
+ with `ssh-keygen -Y sign -n penthera-rules`. Penthera verifies the signature
354
+ (in Node; ssh-keygen is not needed at run time), then every hash, the schema
355
+ and every regex, before it loads anything. Packs arrive bundled in a release,
356
+ or by path with `--rules <dir>` (plus `--rules-signers <file>` for your own
357
+ keys). Unsigned packs are refused unless `--allow-unsigned-rules`, which
358
+ warns loudly. Nothing is ever fetched
359
+ - `penthera rules list` and `penthera rules verify <dir>`; tooling in
360
+ `scripts/rules/` (`build-pack.mjs`, maintainer-only `sign-pack.sh`,
361
+ `check-bundled.mjs`). The publish workflow now refuses to stage a release
362
+ whose bundled packs are not signed by a key in `lib/rules/allowed_signers`
363
+ - ReDoS guard for data-supplied regexes (`lib/rules/regex-guard.js`): length
364
+ cap, no backreferences or lookaround, no nested quantifiers, no alternation
365
+ under unbounded repeats, no unbounded quantifier that every start position
366
+ can rescan, and a backtracking budget for overlapping quantifier chains.
367
+ Fuzz-tested: everything it accepts runs in milliseconds on adversarial
368
+ input. The v1.1.1 template guard moved here too, rewritten from a regex
369
+ (itself polynomial on hostile pattern strings, flagged by CodeQL) into a
370
+ linear scan that also catches deeper nesting
371
+ - Bundled `core` pack: 12 AI-provider key formats, the credential-path
372
+ instruction pattern, two exec patterns and the `.env` template moved out of
373
+ code. Behaviour is identical; a test compares against a snapshot of the old
374
+ built-ins
375
+ - Bundled `ioc-2025-2026` pack (**unsigned in this PR; the maintainer signs it
376
+ before release**): s1ngularity/nx versions (GHSA-cxm3-wv7p-598c), Shai-Hulud
377
+ (StepSecurity's list, exfil URL, `bundle.js` by hash), Shai-Hulud 2.0 (Wiz
378
+ Research's CSV, loader file names) and postmark-mcp 1.0.16 to 1.0.18 with its
379
+ exfil domain. `penthera deps` reports hits as critical `deps-ioc` findings
380
+ that cite the source, wherever the package sits in the tree, installed or not
85
381
  - **Internal testing audit** (`npm run audit:internal`), the release gate:
86
382
  tests, benchmark drift, a self-scan against `audit/baseline.json`, a CLI
87
383
  smoke matrix, package contents and size, zero third-party egress offline,