The /api/fetchRes proxy endpoint accepted an arbitrary URL from the
request body and passed it directly to fetch(), returning the response
to the caller. Any user with the site auth code could use it to reach
internal services (cloud metadata endpoints, RFC1918 hosts, loopback,
non-http(s) schemes) — a classic CWE-918 SSRF primitive.
The endpoint now:
- rejects non-http(s) schemes
- rejects URLs containing embedded credentials
- rejects hostnames resolving to loopback/private/link-local/CGNAT/
multicast/reserved ranges, IPv6 ULA/link-local, IPv4-mapped variants
and well-known cloud metadata hostnames
- follows redirects manually and re-validates each hop (max 5)
- Add 'internal' token type to API Token system, hidden from the
security settings token list
- When WebDAV is enabled, auto-create an internal API Token with
list/upload/delete permissions, stored in WebDAV config
- When WebDAV is disabled, auto-delete the internal token
- WebDAV handler reads the internal token from config and sends it
as Bearer auth; if missing, creates one on-the-fly as fallback
- Works across both Docker and Cloudflare deployments since the
token is persisted in KV/D1, not in process memory
- Change SESSION_PREFIX from 'session@' to 'manage@session@' to prevent
sessions from appearing in file index and backups
- Add KV expirationTtl for automatic session cleanup on expiry
- Fix D1 adapter: route all manage@ keys to settings table instead of
files table (fixes blockipList and session storage in wrong table)
- Fix D1 list({ prefix: 'manage@' }) not matching settings table
(fixes backup not containing settings data)
- Exclude manage@session@ keys from settings backup export
WebDAV upload records now store only the channel identity and object/public paths. Read, delete, move, and rename operations resolve credentials and headers from the current WebDAV channel config by ChannelName, with a legacy metadata fallback so already-created records remain usable.
Constraint: Preserve existing WebDAV object lifecycle behavior while reducing metadata exposure
Rejected: Keep credentials on every file record | expands exposure through metadata reads, backups, and logs
Confidence: high
Scope-risk: moderate
Directive: Keep WebDAV credentials in upload config/env; do not reintroduce per-file credential metadata
Tested: npm test; node deploy/worker/generate-routes.js; npx wrangler deploy --dry-run --config deploy/worker/wrangler.toml; git diff --check
Not-tested: Live WebDAV provider move/delete/read workflow
Cloudflare Workers and Pages already provide the Fetch/Web APIs needed for WebDAV verbs, so the storage integration uses a small local helper instead of adding a Node-oriented WebDAV client. The channel now participates in upload, read, delete, move, rename, channel listing, and runtime config, with chunked uploads explicitly guarded because WebDAV has no portable server-side compose primitive.
Constraint: Preserve Pages Functions and generated Worker deployment paths
Constraint: No new npm dependency for WebDAV client behavior
Rejected: Add a WebDAV npm client | likely Node API/compatibility and package-lock churn
Rejected: Treat WebDAV as External URL only | not a complete storage channel lifecycle
Confidence: high
Scope-risk: moderate
Directive: WebDAV here is third-party storage; keep it distinct from the built-in /dav server settings
Tested: npm test; node worker/generate-routes.js; npx wrangler deploy --dry-run --config worker/wrangler.toml; git diff --cached --check
Not-tested: Live third-party WebDAV provider credentials; Digest-only WebDAV authentication
- checkAdmin: return 'admin' when admin auth not configured
- checkUser: return 'user' when authCode not configured
- directoryTree: use authType !== 'admin' to gate user-only checks
- Remove Basic Auth (verifyBasicAuth, parseBasicAuth) from authCore.js
- Add /api/auth/adminLogin POST endpoint for admin login via JSON body
- Delete legacy /api/manage/check, login, logout (no longer referenced)
- Fix adminConfigured to consider password-only config
- Extract shared authentication logic into utils/auth/authCore.js
- Replace enableBasicAuth/enableAuthCode flags with clear authScope enum (ADMIN/USER/EITHER)
- Move all auth-related files into utils/auth/ subdirectory
- Eliminate duplicated admin auth logic between _middleware.js and dualAuth.js
- Fix: user session no longer grants access to admin-only endpoints
- Fix: dualAuth no longer bypasses authCode when admin is not configured
- Update all 17 import references across the codebase
- Preserve original function signatures (userAuthCheck, dualAuthCheck) for zero caller changes
- Replace single-round SHA-256 with PBKDF2 (100k iterations) via Web Crypto API
- Auto-rehash old SHA-256/plaintext passwords to PBKDF2 on successful login
- Add timing-safe comparison to prevent timing attacks
- Replace Math.random() with crypto.getRandomValues() for API token and token ID generation
- Maintain full backward compatibility with existing SHA-256 hashes and plaintext passwords
Allows resetting all auth config when locked out:
- Requires RESET_KEY environment variable to be set
- GET /api/resetAuth?key=YOUR_RESET_KEY
- Clears security config from database (falls back to env vars)
- Destroys all active sessions
- Fix getSecurityConfig: use ?? instead of || so empty string is preserved
- Handle _clear flag to explicitly remove passwords
- Clear adminUsername together with adminPassword on _clear
- sessionCheck now returns adminRequired/userRequired fields
- Return 200 instead of 401 from sessionCheck for frontend to decide