#7675·checkov

terraform_plan: false positives on resources removed from state via `removed` block ('forget' action)

Author: v3n7iCreated Sep 9, 2026Updated Sep 9, 2026

Describe the issue

Checkov consistently returns False Positives on terraform_plan scans in which the plan JSON contains resources being removed from state (no destroy). This issue is applicable to any Terraform resource type (as long they have change action 'forget'), and any applicable resource/value check against them.

These False Positives are caused by a Bug upstream in Terraform (https://github.com/hashicorp/terraform/issues/38641): with the introduction of the removed {} block in Terraform v1.7.0, a bug was introduced whereby resources being removed from state using the removed {} block with lifecycle { destroy = false } would mistakenly get included stripped of values in the planned_values section of the terraform plan JSON.

This is a confirmed bug upstream which has since been fixed in Terraform 1.15.6 and higher:

As part of the process to remove a resource from state, Terraform removes all configuration values associated to the resource. The resource is not meant to be present in planned_values (as it is being removed from the state managed by Terraform) but due to the aforementioned bug, the 'forgotten' resource falls through into planned_values with an empty configuration. Given the resource is in planned_values, Checkov will run its checks against it, but since none of the values the checks are looking for will be present, it will return multiple false positive failures.

Checkov should filter out these problematic 'forget' resources in its plan_parser to account for the bug and effectively apply the same fix introduced upstream by Terraform in https://github.com/hashicorp/terraform/pull/38665. The issue is fixed in future versions of Terraform, but it persists in all prior versions where the fix didn't get a backport, representing the majority of versions currently widely adopted by companies that tend to lag behind latest version. It may take years for the fixed version to be adopted. These Terraform versions are scanned by Checkov and will keep returning false positives unless Checkov introduces a fix on its end to account for the bug.

Examples & Steps to reproduce

In this section I show an example focused on a single policy (CKV_AWS_145) for simplicity, but the bug is not policy specific, its framework specific (terraform_plan). In the example I configure an S3 bucket with SSE Encryption (CKV_AWS_145: PASS). I then remove the resource from state using the removed block, which results in a false positive CKV_AWS_145 FAIL. The resource is not deleted (its only removed from state) and its configuration was not explicitly modified to remove encryption. The resource config is instead completely replaced by the removed block altogether, reason why in a normal terraform scan CKV_AWS_145 does not run at all. But in the terraform_plan scans CKV_AWS_145 returns a false positive failure.

Generate JSON Plan Sample

  1. Create an S3 resource with SSE encryption
hcl
# main.tf

resource "aws_s3_bucket" "test_bucket" {
  bucket = "test-bucket"
}

resource "aws_kms_key" "test_key" {
  description         = "KMS key"
  enable_key_rotation = true
}

resource "aws_s3_bucket_server_side_encryption_configuration" "test_sse" {
  bucket = aws_s3_bucket.test_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.test_key.arn
    }
  }
}
  1. Generate json plan: terraform plan -out=tfplan.binary followed by terraform show -json tfplan.binary > tfplan.json (gist containing json plan output from this step )
  2. Run Checkov against it: checkov --framework terraform_plan -f plan.json --check CKV_AWS_145 The policy passes as expected.
Image
  1. Apply the configuration: terraform apply
  2. Remove the S3 Bucket from state (no destroy).
hcl
# main.tf

# replace the main.tf config with this block
removed {
  from = aws_s3_bucket.test_bucket
  lifecycle {
    destroy=false
  }
}
  1. Generate plan json: terraform plan -out=tfplan.binary followed by terraform show -json tfplan.binary > tfplan.json (gist containing json plan output from this step)
  2. Run Checkov: checkov --framework terraform_plan -f plan.json --check CKV_AWS_145 The policy return a false positive fail.
Image

Expected Outcome

The 'forgotten' S3 resource should have not been scanned at all. In the example CKV_AWS_145 should have not ran, which is the exact behaviour present during a normal terraform scan. If a Checkov terraform scan is ran against the main.tf file that generated the faulty json terraform plan in this example, CKV_AWS_145 won't return any output, the policy won't run. Instead, during a terraform_plan scan, CKV_AWS_145 is run against the resource and returns a false positive failure. It can be seen in the terraform plan json from step 6 (this gist), how the aws_s3_bucket.test_bucket has no values in planned_values compared to its representation in prior_state. This trips the checkov policy. Can also see the 'forget' change action in resource_changes.

Version

  • Checkov 3.3.16 (and virtually any prior version)