penthera 1.7.0 → 1.8.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.
Files changed (163) hide show
  1. package/CHANGELOG.md +315 -0
  2. package/README.md +139 -76
  3. package/SECURITY.md +8 -6
  4. package/docs/examples/pr-dependency-review.yml +1 -1
  5. package/lib/adaptive-probes.js +3 -3
  6. package/lib/advisories/evidence.js +248 -0
  7. package/lib/advisories/index.js +228 -0
  8. package/lib/advisories/products.js +83 -0
  9. package/lib/advisories/versions.js +65 -0
  10. package/lib/agents/hidden-content.js +122 -11
  11. package/lib/agents/index.js +26 -6
  12. package/lib/agents/lock.js +33 -5
  13. package/lib/agents/rules.js +33 -4
  14. package/lib/compliance/index.js +4 -4
  15. package/lib/crawler.js +12 -15
  16. package/lib/deps/capabilities.js +21 -5
  17. package/lib/deps/findings.js +309 -0
  18. package/lib/deps/index.js +13 -272
  19. package/lib/deps/iocs.js +74 -0
  20. package/lib/deps/lockfile.js +3 -8
  21. package/lib/deps/online.js +8 -3
  22. package/lib/deps/popular-packages.json.gz +0 -0
  23. package/lib/deps/popular-pypi.json.gz +0 -0
  24. package/lib/deps/python/capabilities.js +16 -3
  25. package/lib/deps/python/index.js +5 -1
  26. package/lib/deps/python/lockfiles.js +11 -5
  27. package/lib/deps/python/source.js +75 -26
  28. package/lib/deps/python/toml.js +15 -3
  29. package/lib/deps/source.js +28 -9
  30. package/lib/deps/typosquat.js +30 -5
  31. package/lib/fix/apply.js +253 -34
  32. package/lib/fix/index.js +7 -4
  33. package/lib/fix/model.js +25 -5
  34. package/lib/fix/util.js +6 -2
  35. package/lib/fuzzer.js +3 -3
  36. package/lib/git.js +65 -0
  37. package/lib/hook/index.js +157 -73
  38. package/lib/hook/policy.js +10 -4
  39. package/lib/install/index.js +4 -7
  40. package/lib/machine.js +0 -13
  41. package/lib/memory/store.js +11 -4
  42. package/lib/nuclei-loader.js +0 -25
  43. package/lib/owasp-wstg.js +4 -0
  44. package/lib/plugins.js +1 -1
  45. package/lib/provenance.js +1 -0
  46. package/lib/recon.js +12 -31
  47. package/lib/references.json +224 -0
  48. package/lib/retirejs.js +4 -4
  49. package/lib/rules/advisories/advisories.json +186 -0
  50. package/lib/rules/advisories/eol.json +413 -0
  51. package/lib/rules/advisories/pack.json +20 -0
  52. package/lib/rules/advisories/pack.json.sig +6 -0
  53. package/lib/rules/allowed_signers +13 -0
  54. package/lib/rules/core/agent-exec.json +29 -0
  55. package/lib/rules/core/agent-instructions.json +17 -0
  56. package/lib/rules/core/pack.json +30 -0
  57. package/lib/rules/core/pack.json.sig +6 -0
  58. package/lib/rules/core/secrets.json +161 -0
  59. package/lib/rules/core/templates.json +52 -0
  60. package/lib/rules/index.js +107 -0
  61. package/lib/rules/ioc-2025-2026/files.json +43 -0
  62. package/lib/rules/ioc-2025-2026/hosts.json +35 -0
  63. package/lib/rules/ioc-2025-2026/pack.json +25 -0
  64. package/lib/rules/ioc-2025-2026/pack.json.sig +6 -0
  65. package/lib/rules/ioc-2025-2026/packages.json +1048 -0
  66. package/lib/rules/pack.js +452 -0
  67. package/lib/rules/regex-guard.js +81 -9
  68. package/lib/rules/sshsig.js +205 -0
  69. package/lib/templates.js +24 -20
  70. package/lib/tmp.js +21 -0
  71. package/lib/whitebox/frameworks.js +1 -1
  72. package/lib/whitebox/secrets.js +117 -41
  73. package/package.json +12 -4
  74. package/scripts/rules/build-pack.mjs +80 -0
  75. package/scripts/rules/check-bundled.mjs +30 -0
  76. package/scripts/rules/sign-pack.sh +32 -0
  77. package/skills/penthera/SKILL.md +16 -15
  78. package/src/agent/git.js +147 -14
  79. package/src/agent/loop.js +165 -46
  80. package/src/cli/agent.js +11 -5
  81. package/src/cli/deps.js +0 -2
  82. package/src/cli/detect.js +14 -7
  83. package/src/cli/fix.js +26 -8
  84. package/src/cli/hook.js +2 -1
  85. package/src/cli/onboarding.js +14 -6
  86. package/src/cli/report-outputs.js +1 -0
  87. package/src/cli/rules.js +144 -0
  88. package/src/cli/ui.js +43 -10
  89. package/src/cli.js +24 -1
  90. package/src/report/evidence.js +105 -21
  91. package/src/report/footer.js +1 -1
  92. package/src/report/md-escape.js +8 -0
  93. package/src/scan-repo.js +6 -0
  94. package/src/scan-url.js +11 -3
  95. package/src/ui/api/data.js +39 -6
  96. package/src/ui/api/routes.js +44 -11
  97. package/src/ui/api/runs.js +32 -7
  98. package/src/ui/security.js +20 -23
  99. package/src/ui/server.js +52 -27
  100. package/src/ui/static/app.css +583 -213
  101. package/src/ui/static/favicon.svg +1 -1
  102. package/src/ui/static/fonts/DepartureMono-LICENSE.txt +93 -0
  103. package/src/ui/static/fonts/DepartureMono-Regular.woff2 +0 -0
  104. package/src/ui/static/index.html +5 -4
  105. package/src/ui/static/js/api.js +114 -6
  106. package/src/ui/static/js/app.js +81 -42
  107. package/src/ui/static/js/center.js +246 -133
  108. package/src/ui/static/js/charts.js +99 -18
  109. package/src/ui/static/js/copy.js +68 -9
  110. package/src/ui/static/js/dialog.js +152 -0
  111. package/src/ui/static/js/left.js +23 -60
  112. package/src/ui/static/js/menubar.js +170 -0
  113. package/src/ui/static/js/onboarding.js +104 -0
  114. package/src/ui/static/js/panels.js +186 -0
  115. package/src/ui/static/js/right.js +69 -188
  116. package/src/ui/static/js/state.js +36 -5
  117. package/src/ui/static/logo.svg +10 -0
  118. package/src/ui/static/mark.svg +3 -0
  119. package/src/utils/http.js +162 -13
  120. package/docs/METHODOLOGY.md +0 -375
  121. package/docs/commands/README.md +0 -24
  122. package/docs/commands/action.md +0 -21
  123. package/docs/commands/agents.md +0 -38
  124. package/docs/commands/deps.md +0 -115
  125. package/docs/commands/fix.md +0 -53
  126. package/docs/commands/hook.md +0 -69
  127. package/docs/commands/init.md +0 -114
  128. package/docs/commands/install.md +0 -53
  129. package/docs/commands/scan.md +0 -100
  130. package/docs/commands/skill.md +0 -58
  131. package/docs/compare/README.md +0 -25
  132. package/docs/compare/github.md +0 -60
  133. package/docs/compare/semgrep.md +0 -54
  134. package/docs/compare/snyk.md +0 -62
  135. package/docs/compare/socket.md +0 -78
  136. package/docs/compare/zap.md +0 -59
  137. package/docs/compliance-cra.md +0 -141
  138. package/docs/compliance-nis2.md +0 -168
  139. package/docs/dashboard.md +0 -187
  140. package/docs/evidence.md +0 -162
  141. package/docs/funding/due-diligence-checklist.md +0 -79
  142. package/docs/funding/nlnet-ngi-zero-draft.md +0 -273
  143. package/docs/funding/partner-one-pager.md +0 -84
  144. package/docs/funding/sponsor-tiers.md +0 -81
  145. package/docs/index.md +0 -81
  146. package/docs/internal-audit.md +0 -83
  147. package/docs/local-loop.md +0 -276
  148. package/docs/marketing.md +0 -151
  149. package/docs/owasp-wstg-coverage.md +0 -79
  150. package/docs/plan.md +0 -102
  151. package/docs/privacy.md +0 -38
  152. package/docs/references.bib +0 -559
  153. package/docs/references.md +0 -119
  154. package/docs/release-plan.md +0 -228
  155. package/docs/research/socket-positioning-notes.md +0 -183
  156. package/docs/use-cases/README.md +0 -14
  157. package/docs/use-cases/agencies.md +0 -71
  158. package/docs/use-cases/ai-coding-teams.md +0 -81
  159. package/docs/use-cases/eu-sme-compliance.md +0 -68
  160. package/docs/use-cases/open-source-maintainers.md +0 -75
  161. package/docs/use-cases/solo-founder.md +0 -65
  162. package/lib/deps/popular-packages.json +0 -1
  163. package/lib/deps/popular-pypi.json +0 -1
