Commit Graph

2240 Commits

Author SHA1 Message Date
99819b70ff added caddy-proxy-manager for testing
Some checks failed
Build and Push Docker Images (Trusted) / build-and-push (., docker/caddy/Dockerfile, caddy) (push) Has been cancelled
Build and Push Docker Images (Trusted) / build-and-push (., docker/l4-port-manager/Dockerfile, l4-port-manager) (push) Has been cancelled
Build and Push Docker Images (Trusted) / build-and-push (., docker/web/Dockerfile, web) (push) Has been cancelled
Tests / test (push) Has been cancelled
2026-04-21 22:49:08 +00:00
fuomag9
4c5ad53370 Fix inflated certificate counts in dashboard and certificates page
The dashboard overview counted all proxy hosts without a cert as ACME
certs, ignoring wildcard deduplication. The certificates page only
deduplicated the current page of results (25 rows) but used a full
count(*) for the total, so hosts on other pages covered by wildcards
were never subtracted.

Now both pages fetch all ACME hosts, apply full deduplication (cert
wildcard coverage + ACME wildcard collapsing), then paginate/count
from the deduplicated result.

Also fixes a strict-mode violation in the E2E test where DataTable's
dual mobile/desktop rendering caused getByText to match two elements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 21:01:39 +02:00
fuomag9
d710ad1247 Remove unnecessary IONOS field name migration
The wrong field name only existed for one commit before the fix, and
the only affected user already re-entered their credentials.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 18:09:33 +02:00
fuomag9
6515da666f Fix duplicate ACME entries for subdomains covered by wildcard ACME host
The previous fix (92fa1cb) only collapsed subdomains when an explicit
managed/imported certificate had a wildcard. When all hosts use Caddy
Auto (no certificate assigned), the wildcard ACME host was not checked
against sibling subdomain hosts, so each showed as a separate entry.

Also adds a startup migration to rename the stored IONOS DNS credential
key from api_token to auth_api_token for users who configured IONOS
before ef62ef2.

Closes #110

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 18:04:38 +02:00
fuomag9
96bac86934 Fix L4 port manager failing to recreate caddy after Docker restart
The sidecar's `docker compose up` command lacked `--pull never`, so
Docker Compose would attempt to pull the caddy image from ghcr.io when
the local image was missing or stale. Since the sidecar has no registry
credentials this failed with 403 Forbidden.

