penthera 1.5.0 → 1.6.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 (104) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/README.md +128 -663
  3. package/bin/scan.js +19 -0
  4. package/docs/commands/README.md +23 -0
  5. package/docs/commands/action.md +21 -0
  6. package/docs/commands/agents.md +38 -0
  7. package/docs/commands/deps.md +115 -0
  8. package/docs/commands/fix.md +53 -0
  9. package/docs/commands/hook.md +69 -0
  10. package/docs/commands/install.md +53 -0
  11. package/docs/commands/scan.md +100 -0
  12. package/docs/commands/skill.md +58 -0
  13. package/docs/compare/README.md +25 -0
  14. package/docs/compare/github.md +60 -0
  15. package/docs/compare/semgrep.md +54 -0
  16. package/docs/compare/snyk.md +62 -0
  17. package/docs/compare/socket.md +78 -0
  18. package/docs/compare/zap.md +59 -0
  19. package/docs/dashboard.md +244 -0
  20. package/docs/evidence.md +8 -4
  21. package/docs/examples/github-actions-deps.yml +4 -4
  22. package/docs/examples/github-actions-scan.yml +4 -4
  23. package/docs/index.md +9 -0
  24. package/docs/internal-audit.md +83 -0
  25. package/docs/marketing.md +151 -0
  26. package/docs/plan.md +4 -3
  27. package/docs/privacy.md +38 -0
  28. package/docs/references.bib +10 -0
  29. package/docs/references.md +1 -0
  30. package/docs/research/socket-positioning-notes.md +183 -0
  31. package/docs/use-cases/README.md +14 -0
  32. package/docs/use-cases/agencies.md +71 -0
  33. package/docs/use-cases/ai-coding-teams.md +81 -0
  34. package/docs/use-cases/eu-sme-compliance.md +68 -0
  35. package/docs/use-cases/open-source-maintainers.md +75 -0
  36. package/docs/use-cases/solo-founder.md +65 -0
  37. package/lib/blackbox/email-dns.js +5 -0
  38. package/lib/compliance/questionnaire.js +4 -2
  39. package/lib/deps/capabilities.js +49 -12
  40. package/lib/deps/index.js +290 -30
  41. package/lib/deps/lockfile.js +25 -2
  42. package/lib/deps/popular-pypi.json +1 -0
  43. package/lib/deps/python/capabilities.js +447 -0
  44. package/lib/deps/python/index.js +234 -0
  45. package/lib/deps/python/lockfiles.js +359 -0
  46. package/lib/deps/python/source.js +396 -0
  47. package/lib/deps/python/toml.js +219 -0
  48. package/lib/deps/report.js +37 -6
  49. package/lib/deps/source.js +149 -24
  50. package/lib/deps/typosquat.js +24 -13
  51. package/lib/fix/apply.js +83 -19
  52. package/lib/hook/index.js +41 -8
  53. package/lib/install/index.js +59 -18
  54. package/lib/install/policy.js +17 -5
  55. package/lib/memory/repo-suppress.js +11 -3
  56. package/lib/references.json +77 -0
  57. package/lib/remediation/index.js +9 -0
  58. package/lib/retirejs.js +69 -17
  59. package/lib/rules/regex-guard.js +368 -0
  60. package/lib/templates.js +13 -6
  61. package/lib/tls.js +7 -0
  62. package/lib/whitebox/frameworks.js +8 -5
  63. package/lib/whitebox/secrets.js +20 -7
  64. package/package.json +7 -3
  65. package/skills/penthera/SKILL.md +23 -5
  66. package/src/cli/deps.js +60 -5
  67. package/src/cli/evidence.js +14 -4
  68. package/src/cli/install.js +14 -5
  69. package/src/cli/report-outputs.js +25 -2
  70. package/src/cli/ui.js +89 -0
  71. package/src/cli.js +19 -7
  72. package/src/report/audience.js +10 -10
  73. package/src/report/evidence.js +33 -14
  74. package/src/report/footer.js +11 -0
  75. package/src/report/markdown.js +6 -3
  76. package/src/report/md-escape.js +16 -0
  77. package/src/reporter.js +1 -0
  78. package/src/scan-url.js +5 -1
  79. package/src/ui/api/data.js +309 -0
  80. package/src/ui/api/demo.js +464 -0
  81. package/src/ui/api/routes.js +134 -0
  82. package/src/ui/api/runs.js +243 -0
  83. package/src/ui/api/summarize.js +451 -0
  84. package/src/ui/security.js +153 -0
  85. package/src/ui/server.js +186 -0
  86. package/src/ui/static/app.css +723 -0
  87. package/src/ui/static/favicon.svg +1 -0
  88. package/src/ui/static/index.html +57 -0
  89. package/src/ui/static/js/api.js +29 -0
  90. package/src/ui/static/js/app.js +138 -0
  91. package/src/ui/static/js/charts.js +207 -0
  92. package/src/ui/static/js/copy.js +79 -0
  93. package/src/ui/static/js/dom.js +120 -0
  94. package/src/ui/static/js/format.js +42 -0
  95. package/src/ui/static/js/theme.js +10 -0
  96. package/src/ui/static/js/typer.js +99 -0
  97. package/src/ui/static/js/views/ai.js +68 -0
  98. package/src/ui/static/js/views/deps.js +96 -0
  99. package/src/ui/static/js/views/evidence.js +115 -0
  100. package/src/ui/static/js/views/findings.js +165 -0
  101. package/src/ui/static/js/views/history.js +92 -0
  102. package/src/ui/static/js/views/overview.js +184 -0
  103. package/src/ui/static/js/views/run.js +349 -0
  104. package/src/ui/static/js/views/settings.js +67 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,169 @@ All notable changes to Penthera are documented here. Versioning follows [SemVer]
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.6.1] - 2026-10-19
8
+
9
+ The GitHub Action gets its Marketplace name. Nothing else changes.
10
+
11
+ ### Changed
12
+
13
+ - The GitHub Action is listed on the Marketplace as "Penthera: Cyber Security
14
+ Agent". The `uses:` reference is unchanged.
15
+
16
+ ## [1.6.0] - 2026-10-19
17
+
18
+ Hardening and reach. An independent 360 review found three high-severity bugs, two of them reproduced; all are fixed with regression tests, and the open code-scanning alerts went from 18 to the 2 that need a second maintainer. `penthera deps` now covers Python, `penthera ui` adds a local dashboard (black or white, in the project blue), and every release passes an internal audit first. 1.5.0 was never published to npm; this release includes it.
19
+
20
+ ### Security
21
+
22
+ - Cleared the open code-scanning alerts. The community-template regex guard
23
+ was itself a polynomial regex; it is now a linear scan, and an invalid
24
+ extractor regex no longer aborts a template. Markdown table cells escape
25
+ backslashes first (one shared helper). `<script>` extraction is a tokenizer
26
+ that accepts any case and junk in closing tags. Release workflow: read-only
27
+ top-level token, hash-verified npm, no dependency cache. Docker base image
28
+ pinned by digest. fast-check property tests fuzz the untrusted-input parsers.
29
+
30
+ Fixes from an independent 360 review of `main`. The first three were
31
+ reproduced; each fix has a regression test that fails without it.
32
+
33
+ - **High: tar desync hid install scripts from the install firewall and
34
+ `penthera deps`.** A GNU base-256 size field parsed as 0, the reader lost its
35
+ place, and 512 zero bytes then read as end-of-archive, so `package.json` and
36
+ everything after it went unscanned and the package looked clean. The tar
37
+ reader now handles base-256 sizes and pax `size=`, checks every header
38
+ checksum and fails closed on any anomaly (malformed size, truncation, data
39
+ after the end marker). A package whose archive or `package.json` cannot be
40
+ read is reported as "could not be scanned" (high) and always needs approval
41
+ in `penthera install`; a lockfile `hasInstallScript` that the scan cannot
42
+ find is a high finding and is always denied (except the known benign case
43
+ of a package that ships only prebuilt `.node` binaries, like fsevents 2.x)
44
+ - **High: `applyDiff` wrote through a dangling symlink out of the repo.** Every
45
+ path component is now `lstat`-ed and any symlink is refused; creates use
46
+ `O_CREAT|O_EXCL|O_NOFOLLOW`
47
+ - **High: `.GIT/` bypassed the `.git` guard on case-insensitive file systems.**
48
+ Any path segment that is `.git` in any case, at any depth (plus HFS+ and
49
+ NTFS aliases such as `.git.` and `GIT~1`), is refused, and fix diffs may no
50
+ longer touch `.gitmodules`
51
+ - PR comments escape HTML, Markdown links and images, `@` mentions, `#` refs
52
+ and bare URLs in package names, versions, paths and snippets from the
53
+ lockfile, keep code spans on one line, and cap each field at 200 characters
54
+ - `penthera evidence verify` no longer passes a signed bundle whose signer was
55
+ not checked: a signature only verifies against `--allowed-signers`, and a
56
+ manifest that declares a signature with no `.sig` fails. Unsigned bundles
57
+ pass with an UNSIGNED warning; new `--require-signature` fails them
58
+ - `penthera install` refuses git, hosted-git and tarball-URL specs, and lockfile
59
+ entries resolved outside the configured registries, unless
60
+ `--allow-non-registry` is passed. `npm cache add` runs with `--ignore-scripts`
61
+ - `penthera install` applies with `npm ci`, so npm installs exactly the
62
+ reviewed lockfile and cannot re-resolve before scripts run
63
+ - `penthera deps` now honours `--audience`, `--report-template`, `--evidence`
64
+ (with `--sign-key`) and `--baseline`, and rejects scan-only flags such as
65
+ `--memory` with a clear error instead of ignoring them
66
+ - Gzip and tar size limits are enforced while unpacking (`maxOutputLength` on
67
+ gunzip, per-file and total caps in the tar reader)
68
+ - The pre-commit hook reads `penthera.policy.json` and `penthera.suppress.json`
69
+ from the git index, warns when an unstaged copy is being ignored, and never
70
+ follows a staged symlink in agent config out of the repo
71
+ - `--base` refs are validated (no leading `-`, a plain ref charset) and passed
72
+ after `--end-of-options`, in `penthera deps` and in the GitHub Action's fetch
73
+ - `git status` and friends on a scanned repo (fix apply, evidence bundle git
74
+ info, `--base` reads) run with `core.fsmonitor=false`, no hooks and no
75
+ transports
76
+ - The Action only edits marker comments posted by `github-actions[bot]`
77
+ - `--offline` no longer makes DNS TXT/MX lookups for SPF/DMARC
78
+ - Report citations now cover `dependency-risk`, `license`, `agent-config` and
79
+ the machine-audit categories; `license` findings get their own remediation
80
+ - Docs: `docs/plan.md` lists only what v1.5.0 shipped; top-level `--help`
81
+ lists `penthera hook`
82
+
83
+ ### Added
84
+
85
+ - **Internal testing audit** (`npm run audit:internal`), the release gate:
86
+ tests, benchmark drift, a self-scan against `audit/baseline.json`, a CLI
87
+ smoke matrix, package contents and size, zero third-party egress offline,
88
+ supply chain and version/docs checks, written to `audit/REPORT.md`. Runs
89
+ weekly in CI. See [docs/internal-audit.md](docs/internal-audit.md)
90
+ - **Marketing automation that drafts, never posts** (`docs/marketing.md`): no
91
+ social-media tokens, no tracking, no auto-posting; every workflow SHA-pinned
92
+ with least-privilege permissions and a `workflow_dispatch` dry run
93
+ - Release post drafts: `publish.yml` writes a LinkedIn (~600 characters) and
94
+ an X/Bluesky (≤280) post from the CHANGELOG section to the job summary and
95
+ a collapsed "Share this release" section in the GitHub Release
96
+ (`scripts/marketing/release-post.mjs`)
97
+ - Incident radar (`incident-radar.yml`, daily): new npm and PyPI malware
98
+ advisories from the public GitHub Advisory Database become
99
+ `incident-radar` issues with affected versions, an IOC checklist and a
100
+ draft "check if you're affected" post. Popular packages get their own
101
+ issue (at most 5 per run); the rest are batched into one issue
102
+ - Demo media (`demo-media.yml`): VHS tapes in `assets/tapes/` for a URL
103
+ scan, `penthera agents` and `penthera deps --diff`, re-rendered on release
104
+ and opened as a PR
105
+ - Monthly stats issue (`monthly-stats.yml`): npm downloads, stars, forks,
106
+ skills.sh installs, dependents and merged PRs, with month-over-month
107
+ changes and a draft post
108
+ - Contributor flywheel (`contributor-flywheel.yml`): when fewer than 3
109
+ `good first issue` issues are open, one reminder lists the
110
+ `TODO(good-first-issue)` markers in the code
111
+ - **Report footer**: Markdown reports, audience reports, the PR comment and
112
+ the evidence bundle end with one line, "Checked by Penthera, open-source
113
+ security for the apps and AI systems you ship". Never in SARIF or JSON.
114
+ `--no-footer` (or `footer: "false"` in the Action) leaves it off. Evidence
115
+ bundles now include a `README.md`
116
+ - **Python support for `penthera deps`** (`lib/deps/python/`): reads `uv.lock`,
117
+ `poetry.lock`, `pdm.lock`, `Pipfile.lock` and `requirements*.txt` (pinned and
118
+ `--hash` lines, `-r` includes, pip-compile `# via` for direct deps), and the
119
+ installed `.venv` / `venv` / `--venv <path>` through `dist-info` `METADATA`
120
+ and `RECORD`, with no pip or interpreter. A Python tokenizer blanks comments
121
+ and docstrings; patterns cover shell, network, env bulk access and
122
+ exfiltration, eval/exec/compile, computed imports, unpickling, native
123
+ extensions, obfuscation (`exec` of base64/zlib payloads, encoded blobs,
124
+ PyArmor) and the same AI-agent indicators as npm. Install-time and
125
+ persistence code: `setup.py` custom commands, `.pth` import lines (scored by
126
+ what the imported module can do), `.pth` files no distribution owns, code that
127
+ writes `.pth` files, and installed files that no longer match `RECORD`. Same
128
+ capability ids, findings, diff, PR comment and SARIF as npm; projects with
129
+ both get one combined report
130
+ - `--diff` / `--base` for Python lockfiles. Old versions come from pip's HTTP
131
+ cache (sha256 from the lockfile) or uv's cache (recorded hash), else they are
132
+ marked "not compared"
133
+ - PyPI typosquat check against a vendored list of the top 8,000 PyPI projects
134
+ (`lib/deps/popular-pypi.json`, PEP 503 normalised, refreshed at release time by
135
+ `scripts/refresh-popular-pypi.mjs`), including `python-` / `-py` affixes
136
+
137
+ ### Changed
138
+
139
+ - The live test suites (`pentest-live`, `-recon`, `-adaptive`) are opt-in:
140
+ they run only with `PENTEST_BASE_URL` or a `pentest.config.js`, instead of
141
+ probing whatever listens on `localhost:3000` during `npm test`.
142
+
143
+ ### Fixed
144
+
145
+ - Repo scans skip nested git repositories and worktrees (any subfolder with
146
+ its own `.git`, such as coding-agent worktrees under `.claude/worktrees`),
147
+ instead of reporting their files as this repo's, and no longer follow
148
+ symlinked folders out of the repo.
149
+ - The secret scanner no longer reports a value that is only a template
150
+ placeholder (`apiKey: "${key}"`, `{{ api_key }}`) as a hardcoded secret.
151
+ - `penthera-scan --help` and `--version` exit 0 instead of starting the wizard.
152
+ - The example workflows in `docs/examples/` pin actions by commit SHA.
153
+
154
+ ### Docs
155
+
156
+ - README cut from about 45 KB to under 20 KB. It opens with a three-command
157
+ "Try it in 60 seconds" block, a "Who it is for" table, and a "By the
158
+ numbers" block (benchmark, rule and test counts, references, release
159
+ provenance). Per-command detail moved to `docs/commands/` and network use to
160
+ `docs/privacy.md`.
161
+ - Use-case pages in `docs/use-cases/`: before launch, teams adopting coding
162
+ agents, open-source maintainers, EU SMEs with NIS2 or CRA duties, agencies.
163
+ - Comparison pages in `docs/compare/` for Socket, Snyk, GitHub Dependabot and
164
+ code scanning, OWASP ZAP and Semgrep, framed as using the tools together, with
165
+ sources and a last-checked date.
166
+ - `docs/research/socket-positioning-notes.md`: how Socket presents itself and
167
+ what Penthera's docs took from it.
168
+ - `npm run docs:numbers` prints the counts quoted in the README.
169
+
7
170
  ## [1.5.0] - 2026-10-19
