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.
- package/CHANGELOG.md +179 -0
- package/README.md +128 -663
- package/bin/scan.js +19 -0
- package/docs/commands/README.md +23 -0
- package/docs/commands/action.md +21 -0
- package/docs/commands/agents.md +38 -0
- package/docs/commands/deps.md +115 -0
- package/docs/commands/fix.md +53 -0
- package/docs/commands/hook.md +69 -0
- package/docs/commands/install.md +53 -0
- package/docs/commands/scan.md +100 -0
- package/docs/commands/skill.md +58 -0
- package/docs/compare/README.md +25 -0
- package/docs/compare/github.md +60 -0
- package/docs/compare/semgrep.md +54 -0
- package/docs/compare/snyk.md +62 -0
- package/docs/compare/socket.md +78 -0
- package/docs/compare/zap.md +59 -0
- package/docs/dashboard.md +244 -0
- package/docs/evidence.md +8 -4
- package/docs/examples/github-actions-deps.yml +4 -4
- package/docs/examples/github-actions-scan.yml +4 -4
- package/docs/index.md +9 -0
- package/docs/internal-audit.md +83 -0
- package/docs/marketing.md +151 -0
- package/docs/plan.md +4 -3
- package/docs/privacy.md +38 -0
- package/docs/references.bib +10 -0
- package/docs/references.md +1 -0
- package/docs/research/socket-positioning-notes.md +183 -0
- package/docs/use-cases/README.md +14 -0
- package/docs/use-cases/agencies.md +71 -0
- package/docs/use-cases/ai-coding-teams.md +81 -0
- package/docs/use-cases/eu-sme-compliance.md +68 -0
- package/docs/use-cases/open-source-maintainers.md +75 -0
- package/docs/use-cases/solo-founder.md +65 -0
- package/lib/blackbox/email-dns.js +5 -0
- package/lib/compliance/questionnaire.js +4 -2
- package/lib/deps/capabilities.js +49 -12
- package/lib/deps/index.js +290 -30
- package/lib/deps/lockfile.js +25 -2
- package/lib/deps/popular-pypi.json +1 -0
- package/lib/deps/python/capabilities.js +447 -0
- package/lib/deps/python/index.js +234 -0
- package/lib/deps/python/lockfiles.js +359 -0
- package/lib/deps/python/source.js +396 -0
- package/lib/deps/python/toml.js +219 -0
- package/lib/deps/report.js +37 -6
- package/lib/deps/source.js +149 -24
- package/lib/deps/typosquat.js +24 -13
- package/lib/fix/apply.js +83 -19
- package/lib/hook/index.js +41 -8
- package/lib/install/index.js +59 -18
- package/lib/install/policy.js +17 -5
- package/lib/memory/repo-suppress.js +11 -3
- package/lib/references.json +77 -0
- package/lib/remediation/index.js +9 -0
- package/lib/retirejs.js +69 -17
- package/lib/rules/regex-guard.js +368 -0
- package/lib/templates.js +13 -6
- package/lib/tls.js +7 -0
- package/lib/whitebox/frameworks.js +8 -5
- package/lib/whitebox/secrets.js +20 -7
- package/package.json +7 -3
- package/skills/penthera/SKILL.md +23 -5
- package/src/cli/deps.js +60 -5
- package/src/cli/evidence.js +14 -4
- package/src/cli/install.js +14 -5
- package/src/cli/report-outputs.js +25 -2
- package/src/cli/ui.js +89 -0
- package/src/cli.js +19 -7
- package/src/report/audience.js +10 -10
- package/src/report/evidence.js +33 -14
- package/src/report/footer.js +11 -0
- package/src/report/markdown.js +6 -3
- package/src/report/md-escape.js +16 -0
- package/src/reporter.js +1 -0
- package/src/scan-url.js +5 -1
- package/src/ui/api/data.js +309 -0
- package/src/ui/api/demo.js +464 -0
- package/src/ui/api/routes.js +134 -0
- package/src/ui/api/runs.js +243 -0
- package/src/ui/api/summarize.js +451 -0
- package/src/ui/security.js +153 -0
- package/src/ui/server.js +186 -0
- package/src/ui/static/app.css +723 -0
- package/src/ui/static/favicon.svg +1 -0
- package/src/ui/static/index.html +57 -0
- package/src/ui/static/js/api.js +29 -0
- package/src/ui/static/js/app.js +138 -0
- package/src/ui/static/js/charts.js +207 -0
- package/src/ui/static/js/copy.js +79 -0
- package/src/ui/static/js/dom.js +120 -0
- package/src/ui/static/js/format.js +42 -0
- package/src/ui/static/js/theme.js +10 -0
- package/src/ui/static/js/typer.js +99 -0
- package/src/ui/static/js/views/ai.js +68 -0
- package/src/ui/static/js/views/deps.js +96 -0
- package/src/ui/static/js/views/evidence.js +115 -0
- package/src/ui/static/js/views/findings.js +165 -0
- package/src/ui/static/js/views/history.js +92 -0
- package/src/ui/static/js/views/overview.js +184 -0
- package/src/ui/static/js/views/run.js +349 -0
- 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
|