From ee1c95bbacec3e7bc8c651460699d23656c18538 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Tue, 10 Feb 2026 20:03:52 -0800 Subject: [PATCH 01/13] rename folder to be snakecase --- .../compose-file-only/compose.yaml | 0 .../compose-file-only/compose.yaml.golden | 0 .../defang-config-only/compose.yaml | 0 .../defang-config-only/compose.yaml.golden | 0 .../empty-values/compose.yaml | 0 .../empty-values/compose.yaml.golden | 0 .../{configresolution => config-resolution}/env-values/.env | 0 .../env-values/compose.yaml | 0 .../env-values/compose.yaml.golden | 0 .../interpolated-values/compose.yaml | 0 .../interpolated-values/compose.yaml.golden | 0 .../{configresolution => config-resolution}/mixed-sources/.env | 0 .../mixed-sources/compose.yaml | 0 .../mixed-sources/compose.yaml.golden | 0 .../multiple-services/compose.yaml | 0 .../multiple-services/compose.yaml.golden | 0 .../no-environment/compose.yaml | 0 .../no-environment/compose.yaml.golden | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename src/pkg/cli/testdata/{configresolution => config-resolution}/compose-file-only/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/compose-file-only/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/defang-config-only/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/defang-config-only/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/empty-values/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/empty-values/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/env-values/.env (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/env-values/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/env-values/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/interpolated-values/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/interpolated-values/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/mixed-sources/.env (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/mixed-sources/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/mixed-sources/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/multiple-services/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/multiple-services/compose.yaml.golden (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/no-environment/compose.yaml (100%) rename src/pkg/cli/testdata/{configresolution => config-resolution}/no-environment/compose.yaml.golden (100%) diff --git a/src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml b/src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml rename to src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml rename to src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/empty-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/empty-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/empty-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/empty-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/env-values/.env b/src/pkg/cli/testdata/config-resolution/env-values/.env similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/.env rename to src/pkg/cli/testdata/config-resolution/env-values/.env diff --git a/src/pkg/cli/testdata/configresolution/env-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/env-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/env-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/env-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/env-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/env-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/.env b/src/pkg/cli/testdata/config-resolution/mixed-sources/.env similarity index 100% rename from src/pkg/cli/testdata/configresolution/mixed-sources/.env rename to src/pkg/cli/testdata/config-resolution/mixed-sources/.env diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml rename to src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml rename to src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/no-environment/compose.yaml b/src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/no-environment/compose.yaml rename to src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/no-environment/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/no-environment/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml.golden From 46c0ecd0da96de23ca829599c539b39740dd622e Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Tue, 10 Feb 2026 20:05:10 -0800 Subject: [PATCH 02/13] Reproduce the secret from the env and env files --- src/pkg/cli/configResolution_test.go | 30 +++++++++++++++++-- .../redact-config/api-keys/compose.yaml | 9 ++++++ .../api-keys/compose.yaml.golden | 8 +++++ .../cloud-credentials/compose.yaml | 9 ++++++ .../cloud-credentials/compose.yaml.golden | 8 +++++ .../redact-config/database-urls/compose.yaml | 10 +++++++ .../database-urls/compose.yaml.golden | 9 ++++++ .../redact-config/empty-values/compose.yaml | 12 ++++++++ .../empty-values/compose.yaml.golden | 8 +++++ .../high-entropy-strings/compose.yaml | 9 ++++++ .../high-entropy-strings/compose.yaml.golden | 8 +++++ .../mixed-secrets-and-plain/compose.yaml | 16 ++++++++++ .../compose.yaml.golden | 12 ++++++++ .../redact-config/not-secrets/compose.yaml | 11 +++++++ .../not-secrets/compose.yaml.golden | 10 +++++++ .../redact-config/secrets-in-env-file/.env | 4 +++ .../secrets-in-env-file/compose.yaml | 9 ++++++ .../secrets-in-env-file/compose.yaml.golden | 8 +++++ .../url-with-password/compose.yaml | 9 ++++++ .../url-with-password/compose.yaml.golden | 8 +++++ 20 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 src/pkg/cli/testdata/redact-config/api-keys/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/database-urls/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/empty-values/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env create mode 100644 src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden create mode 100644 src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml create mode 100644 src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden diff --git a/src/pkg/cli/configResolution_test.go b/src/pkg/cli/configResolution_test.go index 5b6e74c2d..21ce6115f 100644 --- a/src/pkg/cli/configResolution_test.go +++ b/src/pkg/cli/configResolution_test.go @@ -12,7 +12,7 @@ import ( ) func TestPrintConfigResolutionSummary(t *testing.T) { - testAllConfigResolutionFiles(t, func(t *testing.T, name, path string) { + testAllConfigResolutionFiles(t, "testdata/config-resolution", func(t *testing.T, name, path string) { stdout, _ := term.SetupTestTerm(t) loader := compose.NewLoader(compose.WithPath(path)) @@ -50,11 +50,35 @@ func TestPrintConfigResolutionSummary(t *testing.T) { }) } -func testAllConfigResolutionFiles(t *testing.T, f func(t *testing.T, name, path string)) { +func TestPrintRedactedConfigResolutionSummary(t *testing.T) { + testAllConfigResolutionFiles(t, "testdata/redact-config", func(t *testing.T, name, path string) { + stdout, _ := term.SetupTestTerm(t) + + loader := compose.NewLoader(compose.WithPath(path)) + proj, err := loader.LoadProject(t.Context()) + if err != nil { + t.Fatal(err) + } + + err = printConfigResolutionSummary(proj, nil) + if err != nil { + t.Fatalf("PrintConfigResolutionSummary() error = %v", err) + } + + output := stdout.Bytes() + + // Compare the output with the golden file + if err := pkg.Compare(output, path+".golden"); err != nil { + t.Error(err) + } + }) +} + +func testAllConfigResolutionFiles(t *testing.T, dir string, f func(t *testing.T, name, path string)) { t.Helper() composeRegex := regexp.MustCompile(`^(?i)(docker-)?compose.ya?ml$`) - err := filepath.WalkDir("testdata/configresolution", func(path string, d os.DirEntry, err error) error { + err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { if err != nil || d.IsDir() || !composeRegex.MatchString(d.Name()) { return err } diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml new file mode 100644 index 000000000..fed79c0c9 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml @@ -0,0 +1,9 @@ +services: + backend: + image: node + environment: + APP_NAME: my-application + API_KEY: api-key=50m34p1k3y + SECRET_TOKEN: secret_token=ab12cd34ef56 + AUTH_PASSWORD: password=hunter2 + NORMAL_CONFIG: debug diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden new file mode 100644 index 000000000..d2c590011 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +backend API_KEY Compose api-key=50m34p1k3y +backend APP_NAME Compose my-application +backend AUTH_PASSWORD Compose password=hunter2 +backend NORMAL_CONFIG Compose debug +backend SECRET_TOKEN Compose secret_token=ab12cd34ef56 diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml new file mode 100644 index 000000000..c74c0520c --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml @@ -0,0 +1,9 @@ +services: + deployer: + image: alpine + environment: + GITHUB_TOKEN: ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 + AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE + AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + AWS_CLIENT_ID: AROA1234567890ABCDEF + REGION: us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden new file mode 100644 index 000000000..296d9f298 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +deployer AWS_ACCESS_KEY_ID Compose AKIAIOSFODNN7EXAMPLE +deployer AWS_CLIENT_ID Compose AROA1234567890ABCDEF +deployer AWS_SECRET_ACCESS_KEY Compose wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY +deployer GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 +deployer REGION Compose us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml new file mode 100644 index 000000000..49c08d7be --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml @@ -0,0 +1,10 @@ +services: + api: + image: node + environment: + DATABASE_URL: postgres://dbuser:p455w0rd@db.example.com:5432/myapp + MONGO_URI: mongodb://admin:s3cretP4ss@mongo.example.com:27017/mydb + MYSQL_URL: mysql://root:r00tP4ssw0rd@mysql.example.com:3306/app + REDIS_URL: rediss://default:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@redis.example.com:6380 + DB_HOST: db.example.com + DB_PORT: "5432" diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden new file mode 100644 index 000000000..dd5283c3f --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden @@ -0,0 +1,9 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +api DATABASE_URL Compose postgres://dbuser:p455w0rd@db.example.com:5432/myapp +api DB_HOST Compose db.example.com +api DB_PORT Compose 5432 +api MONGO_URI Compose mongodb://admin:s3cretP4ss@mongo.example.com:27017/mydb +api MYSQL_URL Compose mysql://root:r00tP4ssw0rd@mysql.example.com:3306/app +api REDIS_URL Compose rediss://default:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@redis.example.com:6380 diff --git a/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml new file mode 100644 index 000000000..28e2622fc --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml @@ -0,0 +1,12 @@ +services: + service1: + image: nginx + environment: + EMPTY_VAR: + WITH_VALUE: some_value + service2: + image: nginx + environment: + - EMPTY_STRING= + - EMPTY_VAR + - WITH_VALUE=some_value diff --git a/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden new file mode 100644 index 000000000..e3587b17a --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +service1 EMPTY_VAR Config +service1 WITH_VALUE Compose some_value +service2 EMPTY_STRING Compose +service2 EMPTY_VAR Config +service2 WITH_VALUE Compose some_value diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml new file mode 100644 index 000000000..512d75b01 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml @@ -0,0 +1,9 @@ +services: + app: + image: python + environment: + SESSION_SECRET: VEfk5vO0Q53VkK_uicor + ENCRYPTION_KEY: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 + SIGNING_KEY: xK9mPqR7sT2vW5yZ8aB3cD6eF + APP_ENV: production + LOG_LEVEL: info diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden new file mode 100644 index 000000000..6064c79b6 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +app APP_ENV Compose production +app ENCRYPTION_KEY Compose 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 +app LOG_LEVEL Compose info +app SESSION_SECRET Compose VEfk5vO0Q53VkK_uicor +app SIGNING_KEY Compose xK9mPqR7sT2vW5yZ8aB3cD6eF diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml new file mode 100644 index 000000000..13f4f1f1c --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml @@ -0,0 +1,16 @@ +services: + frontend: + image: nginx + environment: + APP_NAME: my-frontend + PORT: "3000" + backend: + image: node + environment: + APP_NAME: my-backend + PORT: "8080" + DATABASE_URL: postgres://admin:p455w0rd@db.example.com:5432/myapp + GITHUB_TOKEN: ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 + API_KEY: api-key=50m34p1k3y + LOG_LEVEL: info + NODE_ENV: production diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden new file mode 100644 index 000000000..eedaeef2b --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden @@ -0,0 +1,12 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +backend API_KEY Compose api-key=50m34p1k3y +backend APP_NAME Compose my-backend +backend DATABASE_URL Compose postgres://admin:p455w0rd@db.example.com:5432/myapp +backend GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 +backend LOG_LEVEL Compose info +backend NODE_ENV Compose production +backend PORT Compose 8080 +frontend APP_NAME Compose my-frontend +frontend PORT Compose 3000 diff --git a/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml new file mode 100644 index 000000000..770946440 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml @@ -0,0 +1,11 @@ +services: + web: + image: nginx + environment: + APP_ENV: production + LOG_LEVEL: info + PORT: "8080" + API_URL: https://api.example.com + DOCS_PATH: /leaderboard/api/hubs + NODE_ENV: production + GREETING: not a secret diff --git a/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden new file mode 100644 index 000000000..c4eb8304f --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden @@ -0,0 +1,10 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web API_URL Compose https://api.example.com +web APP_ENV Compose production +web DOCS_PATH Compose /leaderboard/api/hubs +web GREETING Compose not a secret +web LOG_LEVEL Compose info +web NODE_ENV Compose production +web PORT Compose 8080 diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env new file mode 100644 index 000000000..29b3f92ae --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env @@ -0,0 +1,4 @@ +GITHUB_TOKEN=ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 +DATABASE_URL=postgres://dbuser:p455w0rd@db.example.com:5432/myapp +API_SECRET=VEfk5vO0Q53VkK_uicor +APP_ENV=production diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml new file mode 100644 index 000000000..d7a0a0438 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml @@ -0,0 +1,9 @@ +services: + web: + image: nginx + environment: + GITHUB_TOKEN: ${GITHUB_TOKEN} + DATABASE_URL: ${DATABASE_URL} + API_SECRET: ${API_SECRET} + APP_ENV: ${APP_ENV} + STATIC_VALUE: hello diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden new file mode 100644 index 000000000..2bd5745b2 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web API_SECRET Compose VEfk5vO0Q53VkK_uicor +web APP_ENV Compose production +web DATABASE_URL Compose postgres://dbuser:p455w0rd@db.example.com:5432/myapp +web GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 +web STATIC_VALUE Compose hello diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml new file mode 100644 index 000000000..eeac7adf0 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml @@ -0,0 +1,9 @@ +services: + web: + image: nginx + environment: + SAFE_URL: https://example.com/api/v1 + WEBHOOK_URL: https://user:p455w0rd@example.com + CALLBACK_URL: https://user:p845w0rd@hooks.example.com/callback + REDIS_URL: rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 + REDIS_ALT_URL: rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden new file mode 100644 index 000000000..38145f6fc --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web CALLBACK_URL Compose https://user:p845w0rd@hooks.example.com/callback +web REDIS_ALT_URL Compose rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 +web REDIS_URL Compose rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 +web SAFE_URL Compose https://example.com/api/v1 +web WEBHOOK_URL Compose https://user:p455w0rd@example.com From 147bde8040f5e5c57a1c3261c469f8437e913ede Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Tue, 10 Feb 2026 22:11:37 -0800 Subject: [PATCH 03/13] Implement fix for redacting secrets --- src/pkg/cli/composeUp.go | 2 +- src/pkg/cli/configResolution.go | 36 ++++++++++++++++++++++++---- src/pkg/cli/configResolution_test.go | 4 ++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/pkg/cli/composeUp.go b/src/pkg/cli/composeUp.go index 4ce87e6fb..d1da23dd2 100644 --- a/src/pkg/cli/composeUp.go +++ b/src/pkg/cli/composeUp.go @@ -87,7 +87,7 @@ func ComposeUp(ctx context.Context, fabric client.FabricClient, provider client. if upload != compose.UploadModeIgnore { // Ignore missing configs in preview mode, because we don't want to fail the preview if some configs are missing. if upload != compose.UploadModeEstimate { - if err := PrintConfigSummaryAndValidate(ctx, provider, project); err != nil { + if err := PrintRedactedConfigSummaryAndValidate(ctx, provider, project); err != nil { return nil, project, err } } diff --git a/src/pkg/cli/configResolution.go b/src/pkg/cli/configResolution.go index d7d30ccde..f861f6709 100644 --- a/src/pkg/cli/configResolution.go +++ b/src/pkg/cli/configResolution.go @@ -33,8 +33,16 @@ func (s Source) String() string { return string(s) } +func maskTrailingConfigValue(value string) string { + // Mask the value if it looks like a secret and only show the first 4 characters + if len(value) <= 3 { + return configMaskedValue + } + return value[:4] + strings.Repeat("*", 3) +} + // determineConfigSource determines the source of an environment variable -// and returns the appropriate source type and value to display +// and returns the appropriate source type and value to display. func determineConfigSource(envKey string, envValue *string, defangConfigs map[string]struct{}) (Source, string) { // If the key itself is a defang config, mask it if _, isDefangConfig := defangConfigs[envKey]; isDefangConfig { @@ -57,7 +65,9 @@ func determineConfigSource(envKey string, envValue *string, defangConfigs map[st return SourceComposeFile, *envValue } -func printConfigResolutionSummary(project *types.Project, defangConfig []string) error { +// printConfigResolutionSummary prints a summary of where each environment variable in the compose file is coming from (compose file, defang config, or interpolation). +// If redact is true, it will mask values that are from the compose file and look like secrets. +func printConfigResolutionSummary(project *types.Project, defangConfig []string, redact bool) error { configset := make(map[string]struct{}) for _, name := range defangConfig { configset[name] = struct{}{} @@ -68,6 +78,16 @@ func printConfigResolutionSummary(project *types.Project, defangConfig []string) for serviceName, service := range project.Services { for envKey, envValue := range service.Environment { source, value := determineConfigSource(envKey, envValue, configset) + if redact && source == SourceComposeFile { + isSecret, err := compose.IsSecret(*envValue) + if err != nil { + return err + } + + if isSecret { + value = maskTrailingConfigValue(*envValue) + } + } projectEnvVars = append(projectEnvVars, configOutput{ Service: serviceName, Environment: envKey, @@ -97,13 +117,13 @@ func printConfigResolutionSummary(project *types.Project, defangConfig []string) return term.Table(projectEnvVars, "Service", "Environment", "Source", "Value") } -func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { +func printConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project, redact bool) error { configs, err := provider.ListConfig(ctx, &defangv1.ListConfigsRequest{Project: project.Name}) if err != nil { return err } - err = printConfigResolutionSummary(project, configs.Names) + err = printConfigResolutionSummary(project, configs.Names, redact) if err != nil { return err } @@ -115,3 +135,11 @@ func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider return nil } + +func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { + return printConfigSummaryAndValidate(ctx, provider, project, false) +} + +func PrintRedactedConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { + return printConfigSummaryAndValidate(ctx, provider, project, true) +} diff --git a/src/pkg/cli/configResolution_test.go b/src/pkg/cli/configResolution_test.go index 21ce6115f..927cfc60b 100644 --- a/src/pkg/cli/configResolution_test.go +++ b/src/pkg/cli/configResolution_test.go @@ -36,7 +36,7 @@ func TestPrintConfigResolutionSummary(t *testing.T) { defangConfigs = []string{} } - err = printConfigResolutionSummary(proj, defangConfigs) + err = printConfigResolutionSummary(proj, defangConfigs, false) if err != nil { t.Fatalf("PrintConfigResolutionSummary() error = %v", err) } @@ -60,7 +60,7 @@ func TestPrintRedactedConfigResolutionSummary(t *testing.T) { t.Fatal(err) } - err = printConfigResolutionSummary(proj, nil) + err = printConfigResolutionSummary(proj, nil, true) if err != nil { t.Fatalf("PrintConfigResolutionSummary() error = %v", err) } From 9aa62afb8e91a71c274cdfc413959f89c2cc32d5 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Tue, 10 Feb 2026 22:12:06 -0800 Subject: [PATCH 04/13] Update redact-config golden --- .../redact-config/api-keys/compose.yaml | 2 +- .../redact-config/api-keys/compose.yaml.golden | 10 +++++----- .../cloud-credentials/compose.yaml.golden | 10 +++++----- .../database-urls/compose.yaml.golden | 12 ++++++------ .../high-entropy-strings/compose.yaml.golden | 4 ++-- .../compose.yaml.golden | 18 +++++++++--------- .../redact-config/secrets-in-env-file/.env | 1 + .../secrets-in-env-file/compose.yaml | 1 + .../secrets-in-env-file/compose.yaml.golden | 11 ++++++----- .../url-with-password/compose.yaml.golden | 10 +++++----- 10 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml index fed79c0c9..df371d8e1 100644 --- a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml @@ -5,5 +5,5 @@ services: APP_NAME: my-application API_KEY: api-key=50m34p1k3y SECRET_TOKEN: secret_token=ab12cd34ef56 - AUTH_PASSWORD: password=hunter2 + AUTH_PASSWORD: password=hunter12345 NORMAL_CONFIG: debug diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden index d2c590011..1c78e5192 100644 --- a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -backend API_KEY Compose api-key=50m34p1k3y -backend APP_NAME Compose my-application -backend AUTH_PASSWORD Compose password=hunter2 -backend NORMAL_CONFIG Compose debug -backend SECRET_TOKEN Compose secret_token=ab12cd34ef56 +backend API_KEY Compose api-*** +backend APP_NAME Compose my-application +backend AUTH_PASSWORD Compose pass*** +backend NORMAL_CONFIG Compose debug +backend SECRET_TOKEN Compose secr*** diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden index 296d9f298..a02b58b2f 100644 --- a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -deployer AWS_ACCESS_KEY_ID Compose AKIAIOSFODNN7EXAMPLE -deployer AWS_CLIENT_ID Compose AROA1234567890ABCDEF -deployer AWS_SECRET_ACCESS_KEY Compose wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -deployer GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 -deployer REGION Compose us-east-1 +deployer AWS_ACCESS_KEY_ID Compose AKIA*** +deployer AWS_CLIENT_ID Compose AROA*** +deployer AWS_SECRET_ACCESS_KEY Compose wJal*** +deployer GITHUB_TOKEN Compose ghp_*** +deployer REGION Compose us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden index dd5283c3f..033e85eaf 100644 --- a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden @@ -1,9 +1,9 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -api DATABASE_URL Compose postgres://dbuser:p455w0rd@db.example.com:5432/myapp -api DB_HOST Compose db.example.com -api DB_PORT Compose 5432 -api MONGO_URI Compose mongodb://admin:s3cretP4ss@mongo.example.com:27017/mydb -api MYSQL_URL Compose mysql://root:r00tP4ssw0rd@mysql.example.com:3306/app -api REDIS_URL Compose rediss://default:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@redis.example.com:6380 +api DATABASE_URL Compose post*** +api DB_HOST Compose db.example.com +api DB_PORT Compose 5432 +api MONGO_URI Compose mong*** +api MYSQL_URL Compose mysq*** +api REDIS_URL Compose redi*** diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden index 6064c79b6..401572c94 100644 --- a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden @@ -4,5 +4,5 @@ SERVICE ENVIRONMENT SOURCE VALUE app APP_ENV Compose production app ENCRYPTION_KEY Compose 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 app LOG_LEVEL Compose info -app SESSION_SECRET Compose VEfk5vO0Q53VkK_uicor -app SIGNING_KEY Compose xK9mPqR7sT2vW5yZ8aB3cD6eF +app SESSION_SECRET Compose VEfk*** +app SIGNING_KEY Compose xK9m*** diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden index eedaeef2b..8670849c4 100644 --- a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden @@ -1,12 +1,12 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -backend API_KEY Compose api-key=50m34p1k3y -backend APP_NAME Compose my-backend -backend DATABASE_URL Compose postgres://admin:p455w0rd@db.example.com:5432/myapp -backend GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 -backend LOG_LEVEL Compose info -backend NODE_ENV Compose production -backend PORT Compose 8080 -frontend APP_NAME Compose my-frontend -frontend PORT Compose 3000 +backend API_KEY Compose api-*** +backend APP_NAME Compose my-backend +backend DATABASE_URL Compose post*** +backend GITHUB_TOKEN Compose ghp_*** +backend LOG_LEVEL Compose info +backend NODE_ENV Compose production +backend PORT Compose 8080 +frontend APP_NAME Compose my-frontend +frontend PORT Compose 3000 diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env index 29b3f92ae..11e93cbea 100644 --- a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env @@ -1,4 +1,5 @@ GITHUB_TOKEN=ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 DATABASE_URL=postgres://dbuser:p455w0rd@db.example.com:5432/myapp +POSTGRES_PASSWORD=p455w0rd API_SECRET=VEfk5vO0Q53VkK_uicor APP_ENV=production diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml index d7a0a0438..ea4c07afe 100644 --- a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml @@ -4,6 +4,7 @@ services: environment: GITHUB_TOKEN: ${GITHUB_TOKEN} DATABASE_URL: ${DATABASE_URL} + POSTGRES_URL: postgres://dbuser:${POSTGRES_PASSWORD}@db.example.com:5432/myapp API_SECRET: ${API_SECRET} APP_ENV: ${APP_ENV} STATIC_VALUE: hello diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden index 2bd5745b2..ec71555c7 100644 --- a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden @@ -1,8 +1,9 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -web API_SECRET Compose VEfk5vO0Q53VkK_uicor -web APP_ENV Compose production -web DATABASE_URL Compose postgres://dbuser:p455w0rd@db.example.com:5432/myapp -web GITHUB_TOKEN Compose ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 -web STATIC_VALUE Compose hello +web API_SECRET Compose VEfk*** +web APP_ENV Compose production +web DATABASE_URL Compose post*** +web GITHUB_TOKEN Compose ghp_*** +web POSTGRES_URL Compose post*** +web STATIC_VALUE Compose hello diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden index 38145f6fc..eb77cea47 100644 --- a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -web CALLBACK_URL Compose https://user:p845w0rd@hooks.example.com/callback -web REDIS_ALT_URL Compose rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 -web REDIS_URL Compose rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 -web SAFE_URL Compose https://example.com/api/v1 -web WEBHOOK_URL Compose https://user:p455w0rd@example.com +web CALLBACK_URL Compose http*** +web REDIS_ALT_URL Compose redi*** +web REDIS_URL Compose redi*** +web SAFE_URL Compose https://example.com/api/v1 +web WEBHOOK_URL Compose http*** From 04ad57041c453c96d51c50486e3686aa4178c6b0 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:15:36 -0800 Subject: [PATCH 05/13] Update golden file for ENCRYPTION_KEY --- .../high-entropy-strings/compose.yaml.golden | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden index 401572c94..b3c95e709 100644 --- a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -app APP_ENV Compose production -app ENCRYPTION_KEY Compose 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 -app LOG_LEVEL Compose info -app SESSION_SECRET Compose VEfk*** -app SIGNING_KEY Compose xK9m*** +app APP_ENV Compose production +app ENCRYPTION_KEY Compose 9f86*** +app LOG_LEVEL Compose info +app SESSION_SECRET Compose VEfk*** +app SIGNING_KEY Compose xK9m*** From 877579bc4bebd3f9da32ad393f189f0d574345a3 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:17:43 -0800 Subject: [PATCH 06/13] isSecret to return ds as well --- src/pkg/cli/compose/config_detector.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pkg/cli/compose/config_detector.go b/src/pkg/cli/compose/config_detector.go index 99f2fce95..f91b84d76 100644 --- a/src/pkg/cli/compose/config_detector.go +++ b/src/pkg/cli/compose/config_detector.go @@ -6,20 +6,20 @@ import ( "github.com/DefangLabs/secret-detector/pkg/scanner" ) -func IsSecret(input string) (bool, error) { +func IsSecret(key, value string) (bool, []string, error) { // DetectConfig checks if the input string contains any sensitive information - detectorTypes, err := detectConfig(input) + detectorTypes, err := detectConfig(key + ": " + value) if err != nil { - return false, fmt.Errorf("failed to detect config: %w", err) + return false, nil, fmt.Errorf("failed to detect config: %w", err) } // If no detectors were triggered, return false if len(detectorTypes) == 0 { - return false, nil + return false, nil, nil } // If any detectors were triggered, return true - return true, nil + return true, detectorTypes, nil } // assume that the input is a key-value pair string From fbb3ede4a9eee9b4f8f19f9f2880f9f9fc364551 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:19:20 -0800 Subject: [PATCH 07/13] lower entropy value slightly to capture hex --- src/pkg/cli/compose/config_detector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/cli/compose/config_detector.go b/src/pkg/cli/compose/config_detector.go index f91b84d76..7823515f6 100644 --- a/src/pkg/cli/compose/config_detector.go +++ b/src/pkg/cli/compose/config_detector.go @@ -35,7 +35,7 @@ func detectConfig(input string) (detectorTypes []string, err error) { cfg := scanner.NewConfigWithDefaults() cfg.Transformers = []string{"json"} cfg.DetectorConfigs["keyword"] = []string{"3"} - cfg.DetectorConfigs["high_entropy_string"] = []string{"4"} + cfg.DetectorConfigs["high_entropy_string"] = []string{"3.7"} // create a scanner from scanner config scannerClient, err := scanner.NewScannerFromConfig(cfg) From 6c39aa070b1c3d52e3ae9f002d178bc67d95875e Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:19:50 -0800 Subject: [PATCH 08/13] use yaml instead of json because it is a superset --- src/pkg/cli/compose/config_detector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/cli/compose/config_detector.go b/src/pkg/cli/compose/config_detector.go index 7823515f6..9cf1364f7 100644 --- a/src/pkg/cli/compose/config_detector.go +++ b/src/pkg/cli/compose/config_detector.go @@ -33,7 +33,7 @@ func detectConfig(input string) (detectorTypes []string, err error) { // create a custom scanner config cfg := scanner.NewConfigWithDefaults() - cfg.Transformers = []string{"json"} + cfg.Transformers = []string{"yaml"} cfg.DetectorConfigs["keyword"] = []string{"3"} cfg.DetectorConfigs["high_entropy_string"] = []string{"3.7"} From 6add32f1410b63b0c83d7cbf76a0bf23e25f80a2 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:20:30 -0800 Subject: [PATCH 09/13] update IsSecret callers --- src/pkg/cli/compose/validation.go | 9 +++------ src/pkg/cli/configResolution.go | 4 ++-- src/pkg/migrate/migrate.go | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/pkg/cli/compose/validation.go b/src/pkg/cli/compose/validation.go index 3382aabdb..b8f4e35ce 100644 --- a/src/pkg/cli/compose/validation.go +++ b/src/pkg/cli/compose/validation.go @@ -204,19 +204,16 @@ func validateService(svccfg *composeTypes.ServiceConfig, project *composeTypes.P // check for compose file environment variables that may be sensitive for key, value := range svccfg.Environment { if value != nil { - // format input as a key-value pair string - input := key + "=" + *value - // call detectConfig to check for sensitive information - ds, err := detectConfig(input) + isSecret, ds, err := IsSecret(key, *value) if err != nil { return fmt.Errorf("service %q: %w", svccfg.Name, err) } // show warning if sensitive information is detected - if len(ds) > 0 { + if isSecret { term.Warnf("service %q: environment %q may contain sensitive information; consider using 'defang config set %s' to securely store this value", svccfg.Name, key, key) - term.Debugf("service %q: environment %q may contain detected secrets of type: %q", svccfg.Name, key, ds) + term.Debugf("service %q: environment %q may contain detected secrets of type: %v", svccfg.Name, key, ds) } } } diff --git a/src/pkg/cli/configResolution.go b/src/pkg/cli/configResolution.go index f861f6709..a03b3a16f 100644 --- a/src/pkg/cli/configResolution.go +++ b/src/pkg/cli/configResolution.go @@ -79,13 +79,13 @@ func printConfigResolutionSummary(project *types.Project, defangConfig []string, for envKey, envValue := range service.Environment { source, value := determineConfigSource(envKey, envValue, configset) if redact && source == SourceComposeFile { - isSecret, err := compose.IsSecret(*envValue) + isSecret, _, err := compose.IsSecret(envKey, value) if err != nil { return err } if isSecret { - value = maskTrailingConfigValue(*envValue) + value = maskTrailingConfigValue(value) } } projectEnvVars = append(projectEnvVars, configOutput{ diff --git a/src/pkg/migrate/migrate.go b/src/pkg/migrate/migrate.go index 600fa8395..fb74a14d8 100644 --- a/src/pkg/migrate/migrate.go +++ b/src/pkg/migrate/migrate.go @@ -97,7 +97,7 @@ func setupFromHeroku(ctx context.Context, fabric client.FabricClient, surveyor s func sanitizeHerokuApplicationInfo(info HerokuApplicationInfo) (interface{}, error) { for key, value := range info.ConfigVars { // Redact sensitive information in config vars - isSecret, err := compose.IsSecret(value) + isSecret, _, err := compose.IsSecret(key, value) if err != nil { return nil, fmt.Errorf("failed to check if config var %q is a secret: %w", key, err) } From f8bd39cc8ee52d5006fd7aa1c6dd200d88649485 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:21:00 -0800 Subject: [PATCH 10/13] Add fake ENCRYPTION_KEY to test --- src/pkg/cli/compose/config_detector_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pkg/cli/compose/config_detector_test.go b/src/pkg/cli/compose/config_detector_test.go index c95302eca..99fe41529 100644 --- a/src/pkg/cli/compose/config_detector_test.go +++ b/src/pkg/cli/compose/config_detector_test.go @@ -18,6 +18,7 @@ func TestDetectConfig(t *testing.T) { {"AROA1234567890ABCDEF", []string{"AWS Client ID"}}, {"REDIS_URL=rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240", []string{"URL with password"}}, {"REDIS_URL=rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240", []string{"URL with password"}}, + {"ENCRYPTION_KEY: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", []string{"High entropy string"}}, } for _, tt := range tests { From 1d7a5cdcd4db75f572a0545aaf340b920d930e1e Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:35:12 -0800 Subject: [PATCH 11/13] Avoid fully revealing very short secrets --- src/pkg/cli/configResolution.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/cli/configResolution.go b/src/pkg/cli/configResolution.go index a03b3a16f..8834d505b 100644 --- a/src/pkg/cli/configResolution.go +++ b/src/pkg/cli/configResolution.go @@ -35,7 +35,7 @@ func (s Source) String() string { func maskTrailingConfigValue(value string) string { // Mask the value if it looks like a secret and only show the first 4 characters - if len(value) <= 3 { + if len(value) <= 4 { return configMaskedValue } return value[:4] + strings.Repeat("*", 3) From 7ba774d1f001b780f003b1922da6be50b5f1f2c5 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:35:23 -0800 Subject: [PATCH 12/13] match masked length --- src/pkg/cli/configResolution.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkg/cli/configResolution.go b/src/pkg/cli/configResolution.go index 8834d505b..a5ddd5a9e 100644 --- a/src/pkg/cli/configResolution.go +++ b/src/pkg/cli/configResolution.go @@ -19,7 +19,7 @@ type configOutput struct { Source Source `json:"source,omitempty"` } -const configMaskedValue = "*****" +const configMaskedValue = "******" type Source string @@ -38,7 +38,7 @@ func maskTrailingConfigValue(value string) string { if len(value) <= 4 { return configMaskedValue } - return value[:4] + strings.Repeat("*", 3) + return value[:4] + strings.Repeat("*", 2) } // determineConfigSource determines the source of an environment variable From 3e68372cc625c95370416b782c0283e6243e6b16 Mon Sep 17 00:00:00 2001 From: Kevin Vo Date: Wed, 11 Feb 2026 16:44:14 -0800 Subject: [PATCH 13/13] update golden file for new mask value --- .../defang-config-only/compose.yaml.golden | 6 +++--- .../config-resolution/mixed-sources/compose.yaml.golden | 2 +- .../multiple-services/compose.yaml.golden | 4 ++-- .../testdata/redact-config/api-keys/compose.yaml.golden | 6 +++--- .../redact-config/cloud-credentials/compose.yaml.golden | 8 ++++---- .../redact-config/database-urls/compose.yaml.golden | 8 ++++---- .../high-entropy-strings/compose.yaml.golden | 6 +++--- .../mixed-secrets-and-plain/compose.yaml.golden | 6 +++--- .../redact-config/secrets-in-env-file/compose.yaml.golden | 8 ++++---- .../redact-config/url-with-password/compose.yaml.golden | 8 ++++---- 10 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden index 804cce71c..87c295e13 100644 --- a/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden +++ b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden @@ -1,6 +1,6 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -service1 API_TOKEN Config ***** -service1 DB_USER Config ***** -service1 SECRET_KEY Config ***** +service1 API_TOKEN Config ****** +service1 DB_USER Config ****** +service1 SECRET_KEY Config ****** diff --git a/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden index 68a9f39a0..be6594f45 100644 --- a/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden +++ b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden @@ -4,4 +4,4 @@ SERVICE ENVIRONMENT SOURCE VALUE service1 FROM_ENV Compose from_ENV service1 PLAIN_VAR Compose plain_value service1 PUBLIC_URL Config (interpolated) https://example-${SECRET_KEY}-from_ENV.com -service1 SECRET_KEY Config ***** +service1 SECRET_KEY Config ****** diff --git a/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden index a58ac5cbc..e9c9026be 100644 --- a/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden +++ b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden @@ -2,8 +2,8 @@  SERVICE ENVIRONMENT SOURCE VALUE service1 APP_ENV Compose production -service1 DATABASE_URL Config ***** +service1 DATABASE_URL Config ****** service1 LOG_LEVEL Compose info -service2 REDIS_PASSWORD Config ***** +service2 REDIS_PASSWORD Config ****** service2 REDIS_PORT Compose 6379 service3 DB_USER Compose Defang diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden index 1c78e5192..ea393ca6a 100644 --- a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -backend API_KEY Compose api-*** +backend API_KEY Compose api-** backend APP_NAME Compose my-application -backend AUTH_PASSWORD Compose pass*** +backend AUTH_PASSWORD Compose pass** backend NORMAL_CONFIG Compose debug -backend SECRET_TOKEN Compose secr*** +backend SECRET_TOKEN Compose secr** diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden index a02b58b2f..6790ed481 100644 --- a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -deployer AWS_ACCESS_KEY_ID Compose AKIA*** -deployer AWS_CLIENT_ID Compose AROA*** -deployer AWS_SECRET_ACCESS_KEY Compose wJal*** -deployer GITHUB_TOKEN Compose ghp_*** +deployer AWS_ACCESS_KEY_ID Compose AKIA** +deployer AWS_CLIENT_ID Compose AROA** +deployer AWS_SECRET_ACCESS_KEY Compose wJal** +deployer GITHUB_TOKEN Compose ghp_** deployer REGION Compose us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden index 033e85eaf..24ba60e75 100644 --- a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden @@ -1,9 +1,9 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -api DATABASE_URL Compose post*** +api DATABASE_URL Compose post** api DB_HOST Compose db.example.com api DB_PORT Compose 5432 -api MONGO_URI Compose mong*** -api MYSQL_URL Compose mysq*** -api REDIS_URL Compose redi*** +api MONGO_URI Compose mong** +api MYSQL_URL Compose mysq** +api REDIS_URL Compose redi** diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden index b3c95e709..e46e74770 100644 --- a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden @@ -2,7 +2,7 @@  SERVICE ENVIRONMENT SOURCE VALUE app APP_ENV Compose production -app ENCRYPTION_KEY Compose 9f86*** +app ENCRYPTION_KEY Compose 9f86** app LOG_LEVEL Compose info -app SESSION_SECRET Compose VEfk*** -app SIGNING_KEY Compose xK9m*** +app SESSION_SECRET Compose VEfk** +app SIGNING_KEY Compose xK9m** diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden index 8670849c4..3588e8a1c 100644 --- a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden @@ -1,10 +1,10 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -backend API_KEY Compose api-*** +backend API_KEY Compose api-** backend APP_NAME Compose my-backend -backend DATABASE_URL Compose post*** -backend GITHUB_TOKEN Compose ghp_*** +backend DATABASE_URL Compose post** +backend GITHUB_TOKEN Compose ghp_** backend LOG_LEVEL Compose info backend NODE_ENV Compose production backend PORT Compose 8080 diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden index ec71555c7..ec0c89826 100644 --- a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden @@ -1,9 +1,9 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -web API_SECRET Compose VEfk*** +web API_SECRET Compose VEfk** web APP_ENV Compose production -web DATABASE_URL Compose post*** -web GITHUB_TOKEN Compose ghp_*** -web POSTGRES_URL Compose post*** +web DATABASE_URL Compose post** +web GITHUB_TOKEN Compose ghp_** +web POSTGRES_URL Compose post** web STATIC_VALUE Compose hello diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden index eb77cea47..15d028fb3 100644 --- a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden @@ -1,8 +1,8 @@  * Service environment variables resolution summary:  SERVICE ENVIRONMENT SOURCE VALUE -web CALLBACK_URL Compose http*** -web REDIS_ALT_URL Compose redi*** -web REDIS_URL Compose redi*** +web CALLBACK_URL Compose http** +web REDIS_ALT_URL Compose redi** +web REDIS_URL Compose redi** web SAFE_URL Compose https://example.com/api/v1 -web WEBHOOK_URL Compose http*** +web WEBHOOK_URL Compose http**