[12.x] Add --readable flag to env:encrypt for visible key names#58262
Conversation
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... #:eyJpdiI6... (encrypted comment) Features: - Variable names visible, values encrypted as base64 JSON - Comments encrypted with `#:` prefix - Blank lines preserved - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... #:eyJpdiI6... (encrypted comment) Features: - Variable names visible, values encrypted as base64 JSON - Comments encrypted with `#:` prefix - Blank lines preserved - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... Features: - Variable names visible, values encrypted - Comments are skipped - Blank lines skipped - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... Features: - Variable names visible, values encrypted - Comments are skipped - Blank lines skipped - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged
…adable-encrypted-envs
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... Features: - Variable names visible, values encrypted - Comments are skipped - Blank lines skipped - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged
This adds a new `--readable` flag to the `env:encrypt` command that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data. Format example: APP_NAME=eyJpdiI6... DB_HOST=eyJpdiI6... Features: - Variable names visible, values encrypted - Comments are skipped - Blank lines skipped - Multiline values supported - Auto-detection during decryption (backward compatible) - Existing blob format continues to work unchanged ## Encrypter changes - Add static encrypted() method to Encrypter
| $result = ''; | ||
|
|
||
| foreach (Lines::process(preg_split('/\r\n|\r|\n/', $contents)) as $entry) { | ||
| $pos = strpos($entry, '='); |
There was a problem hiding this comment.
This implementation is broken. It doesn't handle multi-line values, quoted values and escape characters properly and it also won't resolve references to other variables. Instead of using Lines, you should use Dotenv::parse($contents) which will give you a key-value map of the data, with sub-variable resolution applied.
There was a problem hiding this comment.
Ok, it was all working. Let me
Check it again
There was a problem hiding this comment.
I was originally using the parse but will check it. For encryption I can't use it because DotEnv::parse interprets the variables and things like MY_ENV_2="${MY_ENV}" would be replaced with the actual value of MY_ENV, but I guess for the decryption I should use it.
There was a problem hiding this comment.
I've just tested it here and it worked 100%
CleanShot.2026-01-05.at.13.50.07.mp4
(sorry for the bad audio. Was in a noisy place)
There was a problem hiding this comment.
@GrahamCampbell I wasn't able to run into any errors and everything you mentioned worked. Can you please let me know how to reproduce what you say is broken?
I've just did some more tests with accents, single quotes, etc
CleanShot.2026-01-05.at.14.08.06.mp4
There was a problem hiding this comment.
This is what a dd(Lines::process(preg_split('/\r\n|\r|\n/', $contents)) looks like
php artisan env:encrypt --key=3UVsEgGVK36XN82KKeyLFMhvosbZN1aF --env=production --readable
array:59 [
0 => "APP_NAME=Laravel"
1 => "APP_ENV=local"
2 => "APP_KEY=base64:Ge+W23u+VZI2tbrp5QCGWrsUuxgcD65i7jtTRR2ZqfY="
3 => "APP_DEBUG=true"
4 => "APP_TIMEZONE=UTC"
5 => "APP_URL=http://framework-test.test"
6 => "APP_LOCALE=en"
7 => "APP_FALLBACK_LOCALE=en"
8 => "APP_FAKER_LOCALE=en_US"
9 => "APP_MAINTENANCE_DRIVER=file"
10 => "PHP_CLI_SERVER_WORKERS=4"
11 => "BCRYPT_ROUNDS=12"
12 => "LOG_CHANNEL=stack"
13 => "LOG_STACK=single"
14 => "LOG_DEPRECATIONS_CHANNEL=null"
15 => "LOG_LEVEL=debug"
16 => "DB_CONNECTION=pgsql"
17 => "DB_HOST=127.0.0.1"
18 => "DB_PORT=5432"
19 => "DB_DATABASE=framework_test_4"
20 => "DB_USERNAME=root"
21 => "DB_PASSWORD="
22 => "SESSION_DRIVER=redis"
23 => "SESSION_LIFETIME=120"
24 => "SESSION_ENCRYPT=false"
25 => "SESSION_PATH=/"
26 => "SESSION_DOMAIN=null"
27 => "BROADCAST_CONNECTION=log"
28 => "FILESYSTEM_DISK=local`"
29 => "QUEUE_CONNECTION=redis"
30 => "CACHE_STORE=redis"
31 => "CACHE_PREFIX="
32 => "MEMCACHED_HOST=127.0.0.1"
33 => "REDIS_CLIENT=phpredis"
34 => "REDIS_HOST=127.0.0.1"
35 => "REDIS_PASSWORD=null"
36 => "REDIS_PORT=6379"
37 => "MAIL_MAILER=smtp"
38 => "MAIL_SCHEME=null"
39 => "MAIL_HOST=127.0.0.1"
40 => "MAIL_PORT=2525"
41 => "MAIL_USERNAME="Framework Test""
42 => "MAIL_PASSWORD=null"
43 => "MAIL_FROM_ADDRESS="hello@example.com""
44 => "MAIL_FROM_NAME="${APP_NAME}""
45 => "AWS_ACCESS_KEY_ID="
46 => "AWS_SECRET_ACCESS_KEY="
47 => "AWS_DEFAULT_REGION=us-east-1"
48 => "AWS_BUCKET="
49 => "AWS_USE_PATH_STYLE_ENDPOINT=false"
50 => "VITE_APP_NAME="${APP_NAME}""
51 => """
APP_TEST="asdasd\n
sd\n
asd\n
asd\n
asd\n
"
"""
52 => """
APP_TEST_2="asdasdasd\n
asd\n
asd\n
as\n
dasd\n
"
"""
53 => "APP_TEST_3="${APP_TEST_2}""
54 => "NAME_1="JOSÉ""
55 => "NAME_2=O'Connel"
56 => "NAME_3="John O'Connel""
57 => "abcdef"
58 => "MY_ENV"
] // /Users/mathiasgrimm/laravel.com/github/framework/src/Illuminate/Foundation/Console/EnvironmentEncryptCommand.php:157
This adds a new
--readableflag to theenv:encryptcommand that produces a line-by-line encrypted format where variable names remain visible but values are encrypted. This allows developers to see what environment variables exist without exposing sensitive data, and makes pull requests easier to review since reviewers can see which variables were added, removed, or renamed without needing to decrypt the file.Format example:
APP_NAME=eyJpdiI6...
DB_HOST=eyJpdiI6...
Features:
Encrypter changes
Notes
For context, inspired by Ansible's Vault Multiple Passwords