Sync GitHub / sync (push) Successful in 8s
Add PublicAccessListener (priority 84) that allows rate-limited unauthenticated access to configured public paths. Authenticated users bypass this listener entirely via AcceptListener/AllowListener. New components: - PublicPathMatcher service with wildcard path matching (* and **) and optional host-prefix scoping - PublicAccessListener applying per-IP rate limiting to public paths - Separate public_limiter compound rate limiter (burst + sustained) - publicRateLimitCache pool (APCu in prod, array in tests) New env vars: - PUBLIC_PATHS (comma-separated path patterns, empty = disabled) - PUBLIC_BURST_COUNT/PUBLIC_BURST_TIME (default 100/60s) - PUBLIC_UPPER_COUNT/PUBLIC_UPPER_TIME (default 500/3600s) Tests: 52 new tests (29 unit for PublicPathMatcher, 12 unit for PublicAccessListener, 11 functional for PublicAccessFlowTest). Total: 293 tests, 605 assertions, all passing. PHP CS Fixer: 0 of 63 files need fixing. Documentation: README, CHANGELOG, ROADMAP, Caddyfile, example.env all updated with public access configuration and examples.
6.2 KiB
6.2 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased] — v1.1
Added
- Public rate-limited access — Select paths can now be made publicly
accessible without TOTP authentication, with separate per-IP rate limiting.
This is useful for exposing public content (e.g., public Gitea repositories)
while protecting server resources from bot traffic.
- New
PUBLIC_PATHSenv var: comma-separated path patterns with*(single segment) and**(cross-segment) wildcard support. Optional host prefix (e.g.,code.example.com/public/**). When empty (default), the feature is fully disabled. - New
PUBLIC_BURST_COUNT/PUBLIC_BURST_TIMEenv vars for burst rate limiting (default: 100 requests per 60 seconds). - New
PUBLIC_UPPER_COUNT/PUBLIC_UPPER_TIMEenv vars for sustained rate limiting (default: 500 requests per 3600 seconds). - Authenticated users bypass the public rate limiter entirely.
- Over-limit responses include a
Retry-Afterheader. - New
PublicPathMatcherservice for path pattern matching. - New
PublicAccessListener(priority 84) in the request pipeline.
- New
[1.0.0] — v1.0 Release
Security
- Made
Remote-Userheader value configurable viaREMOTE_USERenvironment variable with four modes:session(default),static,mapped, andnone. This allows deployments to prevent user-controlled header values from reaching backend services. - Added
SecurityHeadersListenerto setX-Content-Type-Options,X-Frame-Options,Content-Security-Policy,Referrer-Policy, andStrict-Transport-Securityheaders on all responses. - Replaced
document.write()withdocument.documentElement.innerHTMLin login page JavaScript to avoid CSP violations. - Added CSS escaping (
|e('css')) to environment-configured color values in the login page template to prevent CSS injection. - Documented CSRF protection model: the nonce system provides CSRF protection for POST form logins (server-generated, single-use, 120s TTL).
- Reduced TOTP verification window from 10 periods (±5 minutes) to 1 period (±30 seconds) to reduce brute-force attack surface.
- Removed hardcoded
APP_SECRETfrombin/franken.sh(now uses environment variable or generates a random secret). - Removed backup code values from debug log output.
- Added
.envto.gitignore. - Expanded TLD list in
DomainManagerwith many missing multi-part TLDs (.com.au,.co.jp,.com.br,.co.kr,.com.tw,.co.za, etc.) to prevent open redirect vulnerabilities from incorrect domain matching. - Lowercased host before TLD lookup to fix case-sensitivity issue.
Fixed
- Fixed
$payload->jsonaccess on possibly-null$payloadinLoginListenerusing null-safe operator (?->). - Fixed
validReturn()not checkingfalsereturn fromparse_url(), which could cause aTypeErroron malformed URLs. - Added
isHit()race condition check inAcceptListenerandAllowListenerbetweenhasItem()andgetItem()calls. - Added
try/finallyinKernel::terminate()soparent::terminate()always runs even ifpersist()throws an exception. - Added input validation to
GenerateBackupCodesCommand— rejects count < 1.
Changed
- Disabled unused Symfony sessions in
framework.yaml(preauth implements its own cookie/cache-based session management). - Standardized git tag format to use
vprefix (v1.0.0instead of1.0.0). - Updated CI workflows to use
v*.*.*tag pattern and stripvprefix for Docker image tags. - Removed stale
developbranch from CI triggers. - Fixed
publish.yamlto usegit remote set-urlon re-runs instead of failing when the remote already exists. - Explicitly install
curlin the Docker final image (needed for healthcheck). - Added
declare(strict_types=1)to all interface files. - Added
#[AsCommand]attribute toGenerateBackupCodesCommand. - Fixed
BackupCodeInterfacedefault count to match implementation (10). - Used
Response::HTTP_INTERNAL_SERVER_ERRORconstant inGetTotpTraitinstead of literal500.
[0.10.0] - 2026-08-11
Added
- PHP-CS-Fixer with PSR-12 configuration and CI check.
[0.9.0] - 2026-07-15
Added
- PHPUnit test suite — 222 tests, 100% code coverage (lines, methods, classes).
[0.8.1] - 2026-05-30
Fixed
- Bug fixes and cleanup from develop branch merge.
[0.8.0] - 2026-05-29
Changed
- Renamed form fields for clarity.
- Fixed invalid login bug.
[0.7.0] - 2026-05-29
Added
- Single-use backup codes via
app:generate-backup-codesconsole command. - Cache persistence improvement — only write changed keys to file storage.
Removed
- Static password and lookup token (security risks).
Changed
- Updated to PHP 8.5, updated dependencies.
[0.6.0] - 2026-02-10
Added
- Optional (disabled by default) ability to lookup token by static password.
[0.5.0] - 2026-01-17
Added
- Optional (disabled by default) ability to use a static password as backup auth.
Changed
- Nonce-related cleanup.
[0.4.1] - 2025-12-26
Fixed
- Bug which can occur if cache files are deleted.
[0.4.0] - 2025-12-26
Changed
- Massive rewrite to listener-based architecture instead of controllers.
- Login payload sent via
X-Preauthheader instead of GET request parameters. - Enhanced cookie security.
- Removed icon system and asset system.
[0.3.0] - 2025-12-15
Changed
- Breaking: Default port and transport changed to HTTP on port 80.
- Breaking: Environment variable names have changed.
- Refactored to Symfony 7.4 with FrankenPHP.
[0.2.0] - 2025-12-03
Added
- Login rate limiting (burst + upper window).
- Error page for rate-limited clients ("too many requests").
- Example Docker Compose file.
[0.1.0] - 2025-11-14
Added
- Docker image published to Docker Hub.
- PHP-FPM based, code in
src/, templates in separate files.
[0.0.1] - 2024-06-26
Notes
- Started as a single-file script in Caddy config. Hardcoded TOTP secret, zero flexibility, but functional. Ran quietly in production for about a year before any real development began.