Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions .claude/agents/security-reviewer.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
---
name: security-reviewer
description: Reviews event-bus and file-store code for credential handling, injection risks, and insecure defaults
description: Reviews file-store code for credential handling, path traversal, and insecure defaults
tools: ["Read", "Grep", "Glob"]
---

You are a security reviewer for a Fastify plugin library that handles cloud credentials and message broker connections.
You are a security reviewer for `@stackbox-dev/fp-plugins`, a Fastify plugin library
that wraps cloud storage (AWS S3, GCS, Azure Blob, MinIO, local filesystem) behind one
`FileStore` interface (`src/file-store.ts`).

Review the changed or specified files for:

1. **Credential exposure**: Hardcoded secrets, credentials logged to stdout, tokens in error messages
2. **Unsafe deserialization**: `JSON.parse` without try/catch or validation, especially on message payloads from external brokers
3. **Injection risks**: Unsanitized input in the `/event-bus/publish/:event` endpoint, template literal injection in queue/topic names
4. **Insecure defaults**: Missing TLS, overly permissive CORS, unauthenticated endpoints exposed by default
5. **Resource leaks**: Unclosed connections, missing cleanup in error paths, containers not stopped in tests
6. **Dependency concerns**: Known vulnerable patterns in AWS SDK, Azure SDK, GCP SDK, NATS, or RabbitMQ client usage
1. **Credential exposure**: hardcoded secrets, credentials or endpoints logged, tokens
leaking into error messages
2. **Path traversal**: `filepath` arguments are joined onto a base directory in
`LocalFileStore` and used as object keys in the cloud providers — check whether new
code lets `..` escape `LOCAL_STORAGE_DIR` or weakens key handling
3. **Insecure defaults**: env-var fallbacks that silently point at the wrong
region/endpoint, TLS disabled, anonymous credentials
4. **Resource leaks**: unclosed streams or clients, missing cleanup in error paths
5. **SDK misuse**: unsafe patterns in AWS/GCP/Azure SDK usage, e.g. disabling
certificate validation

Report findings with severity (critical/high/medium/low), file location, and a suggested fix.
Report findings with severity (critical/high/medium/low), file location, and a
suggested fix.
10 changes: 7 additions & 3 deletions .claude/skills/gen-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ Generate a Jest test file for a given source module in this project.
- Test files live alongside source: `src/foo.ts` → `src/foo.spec.ts`.
Provider-specific specs are suffixed: `file-store.<provider>.spec.ts`
- `ts-jest` preset, `testEnvironment: "node"`
- Cloud SDKs are **mocked**, never containerised — `jest.mock("@google-cloud/storage")`
and friends. This package has no Docker-based tests and no `testcontainers`
dependency; do not add one
- Cloud SDKs are **mocked** in unit specs — `jest.mock("@google-cloud/storage")` and
friends. The one exception is `src/file-store.minio.integration.spec.ts`, which talks
to a real MinIO over the S3 wire protocol; it self-skips unless `MINIO_TEST_ENDPOINT`
is set and runs via `pnpm run test:integration`. No `testcontainers` dependency; do
not add one
- Behavioural changes to S3/MinIO paths need cases in the integration spec too —
mocked tests cannot catch SDK behaviour changes (see CLAUDE.md, Testing)
- `LocalFileStore` is the exception: test it against the real filesystem using
`fs.promises.mkdtemp` under `os.tmpdir()`, and clean up in `afterEach`
- Save and restore `process.env` around tests that set provider env vars
Expand Down
7 changes: 4 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- **Clean**: `pnpm run clean` — removes `dist`
- **Transpile**: `pnpm run transpile` — TypeScript compilation only

These are the only scripts defined in `package.json`. CI (`.github/workflows/`) runs
The only other scripts in `package.json` are `prepare` (husky) and `prepublishOnly`
(build before publish). CI (`.github/workflows/`) runs
`pnpm install --frozen-lockfile`, then lint, build and test on Node 24; the package declares
`engines: node >=22`.

Expand Down Expand Up @@ -57,8 +58,8 @@ Registered via `fastify-plugin` (v6) and decorates the Fastify instance with
## Testing

Jest + ts-jest. Tests live beside their source in `src/` as `*.spec.ts`, split by
provider: `file-store.local.spec.ts`, `.gcs.`, `.s3.`, `.azure.`, plus the original
`file-store.spec.ts` and `integration.spec.ts`. Coverage is 100% on statements,
provider: `file-store.local.spec.ts`, `.gcs.`, `.s3.`, `.azure.`, plus
`file-store.spec.ts`, `integration.spec.ts` and `utils.spec.ts`. Coverage is 100% on statements,
branches, functions and lines — keep it there.

Cloud SDKs are mocked with `jest.mock(...)`; `LocalFileStore` runs against the real
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

## Setup

This repository uses **pnpm** (pinned via `packageManager` in `package.json`). Do not
use npm or yarn — `pnpm-lock.yaml` is the committed lockfile and the only one CI reads.
Node.js >= 22 (CI runs 24). This repository uses **pnpm** (pinned via `packageManager`
in `package.json`). Do not use npm or yarn — `pnpm-lock.yaml` is the committed lockfile
and the only one CI reads.

```bash
pnpm install
Expand Down
Loading
Loading