Repository: dbt-labs/dbt-core
Issue: [CT-114] Avoid saving secrets in SecretContext

From https://github.com/dbt-labs/dbt-core/issues/4642#issuecomment-1026015170:

> The place that needs to be fixed is in core/dbt/context/secret.py, in the env_var method. Where it saved the return_value in self.env_vars, we want to skip saving if the env_var if it starts with the SECRET_ENV_PREFIX.

(feel free to update with more details)

Changed files:
core/dbt/context/secret.py, test/integration/068_partial_parsing_tests/test_pp_vars.py

diff --git a/core/dbt/context/secret.py b/core/dbt/context/secret.py
index f61538536..5a53f2d47 100644
--- a/core/dbt/context/secret.py
+++ b/core/dbt/context/secret.py
@@ -4,6 +4,7 @@ from typing import Any, Dict, Optional
 from .base import BaseContext, contextmember
 
 from dbt.exceptions import raise_parsing_error
+from dbt.logger import SECRET_ENV_PREFIX
 
 
 class SecretContext(BaseContext):
@@ -27,7 +28,11 @@ class SecretContext(BaseContext):
             return_value = default
 
         if return_value is not None:
-            self.env_vars[var] = return_value
+            # do not save secret environment variables
+            if not var.startswith(SECRET_ENV_PREFIX):
+                self.env_vars[var] = return_value
+
+            # return the value even if its a secret
             return return_value
         else:
             msg = f"Env var required but not provided: '{var}'"
diff --git a/test/integration/068_partial_parsing_tests/test_pp_vars.py b/test/integration/068_partial_parsing_tests/test_pp_vars.py
index 08b6b1625..344ab2c38 100644
--- a/test/integration/068_partial_parsing_tests/test_pp_vars.py
+++ b/test/integration/068_partial_parsing_tests/test_pp_vars.py
@@ -300,6 +300,64 @@ class ProjectEnvVarTest(BasePPTest):
         # cleanup
         del os.environ['ENV_VAR_NAME']
 
+
+class ProfileSecretEnvVarTest(BasePPTest):
+
+    @property
+    def profile_config(self):
+        # Need to set these here because the base integration test class
+        # calls 'load_config' before the tests are run.
+        # Note: only the specified profile is rendered, so there's no
+        # point it setting env_vars in non-used profiles.
+        os.environ['NOT_SECRET_USER'] = 'root'
+        os.environ['DBT_ENV_SECRET_PASS'] = 'password'
+        return {
+            'config': {
+                'send_anonymous_usage_stats': False
+            },
+            'test': {
+                'outputs': {
+                    'dev': {
+                        'type': 'postgres',
+                        'threads': 1,
+                        'host': self.database_host,
+                        'port': 5432,
+                        'user': "root",
+                        'pass': "password",
+                        'user': "{{ env_var('NOT_SECRET_USER') }}",
+                        'pass': "{{ env_var('DBT_ENV_SECRET_PASS') }}",
+                        'dbname': 'dbt',
+                        'schema': self.unique_schema()
+                    },
+                },
+                'target': 'dev'
+            }
+        }
+
+    @use_profile('postgres')
+    def test_postgres_secret_env_vars(self):
+        # Initial run
+        self.setup_directories()
+        self.copy_file('test-files/model_one.sql', 'models/model_one.sql')
+        results = self.run_dbt(["run"])
+        manifest = get_manifest()
+
+        breakpoint()
+        
+        # find the non-secret in the manifest, we expect it to be there.
+        self.assertEqual(manifest.env_vars['NOT_SECRET_USER'], 'root')
+
+        # attempt to find the secret in the manifest. hopefully it's not there
+        try:
+            manifest.env_vars['x']
+            self.assertTrue(False, 'A secret was saved when it shouldn\\'t have been')
+        except KeyError:
+            self.AssertTrue(True)
+
+        # cleanup
+        del os.environ['NOT_SECRET_USER']
+        del os.environ['DBT_ENV_SECRET_PASS']
+
 class ProfileEnvVarTest(BasePPTest):
 
     @property