Skip to content

Commit

Permalink
Do not return ephemeral values to unsupported plugins
Browse files Browse the repository at this point in the history
Because ephemeral values are likely to contain secrets,
return ErrSensitive for plugins that do not support it
to prevent unintended disclosure.
  • Loading branch information
wata727 committed Jan 4, 2025
1 parent 71d5558 commit ccab0bf
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
6 changes: 5 additions & 1 deletion plugin/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/plugin/plugin2host"
"github.com/terraform-linters/tflint-plugin-sdk/terraform/lang/marks"
sdk "github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint/terraform"
"github.com/terraform-linters/tflint/tflint"
Expand Down Expand Up @@ -145,7 +146,10 @@ func (s *GRPCServer) EvaluateExpr(expr hcl.Expression, opts sdk.EvaluateExprOpti

// SDK v0.16+ introduces client-side handling of unknown/NULL/sensitive values.
if s.clientSDKVersion != nil && s.clientSDKVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.16.0"))) {
return val, nil
// Before SDK v0.22, ephemeral marks are ignored, so retrun ErrSensitive to prevent secrets ​​from being leaked.
if !marks.Contains(val, marks.Ephemeral) || s.clientSDKVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.22.0"))) {
return val, nil
}
}

if val.ContainsMarked() {
Expand Down
46 changes: 46 additions & 0 deletions plugin/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,11 @@ variable "sensitive" {
default = "foo"
}
variable "ephemeral" {
ephemeral = true
default = "foo"
}
variable "no_default" {}
variable "null" {
Expand All @@ -472,6 +477,7 @@ variable "foo" {
server := NewGRPCServer(runner, rootRunner, runner.Files(), SDKVersion)

sdkv15 := version.Must(version.NewVersion("0.15.0"))
sdkv21 := version.Must(version.NewVersion("0.21.0"))

// test util functions
hclExpr := func(expr string) hcl.Expression {
Expand Down Expand Up @@ -542,6 +548,15 @@ variable "foo" {
return err == nil || !errors.Is(err, sdk.ErrSensitive)
},
},
{
Name: "sensitive value (SDK v0.21)",
Args: func() (hcl.Expression, sdk.EvaluateExprOption) {
return hclExpr(`var.sensitive`), sdk.EvaluateExprOption{WantType: &cty.String, ModuleCtx: sdk.SelfModuleCtxType}
},
Want: cty.StringVal("foo").Mark(marks.Sensitive),
SDKVersion: sdkv21,
ErrCheck: neverHappend,
},
{
Name: "no default",
Args: func() (hcl.Expression, sdk.EvaluateExprOption) {
Expand Down Expand Up @@ -622,6 +637,37 @@ variable "foo" {
return err == nil || !errors.Is(err, sdk.ErrNullValue)
},
},
{
Name: "ephemeral value",
Args: func() (hcl.Expression, sdk.EvaluateExprOption) {
return hclExpr(`var.ephemeral`), sdk.EvaluateExprOption{WantType: &cty.String, ModuleCtx: sdk.SelfModuleCtxType}
},
Want: cty.StringVal("foo").Mark(marks.Ephemeral),
ErrCheck: neverHappend,
},
{
Name: "ephemeral value (SDK v0.21)",
Args: func() (hcl.Expression, sdk.EvaluateExprOption) {
return hclExpr(`var.ephemeral`), sdk.EvaluateExprOption{WantType: &cty.String, ModuleCtx: sdk.SelfModuleCtxType}
},
Want: cty.NullVal(cty.NilType),
SDKVersion: sdkv21,
ErrCheck: func(err error) bool {
return err == nil || !errors.Is(err, sdk.ErrSensitive)
},
},
{
Name: "ephemeral value in object (SDK v0.21)",
Args: func() (hcl.Expression, sdk.EvaluateExprOption) {
ty := cty.Object(map[string]cty.Type{"value": cty.String})
return hclExpr(`{ value = var.ephemeral }`), sdk.EvaluateExprOption{WantType: &ty, ModuleCtx: sdk.SelfModuleCtxType}
},
Want: cty.NullVal(cty.NilType),
SDKVersion: sdkv21,
ErrCheck: func(err error) bool {
return err == nil || !errors.Is(err, sdk.ErrSensitive)
},
},
}

for _, test := range tests {
Expand Down

0 comments on commit ccab0bf

Please sign in to comment.