Encrypt/decrypt app secret variables (#17394)

Closes https://github.com/twentyhq/core-team-issues/issues/1724
From PR https://github.com/twentyhq/twenty/pull/15283, followed same
implementation
- Introduce EnvironmentModule to provide type safety for env-only
variables
- Encrypt secret variables
- When querying app secret variable, display up to first 5 characters
(depending on secret length) then `******`
This commit is contained in:
Marie
2026-01-27 16:59:37 +01:00
committed by GitHub
parent a913ac7452
commit 7e3d9cd85a
19 changed files with 865 additions and 156 deletions
@@ -10,6 +10,7 @@ import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
import { FileModule } from 'src/engine/core-modules/file/file.module';
import { SecretEncryptionModule } from 'src/engine/core-modules/secret-encryption/secret-encryption.module';
import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.module';
import { CronTriggerEntity } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
import { DatabaseEventTriggerEntity } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
@@ -51,6 +52,7 @@ import { FunctionBuildModule } from 'src/engine/metadata-modules/function-build/
SubscriptionsModule,
WorkspaceCacheModule,
TokenModule,
SecretEncryptionModule,
],
providers: [
ServerlessFunctionService,
@@ -18,6 +18,7 @@ import { AuditService } from 'src/engine/core-modules/audit/services/audit.servi
import { SERVERLESS_FUNCTION_EXECUTED_EVENT } from 'src/engine/core-modules/audit/utils/events/workspace-event/serverless-function/serverless-function-executed';
import { ApplicationTokenService } from 'src/engine/core-modules/auth/token/services/application-token.service';
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
import { SecretEncryptionService } from 'src/engine/core-modules/secret-encryption/secret-encryption.service';
import { buildEnvVar } from 'src/engine/core-modules/serverless/drivers/utils/build-env-var';
import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service';
import { getServerlessFolderOrThrow } from 'src/engine/core-modules/serverless/utils/get-serverless-folder-or-throw.utils';
@@ -70,6 +71,7 @@ export class ServerlessFunctionService {
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly applicationService: ApplicationService,
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly secretEncryptionService: SecretEncryptionService,
) {}
async hasServerlessFunctionPublishedVersion(
@@ -205,7 +207,7 @@ export class ServerlessFunctionService {
[DEFAULT_API_KEY_NAME]: applicationAccessToken.token,
}
: {}),
...buildEnvVar(flatApplicationVariables),
...buildEnvVar(flatApplicationVariables, this.secretEncryptionService),
};
// We keep that check to build functions