Closes #117

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 11:35:12 +02:00
fuomag9
dbfc340ea4 Fix logout redirect to 0.0.0.0 instead of configured BASE_URL
Closes #113

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 09:51:51 +02:00
dependabot[bot]
521a059414 deps(deps): Bump better-auth in the production-dependencies group (#116)
Bumps the production-dependencies group with 1 update: [better-auth](https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth).


Updates `better-auth` from 1.6.4 to 1.6.5
- [Release notes](https://github.com/better-auth/better-auth/releases)
- [Changelog](https://github.com/better-auth/better-auth/blob/main/packages/better-auth/CHANGELOG.md)
- [Commits](https://github.com/better-auth/better-auth/commits/better-auth@1.6.5/packages/better-auth)

---
updated-dependencies:
- dependency-name: better-auth
  dependency-version: 1.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 05:07:02 +00:00
dependabot[bot]
1be8fc2629 deps(deps-dev): Bump the development-dependencies group with 3 updates (#115)
Bumps the development-dependencies group with 3 updates: [eslint](https://github.com/eslint/eslint), [shadcn](https://github.com/shadcn-ui/ui/tree/HEAD/packages/shadcn) and [typescript](https://github.com/microsoft/TypeScript).


Updates `eslint` from 10.2.0 to 10.2.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.2.0...v10.2.1)

Updates `shadcn` from 4.2.0 to 4.3.0
- [Release notes](https://github.com/shadcn-ui/ui/releases)
- [Changelog](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/CHANGELOG.md)
- [Commits](https://github.com/shadcn-ui/ui/commits/shadcn@4.3.0/packages/shadcn)

Updates `typescript` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 10.2.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: shadcn
  dependency-version: 4.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 05:06:24 +00:00
dependabot[bot]
6d2827a132 ci(deps): Bump dependabot/fetch-metadata from 2 to 3 (#114)
Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 2 to 3.
- [Release notes](https://github.com/dependabot/fetch-metadata/releases)
- [Commits](https://github.com/dependabot/fetch-metadata/compare/v2...v3)

---
updated-dependencies:
- dependency-name: dependabot/fetch-metadata
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 05:03:28 +00:00
fuomag9
eb11856994 Update README for multi-provider DNS, forward auth excluded paths
- Add DNS Providers feature listing all 12 supported providers
- Update Certificate Management section for multi-provider DNS-01
- Mention excluded paths in Forward Auth Portal feature
- Remove completed roadmap item (additional DNS providers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 22:24:04 +02:00
fuomag9
7d61528dad Fix login rejection for usernames containing hyphens
better-auth's default username validator only allows [a-zA-Z0-9_.],
rejecting hyphens with a generic "invalid username or password" error.
Added a custom validator that also permits hyphens.

Closes #112

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 12:15:18 +02:00
fuomag9
92fa1cb9d8 Fix duplicate certificate display for wildcard-covered subdomains
When a wildcard cert (e.g. *.domain.de) existed and a proxy host was created
for a subdomain (e.g. sub.domain.de) without explicitly linking it, the
certificates page showed it as a separate ACME entry. Now hosts covered by
an existing wildcard cert are attributed to that cert's "Used by" list instead.

Closes #110

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 12:10:17 +02:00
fuomag9
ef62ef232f Fix IONOS DNS provider field name (api_token -> auth_api_token)
The IONOS libdns provider uses auth_api_token as the JSON field name,
not api_token. This caused Caddy to reject the config with
"unknown field api_token".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 00:57:36 +02:00
fuomag9
0e47ec4d7d Fix Docker image tagging for pre-release versions
The semver patterns in docker/metadata-action don't match pre-release
tags like v1.0-rc2. Add a type=match rule that extracts the version
from any v* tag so RC and other pre-release builds get proper tags.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.0-rc3
2026-04-17 19:43:07 +02:00
fuomag9
5c78a8e8f6 Add IONOS DNS provider
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.0-rc2
2026-04-17 18:09:12 +02:00
fuomag9
2c70f2859a Add multi-provider DNS registry for ACME DNS-01 challenges
Replace hardcoded Cloudflare DNS-01 with a data-driven provider registry
supporting 11 providers (Cloudflare, Route 53, DigitalOcean, Duck DNS,
Hetzner, Vultr, Porkbun, GoDaddy, Namecheap, OVH, Linode). Users can
configure multiple providers with encrypted credentials and select a
default. Per-certificate provider override is supported via providerOptions.

- Add src/lib/dns-providers.ts with provider definitions, credential
  encrypt/decrypt, and Caddy config builder
- Change DnsProviderSettings to multi-provider format with default selection
- Auto-migrate legacy Cloudflare settings on startup (db.ts)
- Normalize old single-provider format on read (getDnsProviderSettings)
- Refactor buildTlsAutomation() to use provider registry
- Add GET /api/v1/dns-providers endpoint for provider discovery
- Add dns-provider settings group to REST API and instance sync
- Replace Cloudflare settings card with multi-provider UI (add/remove
  providers, set default, dynamic credential forms)
- Add 10 DNS provider modules to Caddy Dockerfile
- Update OpenAPI spec, E2E tests, and unit test mocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 18:01:16 +02:00
fuomag9
60633bf6c3 Fix unused variable lint error in api-security test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 10:28:48 +02:00
fuomag9
a520717aab Fix excluded_paths dropped by sanitize functions during creation
The sanitizeAuthentikMeta and sanitizeCpmForwardAuthMeta functions
did not process excluded_paths, causing the field to be silently
stripped when creating a proxy host.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 10:21:18 +02:00
fuomag9
8f4c24119e Add excluded paths support for forward auth (fixes #108)
Allow users to exclude specific paths from Authentik/CPM forward auth
protection. When excluded_paths is set, all paths require authentication
EXCEPT the excluded ones — useful for apps like Navidrome that need
/share/* and /rest/* to bypass auth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 10:11:35 +02:00
Copilot
390840dbd9 Add dependabot automerge workflow (#106)
Agent-Logs-Url: https://github.com/fuomag9/caddy-proxy-manager/sessions/d7981099-949d-4dc6-95c7-7c14383964e4

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: fuomag9 <1580624+fuomag9@users.noreply.github.com>
2026-04-17 01:29:29 +02:00
dependabot[bot]
3a4807b5cd deps(deps-dev): Bump the development-dependencies group with 3 updates (#104)
Bumps the development-dependencies group with 3 updates: [@next/eslint-plugin-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-plugin-next), [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@next/eslint-plugin-next` from 16.2.3 to 16.2.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v16.2.4/packages/eslint-plugin-next)

Updates `better-sqlite3` from 12.8.0 to 12.9.0
- [Release notes](https://github.com/WiseLibs/better-sqlite3/releases)
- [Commits](https://github.com/WiseLibs/better-sqlite3/compare/v12.8.0...v12.9.0)

Updates `typescript-eslint` from 8.58.1 to 8.58.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.2/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@next/eslint-plugin-next"
  dependency-version: 16.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: better-sqlite3
  dependency-version: 12.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: typescript-eslint
  dependency-version: 8.58.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-16 01:17:30 +02:00
dependabot[bot]
0c632811b4 deps(deps): Bump the production-dependencies group with 5 updates (#105)
Bumps the production-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.4.27` | `10.5.0` |
| [better-auth](https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth) | `1.6.2` | `1.6.4` |
| [maplibre-gl](https://github.com/maplibre/maplibre-gl-js) | `5.22.0` | `5.23.0` |
| [next](https://github.com/vercel/next.js) | `16.2.3` | `16.2.4` |
| [postcss](https://github.com/postcss/postcss) | `8.5.9` | `8.5.10` |


Updates `autoprefixer` from 10.4.27 to 10.5.0
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.27...10.5.0)

Updates `better-auth` from 1.6.2 to 1.6.4
- [Release notes](https://github.com/better-auth/better-auth/releases)
- [Changelog](https://github.com/better-auth/better-auth/blob/main/packages/better-auth/CHANGELOG.md)
- [Commits](https://github.com/better-auth/better-auth/commits/better-auth@1.6.4/packages/better-auth)

Updates `maplibre-gl` from 5.22.0 to 5.23.0
- [Release notes](https://github.com/maplibre/maplibre-gl-js/releases)
- [Changelog](https://github.com/maplibre/maplibre-gl-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/maplibre/maplibre-gl-js/compare/v5.22.0...v5.23.0)

Updates `next` from 16.2.3 to 16.2.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.2.3...v16.2.4)

Updates `postcss` from 8.5.9 to 8.5.10
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.9...8.5.10)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-version: 10.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: better-auth
  dependency-version: 1.6.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: maplibre-gl
  dependency-version: 5.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: next
  dependency-version: 16.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: postcss
  dependency-version: 8.5.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-16 01:17:13 +02:00
Copilot
81be14e95e configure dependabot for bun ecosystem (#103)
Agent-Logs-Url: https://github.com/fuomag9/caddy-proxy-manager/sessions/169dafb8-7aec-48bd-b02d-f0cea1d14bf8

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: fuomag9 <1580624+fuomag9@users.noreply.github.com>
2026-04-16 01:12:33 +02:00
fuomag9
2adb8e3807 Fix migration crash when linking_tokens table does not exist
Some deployments never ran migration 0007 that created the
linking_tokens table. The camelCase rename migration (0021) now
creates the table with old column names if missing before renaming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.0-rc1 v1.0-RC
2026-04-13 06:46:02 +02:00
fuomag9
8bb6dc8552 Update README for 1.0-RC: new OAuth callback URLs and auth env vars
- Document new OAuth callback URL format (/api/auth/oauth2/callback/{id})
- Add UI-based OAuth provider management section
- Add AUTH_TRUST_HOST, AUTH_RATE_LIMIT_* env vars to table
- Update rate limiting description (5 attempts per 60s)
- Add upgrade notice for users migrating from < 1.0-RC

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:32:54 +02:00
fuomag9
1472f84c15 Create disabled-user.spec.ts 2026-04-12 23:25:28 +02:00
fuomag9
7f4a268cf7 Fix flaky E2E tests: strict mode violations, OAuth redirect, parallelism
- Set workers: 1 to eliminate parallelism race conditions
- Fix groups test: use .first() for "0 members" assertion
- Fix access-control helper: match by name instead of generic "Delete List"
- Fix forward-auth-oauth: target Dex button specifically, handle /login in Dex URL
- Add comprehensive API security E2E tests (316 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:17:49 +02:00
fuomag9
a5c0df6a9c Add comprehensive API security E2E tests
Tests every /api/v1/ endpoint (86 endpoints × 4 auth levels = 316 tests):
- Unauthenticated requests → 401 on all endpoints
- User role → 403 on admin-only endpoints
- Viewer role → 403 on admin-only endpoints
- Admin role → allowed on all endpoints
- Cross-user isolation: users cannot access other users' profiles

Uses Bearer API tokens (created directly in DB) to avoid
Better Auth rate limiting during test execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:29:13 +02:00
fuomag9
1237cdee4f Fix lint errors: remove unused imports and fix type assertions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:57:56 +02:00
fuomag9
c136bc9247 Revert hash suffix on env-synced OAuth provider IDs
Use plain slug (e.g. "dex" not "dex-RGV4") for predictable callback URLs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:55:35 +02:00
fuomag9
66f8e32df5 Fix security issues in Better Auth migration
- Tighten login rate limit from 200/10s to 5/60s to prevent brute-force
- Encrypt OAuth tokens (access/refresh/id) in accounts table via databaseHooks
- Sync password changes to accounts.password so old passwords stop working
- Redact OAuth client secrets in server actions before returning to client
- Add trustHost config (default false) to prevent Host header poisoning
- Add audit logging for successful logins via session create hook
- Add audit logging to OAuth provider update/delete server actions
- Fix provider ID collision by appending name hash suffix to slug
- Fix nullable provider field causing incorrect hasOAuth detection
- Refuse to store plaintext secrets if encryption module fails to load

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:50:48 +02:00
fuomag9
3a16d6e9b1 Replace next-auth with Better Auth, migrate DB columns to camelCase
- Replace next-auth v5 beta with better-auth v1.6.2 (stable releases)
- Add multi-provider OAuth support with admin UI configuration
- New oauthProviders table with encrypted secrets (AES-256-GCM)
- Env var bootstrap (OAUTH_*) syncs to DB, UI-created providers fully editable
- OAuth provider REST API: GET/POST/PUT/DELETE /api/v1/oauth-providers
- Settings page "Authentication Providers" section for admin management
- Account linking uses new accounts table (multi-provider per user)
- Username plugin for credentials sign-in (replaces email@localhost pattern)
- bcrypt password compatibility (existing hashes work)
- Database-backed sessions via Kysely adapter (bun:sqlite direct)
- Configurable rate limiting via AUTH_RATE_LIMIT_* env vars
- All DB columns migrated from snake_case to camelCase
- All TypeScript types/models migrated to camelCase properties
- Removed casing: "snake_case" from Drizzle config
- Callback URL format: {baseUrl}/api/auth/oauth2/callback/{providerId}
- package-lock.json removed and gitignored (using bun.lock)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:11:48 +02:00
fuomag9
eb78b64c2f update packages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:47:54 +02:00
fuomag9
f007f2df0c Use safe test-range CIDRs in geoblock E2E tests to prevent worker interference
Replace 0.0.0.0/0 with RFC 5737 test ranges (198.51.100.0/24, etc.) in
persistence tests so saving geoblock rules to Caddy doesn't block real
traffic for concurrent test workers. The LAN Only preset save test uses
the API to verify saved values and immediately resets, minimizing the
window where block-all is active.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 19:16:49 +02:00
fuomag9
f9169c2ab2 Fix geo blocking form losing rules when switching tabs or collapsing accordion
Radix UI Tabs and Accordion unmount inactive/closed content from the DOM
by default. This caused hidden form inputs to be missing from FormData on
submit — saving while on the Block tab wiped all Allow rules (and vice
versa), and saving with the advanced accordion collapsed wiped redirect
URL, trusted proxies, and response settings.

Fix by adding forceMount to TabsContent and AccordionContent so all form
fields remain in the DOM regardless of which tab/panel is visible.

Also adds E2E regression tests covering both scenarios plus the RFC1918
preset, with proper afterEach cleanup to prevent test interference with
concurrent workers.

Fixes #99

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 16:34:31 +02:00
fuomag9
eee4c7b718 Add LAN Only (RFC1918) preset button to geo blocking UI
Adds a quick-apply preset that pre-fills allow CIDRs with private
network ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and
block CIDRs with 0.0.0.0/0, addressing the common homelab use case
of restricting services to LAN-only access.

Closes #97

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:29:54 +02:00
fuomag9
dc121700fd Suppress false-positive CodeQL ReDoS alerts on placeholder-stripping regex
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:52:28 +02:00
fuomag9
6c30533014 Fix OG preview image to show the landing page instead of the dashboard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:38:48 +02:00
fuomag9
c7b1bf8b29 Update landing page to reflect current project features and refresh screenshots
Add missing feature cards (Forward Auth Portal, REST API, OAuth/SSO, mTLS),
update existing cards and spotlights to match current functionality, add new
Authentication and Automation spotlight sections, and refresh all screenshots
with mockup data including populated analytics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:35:43 +02:00
fuomag9
95cb97b48a Allow cdn.jsdelivr.net in CSP for Swagger UI API docs page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:15:37 +02:00
fuomag9
2dea2af20f Add E2E container health tests to catch crash-looping sidecars
Verifies all Docker containers in the test stack are running and healthy,
including a restart-count check on the l4-port-manager to detect permission
errors or other crash-loop scenarios that previously went unnoticed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:26:17 +02:00
fuomag9
4e3f7e8ab7 Security hardening: fix SQL injection, WAF bypass, placeholder injection, and more
- C1: Replace all ClickHouse string interpolation with parameterized queries
  (query_params) to eliminate SQL injection in analytics endpoints
- C3: Strip Caddy placeholder patterns from redirect rules, protected paths,
  and Authentik auth endpoint to prevent config injection
- C4: Replace WAF custom directive blocklist with allowlist approach — only
  SecRule/SecAction/SecMarker/SecDefaultAction permitted; block ctl:ruleEngine
  and Include directives
- H2: Validate GCM authentication tag is exactly 16 bytes before decryption
- H3: Validate forward auth redirect URIs (scheme, no credentials) to prevent
  open redirects
- H4: Switch 11 analytics/WAF/geoip endpoints from session-only requireAdmin
  to requireApiAdmin supporting both Bearer token and session auth
- H5: Add input validation for instance-mode (whitelist) and sync-token
  (32-char minimum) in settings API
- M1: Add non-root user to l4-port-manager Dockerfile
- M5: Document Caddy admin API binding security rationale
- Document C2 (custom config injection) and H1 (SSRF via upstreams) as
  intentional admin features

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:26:16 +02:00
fuomag9
5d0b4837d8 Security hardening: fix SQL injection, WAF bypass, placeholder injection, and more
- C1: Replace all ClickHouse string interpolation with parameterized queries
  (query_params) to eliminate SQL injection in analytics endpoints
- C3: Strip Caddy placeholder patterns from redirect rules, protected paths,
  and Authentik auth endpoint to prevent config injection
- C4: Replace WAF custom directive blocklist with allowlist approach — only
  SecRule/SecAction/SecMarker/SecDefaultAction permitted; block ctl:ruleEngine
  and Include directives
- H2: Validate GCM authentication tag is exactly 16 bytes before decryption
- H3: Validate forward auth redirect URIs (scheme, no credentials) to prevent
  open redirects
- H4: Switch 11 analytics/WAF/geoip endpoints from session-only requireAdmin
  to requireApiAdmin supporting both Bearer token and session auth
- H5: Add input validation for instance-mode (whitelist) and sync-token
  (32-char minimum) in settings API
- M1: Add non-root user to l4-port-manager Dockerfile
- M5: Document Caddy admin API binding security rationale
- Document C2 (custom config injection) and H1 (SSRF via upstreams) as
  intentional admin features

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 12:13:50 +02:00
fuomag9
e1c97038d4 Migrate analytics from SQLite to ClickHouse
SQLite was too slow for analytical aggregations on traffic_events and
waf_events (millions of rows, GROUP BY, COUNT DISTINCT). ClickHouse is
a columnar OLAP database purpose-built for this workload.

- Add ClickHouse container to Docker Compose with health check
- Create src/lib/clickhouse/client.ts with singleton client, table DDL,
  insert helpers, and all analytics query functions
- Update log-parser.ts and waf-log-parser.ts to write to ClickHouse
- Remove purgeOldEntries — ClickHouse TTL handles 90-day retention
- Rewrite analytics-db.ts and waf-events.ts to query ClickHouse
- Remove trafficEvents/wafEvents from SQLite schema, add migration
- CLICKHOUSE_PASSWORD is required (no hardcoded default)
- Update .env.example, README, and test infrastructure

API response shapes are unchanged — no frontend modifications needed.
Parse state (file offsets) remains in SQLite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 00:05:38 +02:00
fuomag9
833284efb1 Add forward auth E2E tests with Dex OIDC provider
- Add Dex OIDC provider to test Docker Compose stack with static test
  users (alice, bob) and pre-configured OAuth client
- Add forward-auth.spec.ts: credential-based forward auth flow tests
  (redirect, portal form, login, session cookie, forged cookie rejection)
- Add forward-auth-oauth.spec.ts: full OAuth forward auth flow tests
  including user-based access (allowed/denied), group-based access,
  access revocation, and credential login coexisting with OAuth
- Add waitForStatus helper for polling specific HTTP status codes
- Expand portal.spec.ts with OAuth button visibility, URI scheme
  rejection, and strict alert selector tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:10:28 +02:00
fuomag9
b7bd6b930a Revert "Move forward auth redirect URI from query string to HttpOnly cookie"
This reverts commit b6b53b7029.
2026-04-09 16:22:05 +02:00
dependabot[bot]
a5f25cd733 deps(deps-dev): bump hono from 4.12.10 to 4.12.12 (#95)
Bumps [hono](https://github.com/honojs/hono) from 4.12.10 to 4.12.12.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.12.10...v4.12.12)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 15:52:37 +02:00
dependabot[bot]
e1839d8b51 deps(deps-dev): bump @hono/node-server from 1.19.12 to 1.19.13 (#96)
Bumps [@hono/node-server](https://github.com/honojs/node-server) from 1.19.12 to 1.19.13.
- [Release notes](https://github.com/honojs/node-server/releases)
- [Commits](https://github.com/honojs/node-server/compare/v1.19.12...v1.19.13)

---
updated-dependencies:
- dependency-name: "@hono/node-server"
  dependency-version: 1.19.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 15:40:48 +02:00
fuomag9
b6b53b7029 Move forward auth redirect URI from query string to HttpOnly cookie
Replace the ?rd= query parameter in the Caddy→portal redirect with a
_cpm_rd HttpOnly cookie (Secure, SameSite=Lax, Path=/portal, 10min TTL).
The portal server component reads and immediately deletes the cookie,
then processes it through the existing validation and redirect intent flow.

This removes the redirect URI from the browser URL bar while maintaining
all existing security properties (domain validation, server-side storage,
one-time opaque rid).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:21:45 +02:00
dependabot[bot]
16c92f9268 deps(deps-dev): bump vite from 8.0.1 to 8.0.5 (#94)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.1 to 8.0.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-06 20:31:54 +02:00