@@ -1,81 +0,0 @@
1
- # The AI-tooling supply chain: for teams adopting Claude Code or Cursor
2
-
3
- ## The problem
4
-
5
- A coding agent runs with your developer's permissions. What it can do is decided
6
- by files that rarely get reviewed: `.mcp.json`, `.claude/settings.json`, hooks,
7
- skills, plugins, `CLAUDE.md`, `AGENTS.md` and `.cursor/` rules. Some of these
8
- arrive from a teammate's pull request, some from a marketplace, some from a
9
- blog post. In 2025 and 2026 attackers used exactly these paths: skills with
10
- instructions hidden from human reviewers, MCP servers launched with `npx -y` on
11
- whatever version was latest, and npm worms that wrote to `~/.claude` and ran the
12
- `claude` CLI on the victim's machine.
13
-
14
- ## What to run
15
-
16
- ```bash
17
- npx penthera agents --home # this repo plus your user-level Claude Code, Cursor and Claude Desktop config
18
- npx penthera agents ./some-skill # vet a downloaded skill before you install it
19
- npx penthera agents --pin # record hashes in penthera.lock; later runs show what changed
20
- ```
21
-
22
- For a team, add the pre-commit hook so agent-config changes are checked before
23
- they are committed, and the GitHub Action in `agents` mode on pull requests:
24
-
25
- ```bash
26
- npx penthera hook install
27
- ```
28
-
29
- ```yaml
30
- - uses: danoszz/penthera@<release-commit-sha>
31
- with:
32
- mode: agents
33
- ```
34
-
35
- ## What you get
36
-
37
- From Penthera's own test fixture of a deliberately bad setup (abridged):
38
-
39
- ```
40
- Grade F (0/100)
41
- Found 1 skills · 4 MCP servers · 3 hooks · 0 plugins · 1 rule files
42
- Lock none (run with --pin)
43
-
44
- CRIT MCP server "installer" launches by downloading and running code
45
- .mcp.json
46
- CRIT SessionStart hook downloads and runs code
47
- .claude/settings.json
48
- HIGH Instructions hidden in an HTML comment
49
- skills/helper/SKILL.md
50
- HIGH Text addressed to a security scanner
51
- skills/helper/SKILL.md
52
- HIGH PreToolUse (*) hook auto-approves tool calls
53
- .claude/settings.json
54
- HIGH Permission allow-list grants `Bash(*)`
55
- .claude/settings.json
56
- MED MCP server "filesystem" runs an unpinned package via npx
57
- .mcp.json
58
- ```
59
-
60
- Each finding names the OWASP MCP Top 10 and Agentic Top 10 ids it maps to, and
61
- the rule that fired is readable in [`lib/agents/`](../../lib/agents/). The audit
62
- is offline and read-only: no model judges the skill, so a skill cannot talk its
63
- way past it. [More on `penthera agents`](../commands/agents.md).
64
-
65
- `penthera deps` also flags packages that write to `~/.claude`, `~/.cursor` or
66
- `.mcp.json`, or run the `claude`, `gemini` or `q` CLIs, which is how the
67
- s1ngularity attack used local AI tools. [More on `penthera deps`](../commands/deps.md).
68
-
69
- ## What it does not do
70
-
71
- - It reads configuration and files on disk. It does not watch what an agent does
72
- at run time, and it does not sandbox anything.
73
- - It does not know whether a remote MCP server is trustworthy. It checks how the
74
- server is launched and configured, not what the service behind it does.
75
- - It does not check the registries for newly published malicious skills or
76
- packages. A registry-watching service such as
77
- [Socket](../compare/socket.md) covers that.
78
- - Its rules cover the patterns in the [methodology](../METHODOLOGY.md). A new
79
- trick needs a new rule and a release.
80
-
81
- [All use cases](README.md) · [Back to the README](../../README.md)
@@ -1,68 +0,0 @@
1
- # Evidence for NIS2 and the CRA: for EU SMEs
2
-
3
- ## The problem
4
-
5
- NIS2 puts a duty of care on in-scope organisations, written into national law
6
- (the Cyberbeveiligingswet in the Netherlands, the NIS2-wet in Belgium). The
7
- Cyber Resilience Act adds reporting duties for manufacturers of products with
8
- digital elements, with deadlines measured in hours. Large customers now send
9
- security questionnaires as part of procurement. A small company has to show
10
- that it tests, fixes and records, without a compliance team or a budget for a
11
- platform.
12
-
13
- ## What to run
14
-
15
- ```bash
16
- penthera --assessment-init assessment.json # once: the organisational measures a scanner cannot test
17
- penthera https://staging.example.com --repo . \
18
- --framework nis2 --readiness --assessment assessment.json \
19
- --sbom sbom.cdx.json --evidence evidence/2026-10-19 --sign-key ~/.ssh/id_ed25519
20
- ```
21
-
22
- That run writes the scan, an Article 21(2) coverage table, a readiness report
23
- with every measure marked met, partial, gap or not applicable, a CycloneDX SBOM,
24
- and a hashed, SSH-signed evidence bundle an auditor can verify with standard
25
- tools.
26
-
27
- Around it:
28
-
29
- ```bash
30
- penthera --policy-pack ./policies --org "Your Company" --readiness --assessment assessment.json
31
- penthera https://example.com --readiness --assessment assessment.json --questionnaire questions.txt
32
- penthera --cra-init cra.json && penthera --cra cra.json # CRA Article 14 timeline and drafts
33
- penthera --repo . --aibom aibom.cdx.json # CycloneDX 1.6 AI-BOM
34
- ```
35
-
36
- ## What you get
37
-
38
- The CRA helper prints the deadlines and writes draft reports, marking every fact
39
- it still needs:
40
-
41
- ```
42
- CRA Article 14 report drafts written to cra-reports.md
43
- Early warning (24 hours): n/a, set aware_at
44
- Vulnerability notification (72 hours): n/a, set aware_at
45
- Final report (14 days after a corrective or mitigating measure is available): ...
46
- ⚠️ No valid `aware_at` timestamp, so deadlines can't be computed. Set when you became aware (ISO 8601) and re-run.
47
- ```
48
-
49
- The questionnaire helper answers each question from your scan and
50
- self-assessment, cites the evidence, and marks anything it cannot map as
51
- `NEEDS HUMAN INPUT` instead of guessing. Guides:
52
- [NIS2](../compliance-nis2.md), [CRA](../compliance-cra.md),
53
- [evidence bundles](../evidence.md).
54
-
55
- ## What it does not do
56
-
57
- - It is readiness tooling, not a certification and not legal advice. Whether you
58
- are in scope, and what is proportionate for you, is for you and your advisers
59
- to decide.
60
- - It covers the technical, testable part of the duty of care. Policies,
61
- training, backups and MFA come from your self-assessment; Penthera records
62
- what you attest, it cannot check it.
63
- - It does not file anything. Reports to a CSIRT or ENISA are drafts for you to
64
- review and submit.
65
- - Jurisdiction details ship for the Netherlands today; other member states are
66
- configuration still to be added.
67
-
68
- [All use cases](README.md) · [Back to the README](../../README.md)
@@ -1,75 +0,0 @@
1
- # For open-source maintainers
2
-
3
- ## The problem
4
-
5
- Your project is someone else's dependency. A compromised maintainer account, a
6
- malicious contributor pull request that bumps a lockfile, or a leaked publish
7
- token can turn it into the attack. Most maintainers do this unpaid, without a
8
- security budget, and many cannot send their dependency list or code to a vendor
9
- service, or would rather not sign up for one.
10
-
11
- ## What to run
12
-
13
- On every pull request that touches the lockfile, comment what the change lets
14
- code do:
15
-
16
- ```yaml
17
- - uses: danoszz/penthera@<release-commit-sha> # pin to a release commit
18
- with:
19
- mode: deps
20
- fail-on: none
21
- ```
22
-
23
- The full workflow, with permissions and a paths filter, is in
24
- [`docs/examples/pr-dependency-review.yml`](../examples/pr-dependency-review.yml).
25
- The action runs Penthera from its own checkout: no install from npm and no
26
- registry lookups. On pull requests from forks the token is read-only, so the
27
- diff goes to the job summary instead of a comment.
28
-
29
- Locally, before you cut a release:
30
-
31
- ```bash
32
- npx penthera deps --base origin/main # what changed in the tree since main
33
- npx penthera --repo . # secrets, including AI provider keys
34
- npx penthera agents # the agent config you ship (CLAUDE.md, .mcp.json, skills/)
35
- npx penthera hook install # block secrets and risky config at commit time
36
- ```
37
-
38
- ## What you get
39
-
40
- ```
41
- ▲ net-helper 1.0.0 → 1.1.0 + network, whole environment
42
- node_modules/net-helper/index.js:3 const https = require('https');
43
- node_modules/net-helper/index.js:5 const body = JSON.stringify(process.env);
44
- ```
45
-
46
- A patch release that starts reading the whole environment next to a network call
47
- is the shape of most credential-stealing packages. The diff shows it with
48
- `file:line` evidence, whether or not an advisory exists yet.
49
- [More on `penthera deps`](../commands/deps.md) and [the action](../commands/action.md).
50
-
51
- If your project ships agent skills or MCP configuration, `penthera agents` on
52
- your own repo is a reasonable release check too: it is what your users' tools
53
- will load.
54
-
55
- ## How Penthera handles its own releases
56
-
57
- The same practices are worth copying. Penthera releases are published with npm
58
- provenance through trusted publishing and are staged: each version waits on npm
59
- until a maintainer approves it with 2FA. CI actions are pinned by SHA, CodeQL
60
- runs on every push, and the
61
- [OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/danoszz/penthera)
62
- is public. See [`.github/workflows/publish.yml`](../../.github/workflows/publish.yml).
63
-
64
- ## What it does not do
65
-
66
- - Dependency analysis covers npm and Python. The install firewall and the
67
- `--online` registry checks are npm only for now.
68
- - It does not track CVEs in your dependencies. Keep Dependabot or a similar
69
- service on for that ([how they fit](../compare/github.md)).
70
- - It does not watch the registry for your package being republished by someone
71
- else. Enable 2FA and trusted publishing on npm for that.
72
- - A capability is what code *can* do, not proof of intent. Many good packages
73
- use the network; the diff is there so a person can look.
74
-
75
- [All use cases](README.md) · [Back to the README](../../README.md)
@@ -1,65 +0,0 @@
1
- # Before launch: for solo founders and vibecoders
2
-
3
- ## The problem
4
-
5
- You built the app in weeks, much of it with an AI assistant. It works. You have
6
- not had time to check the things that tend to go wrong in AI-written apps: an
7
- API route that returns any user's data if you change the id, an OpenAI key in a
8
- client bundle, a missing security header, a CORS policy of `*`, a login with no
9
- rate limit. Nobody on the team does security, because there is no team.
10
-
11
- ## What to run
12
-
13
- Start the app locally, then:
14
-
15
- ```bash
16
- npx penthera http://localhost:3000 --repo . # the running app and its source, together
17
- npx penthera fix --plan --repo . # fixes for what it can fix, as diffs
18
- npx penthera hook install # stop secrets at commit time from now on
19
- ```
20
-
21
- Or ask your coding agent, with the [Agent Skill](../commands/skill.md)
22
- installed: "scan my app on localhost:3000 and fix what you find".
23
-
24
- Before you deploy, run the same scan against your preview URL. Only scan systems
25
- you own.
26
-
27
- ## What you get
28
-
29
- ```
30
- Findings
31
-
32
- HIGH IDOR/BOLA: GET /api/users/{user_id}
33
- http://localhost:3000/api/users/1 → 200
34
- HIGH OAuth open redirect
35
- http://localhost:3000/api/oauth/callback?redirect_uri=... → 302
36
- MED Missing Content-Security-Policy
37
- MED No login rate limiting detected
38
- http://localhost:3000/api/login → 401
39
- LOW Missing X-Frame-Options
40
- INFO Missing Referrer-Policy
41
-
42
- ──────────────────────────────────────────────────────────
43
- 2 high · 5 medium · 2 low · 2 info
44
- ```
45
-
46
- `penthera fix --plan` then prints a unified diff per fix it knows (security
47
- headers, cookie flags, a CORS allowlist, a login rate limit, moving a
48
- hardcoded secret to an environment variable) for Next.js, Express, Fastify and
49
- Hono. Nothing is written until you apply a plan by id, and the repo is
50
- re-scanned afterwards to confirm the finding is gone.
51
- [More on fixes](../commands/fix.md).
52
-
53
- ## What it does not do
54
-
55
- - It is not a penetration test by a person. It checks known classes of problem;
56
- it will not find a flaw in your business logic, such as a coupon that can be
57
- applied twice.
58
- - It does not fix IDOR or auth design for you. It points at the route; the fix
59
- is yours.
60
- - It does not watch production yet. Scheduled checks are on the
61
- [roadmap](../../ROADMAP.md).
62
- - A clean scan is not proof of safety. Every finding has a confidence label, and
63
- probes that could not run are listed as inconclusive rather than passed.
64
-
65
- [All use cases](README.md) · [Back to the README](../../README.md)