Skip to content

fix(security): harden security across auth, API, frontend, and infra#10

Merged
thlaure merged 11 commits intomasterfrom
fix/security-vulnerabilities
Mar 15, 2026
Merged

fix(security): harden security across auth, API, frontend, and infra#10
thlaure merged 11 commits intomasterfrom
fix/security-vulnerabilities

Conversation

@thlaure
Copy link
Owner

@thlaure thlaure commented Mar 14, 2026

Summary

  • Auth: Replace assert() with AccessDeniedException in all state processors/providers; prevent user enumeration on register (generic 201 response); enforce PasswordStrength(MEDIUM) on registration
  • SSRF: Add SsrfSafeUrl custom validator, applied to feed URL input
  • XSS: Sanitize article HTML with DOMPurify before rendering
  • Infra: Add Content-Security-Policy header in Caddyfile; clear hardcoded secrets from .env/.env.dev; prevent raw exception messages leaking from feed crawl errors
  • CI: Add composer audit, npm audit, TruffleHog secret scanning; enforce typecheck and lint (remove || true)
  • Behat: Fix api_platform.yaml formats accidentally scoped under when@prod; update test passwords to pass strength check

Test plan

  • All Behat API tests pass (57/57)
  • make quality passes (lint, PHPStan, Rector)
  • PHPUnit unit tests pass
  • Frontend builds without error (npm run build)
  • Register endpoint returns generic 201 for both new and existing emails

🤖 Generated with Claude Code

Thomas Laure and others added 6 commits March 14, 2026 23:16
- Replace assert($user instanceof User) with AccessDeniedException
  in all state processors and providers
- Add SsrfSafeUrl custom validator, apply to AddFeedInput
- Fix api_platform.yaml formats scoped under when@prod by mistake
- Update register Behat passwords to pass PasswordStrength check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Return identical 201 response regardless of email existence
- Add PasswordStrength(MEDIUM) constraint to RegisterInput
- RegisterHandler no longer throws EmailAlreadyExistsException
- RegisterController returns generic message instead of user ID

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add dompurify dependency to prevent XSS via article content
- Wrap dangerouslySetInnerHTML with DOMPurify.sanitize() in ArticlePage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Apply SsrfSafeUrl constraint to AddFeedInput URL field
- Replace raw exception message in CrawlFeedMessageHandler
  with a generic error to avoid leaking internal details
- Clear hardcoded secrets from .env and .env.dev
- Add Content-Security-Policy header in Caddyfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add composer audit for PHP dependency vulnerabilities
- Add npm audit --audit-level=high for JS dependencies
- Add TruffleHog secret scanning job
- Remove || true from typecheck and lint (enforce them)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gitguardian
Copy link

gitguardian bot commented Mar 14, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
28737789 Triggered Company Email Password f2313b3 features/api/register.feature View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Thomas Laure and others added 5 commits March 14, 2026 23:51
- Add typecheck script to package.json (tsc -b --noEmit)
- Allow composer audit exit code 2 (abandoned packages, non-blocking)
  while still failing on exit code 1 (actual vulnerabilities)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix axios DoS via prototype pollution (GHSA-43fc-jf86-j433)
- Fix rollup path traversal (GHSA-mw96-cpmx-2vgc)
- Fix minimatch ReDoS (GHSA-3ppc-4f35-3m26, GHSA-7r86-cg39-jmmj)
- Fix flatted unbounded recursion DoS (GHSA-25h7-pfq9-p65f)
- Fix ajv ReDoS (GHSA-2g4f-4pwh-qvx6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous approach used semicolons which don't prevent bash
set -e from exiting early on failure. Use || compound command
so exit code 2 (abandoned packages) is non-blocking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thlaure thlaure merged commit 532d996 into master Mar 15, 2026
5 checks passed
@thlaure thlaure deleted the fix/security-vulnerabilities branch March 15, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant