Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Encrypt Bundle Laravel Package

studio201/doctrine-encrypt-bundle

A Symfony bundle that adds transparent field-level encryption to Doctrine entities, letting you mark sensitive properties for automatic encrypt/decrypt on persist and hydrate with configurable ciphers and key management.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Primary finding: this is not a Laravel package. studio201/doctrine-encrypt-bundle is a Symfony bundle wrapping Doctrine ORM entity encryption (it appears to be a low-traffic fork/continuation of ambta/doctrine-encrypt-bundle). Laravel's default ORM is Eloquent. A TPM reviewing this for a Laravel/PHP roadmap should treat the stack mismatch as the dominant decision factor, ahead of any feature or crypto comparison.

Architecture fit

  • The bundle's value is delivered through Symfony's DI and bundle extension system: it registers Doctrine event subscribers (flush/load/metadata events) and a custom Doctrine DBAL type. Without Symfony's Bundle/Extension/CompilerPass machinery, none of that auto-wires.
  • In a pure Eloquent codebase, there is no Doctrine entity mapping layer for these subscribers to attach to. Adopting the package would mean adopting Doctrine ORM as a second ORM — a major architectural decision that should never be made as a side effect of wanting field encryption.
  • In a Symfony app, or a Laravel app already running laravel-doctrine/orm, the approach fits the standard "custom type + lifecycle listener" pattern and is technically sound.
  • The package's real IP is a small pattern (custom Doctrine type + pre/post hydration hooks + a cipher wrapper), not a large system. If the target is Laravel/Eloquent, reimplementing the pattern as Castable/Encrypter-backed attribute casts is roughly 1-2 weeks of work and produces code you actually own.

Integration feasibility

  • Doctrine ORM 3.x removed several event classes and changed listener signatures that bundles of this vintage typically depend on. Expect API incompatibility with modern doctrine/orm unless the fork was specifically updated. Verify this first — it is a go/no-go gate, not a detail.
  • Symfony 6/7 DI changes plus PHP 8.1+ strictness are further compatibility hazards. The bundle's own test matrix, if any, is the fastest signal.
  • In a Laravel context, you would manually register the encryption subscriber in a service provider and bind the cipher/key config outside Symfony's config tree. That is achievable but means you are maintaining glue code the package was never designed to support.
  • Crypto dependency: the upstream family typically offers OpenSSL, defuse/php-encryption, and/or paragonie/halite. OpenSSL mode is a red flag (unauthenticated modes, easy footguns). Confirm the default cipher is an authenticated construction (e.g., AES-256-CTR + HMAC via defuse, or libsodium secretbox) and that the default is not the OpenSSL path.

Technical risk

  • Supply chain: 0 stars, 0 dependents, low opportunity score (~25.7). This means no security advisory feed, no CVE visibility, no release cadence, no downstream users validating upgrades. You are the only party testing this code. Treat it as a vendored dependency at best.
  • Key management is the hard problem, and the package does not solve it. Configuration-file keys mean: no rotation story, no per-tenant keys, no KMS/Vault integration, no envelope encryption, and a single key compromise exposing every encrypted column across every environment.
  • Query semantics collapse. Encrypted columns cannot be indexed, joined on, range-filtered, ORDER BY-ed, or LIKE-matched. Any existing feature that sorts or filters on a target column will degrade to in-memory processing or break. This is a product-surface change, not an infrastructure change, and it is consistently underestimated in planning.
  • Bulk-write hazard. DQL UPDATE/DELETE and raw SQL bypass hydration and therefore bypass the encryption subscriber — producing plaintext in an encrypted column or double-encryption. This is a silent, high-severity failure mode that requires linting or query-layer guardrails.
  • Deterministic-mode temptation. Some bundles offer deterministic encryption to preserve equality search. That trades meaningful leakage (frequency analysis) for a small UX gain. Any such request should be refused without a written security sign-off.

Key questions to resolve before commitment

  1. Is the actual target stack Symfony/Doctrine, or Laravel/Eloquent? If Eloquent, this package is out of scope and the decision is "build the pattern."
  2. Which cipher is default, and is it authenticated encryption?
  3. Does it work on Doctrine ORM 3.x and current Symfony components?
  4. What is the diff versus upstream ambta/doctrine-encrypt-bundle and versus vmelnikov/doctrine-encrypt-bundle? Who is the maintainer, and what is the commit history?
  5. Where do keys live in production, and who can read them? Does the threat model actually exclude DBAs, or only disk/backup theft?
  6. Which specific columns need encryption, and what queries touch them today?

Integration Approach

Stack fit

  • Fit is poor for Laravel/Eloquent, moderate for Symfony/Doctrine, acceptable for Laravel-Doctrine hybrids with added glue.
  • Recommended framing for a Laravel roadmap: do not adopt this package. Adopt (a) Laravel's native encrypted cast / Encrypter for at-rest field protection where query semantics permit, or (b) an Eloquent-native package, or (c) an internal extraction of this package's pattern if its cipher handling is genuinely better than the default.
  • Recommended framing for a Symfony roadmap: viable, but only as an internally forked and pinned dependency, and only for a small, well-bounded set of columns.

