chore(ui): harden npm package audit workflow

This commit is contained in:
Alan Buscaglia committed 2026-05-22 13:33:47 +02:00
1 parent 3a096b1750
commit 87ed5595e2
7 files changed
+194 -39

No files matched your search

+3 -3
View File
@@ -16,7 +16,7 @@ deps = "uv sync"
[[pre-start]]
reminder = "echo '>> Reminder: activate the venv in this shell with: source .venv/bin/activate'"
# Background: pnpm install runs while you start working.
# Tail logs via `wt config state logs`.
# Background: avoid running UI package lifecycle scripts before the branch is reviewed.
# Run `cd ui && pnpm install` explicitly when UI dependencies are needed.
[post-start]
ui = "cd ui && pnpm install"
ui = "echo '>> UI dependencies were not installed automatically. Run: cd ui && pnpm install'"
+4
View File
@@ -46,6 +46,7 @@ Use these skills for detailed patterns on-demand:
| `prowler-commit` | Professional commits (conventional-commits) | [SKILL.md](skills/prowler-commit/SKILL.md) |
| `prowler-pr` | Pull request conventions | [SKILL.md](skills/prowler-pr/SKILL.md) |
| `prowler-docs` | Documentation style guide | [SKILL.md](skills/prowler-docs/SKILL.md) |
| `prowler-npm-security-audit` | npm/pnpm supply-chain audit patterns | [SKILL.md](skills/prowler-npm-security-audit/SKILL.md) |
| `django-migration-psql` | Django migration best practices for PostgreSQL | [SKILL.md](skills/django-migration-psql/SKILL.md) |
| `postgresql-indexing` | PostgreSQL indexing, EXPLAIN, monitoring, maintenance | [SKILL.md](skills/postgresql-indexing/SKILL.md) |
| `prowler-attack-paths-query` | Create Attack Paths openCypher queries | [SKILL.md](skills/prowler-attack-paths-query/SKILL.md) |
@@ -68,6 +69,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
| After creating/modifying a skill | `skill-sync` |
| App Router / Server Actions | `nextjs-16` |
| Auditing check-to-requirement mappings as a cloud auditor | `prowler-compliance` |
| Auditing npm/pnpm package security | `prowler-npm-security-audit` |
| Building AI chat features | `ai-sdk-5` |
| Committing changes | `prowler-commit` |
| Configuring MCP servers in agentic workflows | `gh-aw` |
@@ -107,6 +109,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
| Review changelog format and conventions | `prowler-changelog` |
| Reviewing JSON:API compliance | `jsonapi` |
| Reviewing compliance framework PRs | `prowler-compliance-review` |
| Reviewing npm supply-chain policy | `prowler-npm-security-audit` |
| Running makemigrations or pgmakemigrations | `django-migration-psql` |
| Syncing compliance framework with upstream catalog | `prowler-compliance` |
| Testing RLS tenant isolation | `prowler-test-api` |
@@ -124,6 +127,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
| Using Zustand stores | `zustand-5` |
| Working on MCP server tools | `prowler-mcp` |
| Working on Prowler UI structure (actions/adapters/types/hooks) | `prowler-ui` |
| Working on npm package, lockfile, or pnpm configuration | `prowler-npm-security-audit` |
| Working on task | `tdd` |
| Working with Prowler UI test helpers/pages | `prowler-test-ui` |
| Working with Tailwind classes | `tailwind-4` |
+122
View File
@@ -0,0 +1,122 @@
---
name: prowler-npm-security-audit
description: >
Audits npm/pnpm package manager configuration and dependency changes against
npm security best practices, Prowler UI conventions, and supply-chain
hardening requirements. Trigger: PRs or repo audits that touch package.json,
lockfiles, pnpm-workspace.yaml, npmrc, CI install steps, Docker installs,
security dependency updates, or package supply-chain policy.
license: Apache-2.0
metadata:
author: prowler-cloud
version: "1.0"
scope: [root, ui]
auto_invoke:
- "Auditing npm/pnpm package security"
- "Reviewing npm supply-chain policy"
- "Working on npm package, lockfile, or pnpm configuration"
---
## When to Use
Use this skill when reviewing or changing:
- `ui/package.json`, `ui/pnpm-lock.yaml`, `ui/pnpm-workspace.yaml`, or `ui/.npmrc`
- UI package-manager migrations, dependency bumps, or lockfile-only changes
- CI, Docker, worktree, or local setup paths that run package installs
- Security-only dependency remediation workflows for npm packages
- npm package-health evidence, trust policy, lifecycle scripts, or supply-chain controls
Do **not** recommend enabling general UI dependency-update automation in Dependabot or Renovate. Prowler intentionally avoids bot-driven UI version bumps; only security remediation should be considered.
## Critical Patterns
Base the audit on [lirantal/npm-security-best-practices](https://github.com/lirantal/npm-security-best-practices) and Prowler's UI rules.
| Area | What to verify | Red flags |
| --- | --- | --- |
| Lifecycle scripts | `allowBuilds` is explicit and `strictDepBuilds: true` is enabled | Broad or undocumented build allowances; root lifecycle scripts mutating git state |
| Exotic dependencies | `blockExoticSubdeps: true` or equivalent is enabled | Git, tarball, HTTP, file, link, or workspace specs in committed lockfiles without rationale |
| Cooldown | `minimumReleaseAge` exists and security remediation respects the repository policy | Bot-driven general UI version bumps in Dependabot/Renovate; emergency security updates without review evidence |
| Trust policy | `trustPolicy: no-downgrade` is enabled | Open-ended `trustPolicyExclude` entries; exceptions without evidence |
| Determinism | Lockfile committed; CI/Docker use frozen installs; package manager pinned | Floating package managers; future major ranges not exercised in CI |
| CI coverage | Existing gates remain intact | Package-manager migration removes format, lint, tests, audit, or build gates |
| Overrides | Overrides are scoped and documented | Global overrides that force unrelated consumers or incompatible majors |
| Package health | New direct dependencies have rationale and package-health evidence | New packages without maintenance/license/vulnerability/provenance review |
| Local safety | Installs do not unexpectedly mutate shared git state | `postinstall` installs hooks or rewrites files without opt-in |
| Dependency confusion | Private scopes have registry mapping; no plaintext tokens | Unscoped private package names, committed tokens, or ambiguous registries |
## Prowler Audit Scope
Primary files:
```text
ui/package.json
ui/pnpm-lock.yaml
ui/pnpm-workspace.yaml
ui/.npmrc
ui/Dockerfile
.github/workflows/ui-*.yml
.github/dependabot.yml
.github/renovate.json
.config/wt.toml
ui/dependency-log.json
```
Also inspect package install scripts under `ui/scripts/` when lifecycle behavior changes.
## Review Output Format
Use this structure for review findings:
```markdown
Verdict: pass | pass-with-issues | fail
## Findings
### Blocker
### High
### Medium
### Low
### Questions
## Positive controls observed
## Checks run
## Not checked
```
Each finding must include:
- file path and line reference when possible;
- evidence;
- risk;
- smallest suggested fix.
## Commands
```bash
# Inspect package/security config
cd ui
pnpm audit --audit-level high
pnpm install --frozen-lockfile --prefer-offline
pnpm run healthcheck
# Search for exotic lockfile sources
rg -n "git\+|github:|bitbucket:|gitlab:|http://|https://|tarball:|file:|link:|workspace:" ui/pnpm-lock.yaml
# Confirm UI workflows keep expected gates
rg -n "pnpm run (healthcheck|format:check|audit|build|test)" .github/workflows/ui-*.yml
```
## Constraints
- Default to read-only review unless explicitly asked to fix.
- Do not treat frontend package hiding as a security boundary; backend authorization still matters.
- Do not invent package-health claims. Fetch primary evidence when needed.
- Prefer concrete, actionable findings over generic best-practice prose.
+32 -29
View File
@@ -19,35 +19,38 @@
When performing these actions, ALWAYS invoke the corresponding skill FIRST:
| Action | Skill |
| -------------------------------------------------------------- | ------------------- |
| Add changelog entry for a PR or feature | `prowler-changelog` |
| App Router / Server Actions | `nextjs-16` |
| Building AI chat features | `ai-sdk-5` |
| Committing changes | `prowler-commit` |
| Create PR that requires changelog entry | `prowler-changelog` |
| Creating Zod schemas | `zod-4` |
| Creating a git commit | `prowler-commit` |
| Creating/modifying Prowler UI components | `prowler-ui` |
| Fixing bug | `tdd` |
| Implementing feature | `tdd` |
| Modifying component | `tdd` |
| Refactoring code | `tdd` |
| Review changelog format and conventions | `prowler-changelog` |
| Testing hooks or utilities | `vitest` |
| Update CHANGELOG.md in any component | `prowler-changelog` |
| Using Zustand stores | `zustand-5` |
| Working on Prowler UI structure (actions/adapters/types/hooks) | `prowler-ui` |
| Working on task | `tdd` |
| Working with Prowler UI test helpers/pages | `prowler-test-ui` |
| Working with Tailwind classes | `tailwind-4` |
| Writing Playwright E2E tests | `playwright` |
| Writing Prowler UI E2E tests | `prowler-test-ui` |
| Writing React component tests | `vitest` |
| Writing React components | `react-19` |
| Writing TypeScript types/interfaces | `typescript` |
| Writing Vitest tests | `vitest` |
| Writing unit tests for UI | `vitest` |
| Action | Skill |
| -------------------------------------------------------------- | ---------------------------- |
| Add changelog entry for a PR or feature | `prowler-changelog` |
| App Router / Server Actions | `nextjs-16` |
| Auditing npm/pnpm package security | `prowler-npm-security-audit` |
| Building AI chat features | `ai-sdk-5` |
| Committing changes | `prowler-commit` |
| Create PR that requires changelog entry | `prowler-changelog` |
| Creating Zod schemas | `zod-4` |
| Creating a git commit | `prowler-commit` |
| Creating/modifying Prowler UI components | `prowler-ui` |
| Fixing bug | `tdd` |
| Implementing feature | `tdd` |
| Modifying component | `tdd` |
| Refactoring code | `tdd` |
| Review changelog format and conventions | `prowler-changelog` |
| Reviewing npm supply-chain policy | `prowler-npm-security-audit` |
| Testing hooks or utilities | `vitest` |
| Update CHANGELOG.md in any component | `prowler-changelog` |
| Using Zustand stores | `zustand-5` |
| Working on Prowler UI structure (actions/adapters/types/hooks) | `prowler-ui` |
| Working on npm package, lockfile, or pnpm configuration | `prowler-npm-security-audit` |
| Working on task | `tdd` |
| Working with Prowler UI test helpers/pages | `prowler-test-ui` |
| Working with Tailwind classes | `tailwind-4` |
| Writing Playwright E2E tests | `playwright` |
| Writing Prowler UI E2E tests | `prowler-test-ui` |
| Writing React component tests | `vitest` |
| Writing React components | `react-19` |
| Writing TypeScript types/interfaces | `typescript` |
| Writing Vitest tests | `vitest` |
| Writing unit tests for UI | `vitest` |
---
+20 -4
View File
@@ -100,10 +100,18 @@ git clone git@github.com:prowler-cloud/ui.git
pnpm install
```
**Note:** The `pnpm install` command will automatically configure prek Git hooks for code quality checks. If hooks are not installed, run from the repo root:
**Note:** The `pnpm install` command does not configure Git hooks automatically. To install prek hooks for code quality checks, run one of the following:
From `ui/`:
```bash
prek install
pnpm run setup:hooks
```
From the monorepo root:
```bash
cd ui && pnpm run setup:hooks
```
#### Run the development server
@@ -124,10 +132,18 @@ pnpm run dev
## Git Hooks
The UI uses [prek](https://github.com/j178/prek) for pre-commit checks, configured in [`.pre-commit-config.yaml`](.pre-commit-config.yaml). `pnpm install` runs the postinstall script that installs hooks automatically. To re-install manually:
The UI uses [prek](https://github.com/j178/prek) for pre-commit checks, configured in [`.pre-commit-config.yaml`](.pre-commit-config.yaml). Git hook setup is opt-in so package installs do not mutate shared git state automatically. To install or re-install manually:
From `ui/`:
```bash
prek install --overwrite
pnpm run setup:hooks
```
From the monorepo root:
```bash
cd ui && pnpm run setup:hooks
```
On each commit, prek runs Prettier and ESLint against the staged files, plus a project-wide TypeScript check and the unit tests related to the staged changes. The full Next.js build runs in CI, not on commit.
+1
View File
@@ -17,6 +17,7 @@
"lint:fix": "eslint . --fix --max-warnings 40",
"lint:knip": "knip --max-issues 494",
"lint:knip:fix": "knip --fix --max-issues 494",
"setup:hooks": "node scripts/setup-git-hooks.js",
"start": "next start",
"start:standalone": "node .next/standalone/server.js",
"test": "vitest run",
+12 -3
View File
@@ -5,7 +5,11 @@
*
* This script runs after npm install to:
* 1. Update dependency log (if the script exists)
* 2. Setup git hooks (if the script exists)
* 2. Harden the MSW service worker when present
*
* Git hook installation is intentionally opt-in because postinstall runs during
* normal package installs and should not mutate shared git hook state unless the
* developer asked for onboarding setup.
*/
const fs = require("fs");
@@ -89,5 +93,10 @@ runScriptIfExists("./update-dependency-log.js", "deps:log");
// Keep this before setup-git-hooks because that script can exit the process.
hardenMswServiceWorker();
// Run git hooks setup
runScriptIfExists("./setup-git-hooks.js", "setup-git-hooks");
if (process.env.PROWLER_UI_SETUP_GIT_HOOKS === "1") {
runScriptIfExists("./setup-git-hooks.js", "setup-git-hooks");
} else {
console.log(
"Skip git hooks setup (run `pnpm run setup:hooks` or set PROWLER_UI_SETUP_GIT_HOOKS=1 to opt in)",
);
}