8
171
 
9
172
  Blocks problems at commit time, adds license policy, and extends the EU
@@ -79,6 +242,22 @@ Requires Node 22+. Upgrading from 1.1.x or 1.2.x needs no config changes.
79
242
 
80
243
  ### Added
81
244
 
245
+ - **`penthera ui [--open] [--port 0] [--project <dir>] [--reports <dir>] [--demo]`**:
246
+ a local dashboard on 127.0.0.1 (random port, one-time URL), styled as a
247
+ 1-bit early-90s Mac desktop with a terminal inside, in dark and light themes.
248
+ Overview (posture per project, severity mix, findings over time, time to
249
+ fix, hosts contacted; a three-step start when there is no data yet),
250
+ Findings (filters, a plain-words explanation, evidence, sources, fix diff),
251
+ Run (scan, check dependencies, audit AI tooling, or the fix loop with an
252
+ Apply / Skip / Stop dialog on every diff, live output over SSE), History
253
+ (new, fixed and still open between two scans), Dependencies, AI tooling,
254
+ Evidence (create a bundle from the latest scan, verify in one click,
255
+ download the auditor report) and Settings. Reads only the chosen folders and
256
+ `~/.penthera`; no network, no new dependencies, no build step. Host check
257
+ against DNS rebinding, one-time token swapped for an HttpOnly SameSite=Strict
258
+ cookie, Origin check and JSON-only bodies on state changes, strict CSP, no
259
+ CORS, rate-limited unauthenticated requests, allowlisted static files.
260
+ Penthera scans it clean. `--demo` seeds fake data. See `docs/dashboard.md`
82
261
  - **GitHub Action** (`uses: danoszz/penthera@<sha>`, `action.yml`): on PRs that
83
262
  change the lockfile it runs `penthera deps --base <PR base>`, upserts one PR
84
263
  comment marked `<!-- penthera-deps -->` (edited in place on every push), and