Migration path (if proceeding on Doctrine)

  1. Threat model and data classification. Enumerate columns, justify each one. Field encryption has real cost; encrypting everything is a sign of an unformed threat model.
  2. Key management design before code. Envelope encryption with a KMS/Vault-held master key, per-environment data keys, a documented rotation runbook, and a dual-key read window. This is the actual deliverable; the bundle is a small part of it.
  3. Vendor the dependency. Fork into an internal namespace, pin the commit, add PHPUnit coverage for encrypt/decrypt/null/wrong-key/rotated-key cases, and wire it into CI.
  4. Spike. One low-risk column, one entity, dev environment only. Validate: hydrate, persist, query, serialization to logs, queue payloads, and cache contents.
  5. Query audit. Grep and instrument every repository method touching target columns. Classify each as compatible, needs-rewrite, or needs-a-shadow-index (e.g., a blind-index HMAC column for exact-match lookups).
  6. Backfill. Read plaintext, write ciphertext, in batches. Design a dual-read path (try decrypt, fall back to plaintext) for the transition window, and remove it on a hard date.
  7. Rollout. Feature-flagged by entity, not by deploy. Roll back by flag, but treat rollback as re-encryption, not a simple revert — plan for it.
  8. Rotate. Do a real key rotation in staging before trusting the design in production.

Compatibility

  • Expect to hold doctrine/orm and symfony/* at specific versions. If the rest of the platform wants to upgrade, this package becomes a blocker — budget for that as recurring maintenance, not one-time integration.
  • For Laravel hybrids, verify that laravel-doctrine/orm + manual subscriber registration does not conflict with existing Eloquent models sharing the same tables. Mixed-ORM tables with encrypted columns are a classic partial-encryption bug source.

Sequencing recommendation Treat this as a three-phase gate: (1) stack decision, (2) key-management design, (3) implementation. Do not let implementation start before (2) is signed off; retrofitting envelope encryption and rotation onto a config.yml key is a rewrite, not a refactor.

Operational Impact

Maintenance

  • No upstream support. You own the code, the tests, and every future PHP/Doctrine/Symfony upgrade. Estimate 5-10 engineering days per year in steady state, plus a spike whenever the ORM majors.
  • Track the upstream ambta fork for security-relevant commits and cherry-pick manually. There is no advisory list for this package, so "no news" is not "no vulnerabilities."
  • The 0-star, 0-dependent, low-opportunity profile means no ecosystem pressure will find its bugs for you.

Support

  • No maintainer to escalate to; no Stack Overflow corpus. Debugging is first-principles.
  • Knowledge concentrates in whoever performs the integration. Mitigate with a written runbook covering key location, rotation steps, decryption failure triage, and the backfill procedure — otherwise this is a single-person operational dependency.

Scaling

  • Per-row encrypt/decrypt is cheap; per-result-set is not. Report queries returning 100k rows will pay a large fixed CPU and memory tax, and will materialize full plaintext in PHP memory — which may violate the data-handling posture you encrypted the column to satisfy.
  • Ciphertext expands by roughly 40-100% depending on encoding (IV + tag + base64). TEXT columns and backups grow proportionally.
  • Indexes on encrypted columns must be dropped, which can silently degrade execution plans on adjacent queries. Measure before and after.
  • Cache and queue layers (Redis, SQS payloads, job serialization, log scrubbing) become part of the compliance boundary. Decrypted values leaking into logs is the most common real-world incident in this class of design.

Failure modes to plan for

  • Key unavailable → app-wide failure on every entity using the column. Decide explicitly between fail-closed (safe, loud) and fail-open (never). Never allow silent plaintext fallback.
  • Wrong/rotated key → decryption exceptions at hydrate time, or, worse, ciphertext written back as plaintext on flush. Add a schema/format sanity check on write.
  • Bulk DQL/raw SQL → plaintext contamination or double encryption, undetected until read. Add a CI lint on raw statements touching encrypted columns.
  • Unencrypted legacy rows → mixed state during backfill; dual-read masks it, and removing dual-read without a verified 100% backfill corrupts reads.
  • Deterministic mode misuse → leakage that no one notices until an audit.

Ramp-up

  • A senior Doctrine engineer: ~2-3 days to a working integration, ~2 weeks to a defensible one including key management and backfill.
  • A Laravel-only team: materially higher, because the work splits into "learn Doctrine lifecycle internals" and "learn the crypto/key-management design." Expect 3-4 weeks before the team can operate and rotate keys without assistance.
  • Add a security review checkpoint. This is exactly the category of change where a two-hour review prevents a quarter of rework.

Bottom line for the roadmap This package should not be adopted as a strategic dependency. Its pattern is worth studying; its code is not worth depending on at 0 stars and 0 dependents, and it does not fit a Laravel/Eloquent stack at all. If field-level encryption is a real requirement, the defensible path is a small internally owned implementation (or Laravel's native encrypted casting where query semantics allow) sitting on top of a properly designed key-management layer — which is where the actual engineering effort and the actual risk live, regardless of which package is chosen.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core