Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 6 additions & 18 deletions packages/cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ var exportCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}

secretsPath, err := cmd.Flags().GetString("path")
secretsPaths, err := cmd.Flags().GetStringArray("path")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
Expand All @@ -92,21 +92,15 @@ var exportCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}

request := models.GetAllSecretsParameters{
multiPathRequest := models.GetMultiPathSecretsParameters{
Environment: environmentName,
TagSlugs: tagSlugs,
WorkspaceId: projectId,
SecretsPath: secretsPath,
TagSlugs: tagSlugs,
SecretsPaths: secretsPaths,
IncludeImport: includeImports,
ExpandSecretReferences: shouldExpandSecrets,
}

if token != nil && token.Type == util.SERVICE_TOKEN_IDENTIFIER {
request.InfisicalToken = token.Token
} else if token != nil && token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER {
request.UniversalAuthAccessToken = token.Token
}

if templatePath != "" {
dynamicSecretLeases := NewDynamicSecretLeaseManager(nil, nil)

Expand All @@ -131,17 +125,11 @@ var exportCmd = &cobra.Command{
return
}

secrets, err := util.GetAllEnvironmentVariables(request, "")
secrets, err := fetchSecrets(multiPathRequest, "", secretOverriding, token)
if err != nil {
util.HandleError(err, "Unable to fetch secrets")
}
Comment on lines +128 to 131

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Duplicate keys in multi-path export output

When two or more paths contain a secret with the same key, fetchSecrets appends all of them into allSecrets and then calls OverrideSecrets, which only resolves personal-vs-shared conflicts — not cross-path conflicts. The result is that the final slice can hold multiple entries for the same key, producing duplicate keys in the exported output (e.g. the same DB_HOST appearing twice in a .env file). In run.go this is silently deduplicated downstream by getSecretsByKeys, which uses a map; the export path has no equivalent step. A consumer that relies on only one value per key (dotenv, yaml) will silently use whichever instance appears last, which may not be the intended one.


if secretOverriding {
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_PERSONAL)
} else {
secrets = util.OverrideSecrets(secrets, util.SECRET_TYPE_SHARED)
}

var output string
secrets = util.FilterSecretsByTag(secrets, tagSlugs)
secrets = util.SortSecretsByKeys(secrets)
Expand Down Expand Up @@ -272,7 +260,7 @@ func init() {
exportCmd.Flags().String("token", "", "Fetch secrets using service token or machine identity access token")
exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs")
exportCmd.Flags().String("projectId", "", "manually set the projectId to export secrets from")
exportCmd.Flags().String("path", "/", "get secrets within a folder path")
exportCmd.Flags().StringArray("path", []string{"/"}, "get secrets within a folder path (can be specified multiple times to merge secrets from multiple paths)")
exportCmd.Flags().String("template", "", "The path to the template file used to render secrets")
exportCmd.Flags().StringP("output-file", "o", "", "The path to write the output file to. Can be a full file path, directory, or filename. If not specified, output will be printed to stdout")
}
Expand Down