Back to blog
AWSBest PracticesCloud SecurityOperations & ComplianceStorage

Athena Workgroup Results Not Encrypted: Why It Matters and How to Fix It

Athena workgroups can write query results to S3 in plaintext. Learn why unencrypted results are a risk and how to enforce SSE-KMS encryption with CLI and Terraform.

TL;DR

This check flags Athena workgroups that do not force encryption on query results written to S3. Anyone with read access to the results bucket can see raw query output in plaintext. Fix it by enabling EnforceWorkGroupConfiguration with an encryption option (SSE_S3, SSE_KMS, or CSE_KMS) on the workgroup.

Amazon Athena is convenient precisely because it sits on top of S3 and lets you run SQL against data you already have. But that same convenience hides a detail people forget: every query Athena runs writes its results back to an S3 location, and unless you tell it otherwise, those result files can land unencrypted. This check catches workgroups where encryption of query results is not enforced.

The risk is easy to underestimate. The query result might contain a subset of your most sensitive data, joined, filtered, and conveniently flattened into a CSV. If that bucket is readable by the wrong principal, you have handed over exactly the data someone would want, already packaged.


What this check detects

The athena_unencrypted check inspects each Athena workgroup and looks at its result configuration. Specifically, it verifies two things:

  • The workgroup has an encryption configuration set for query results (SSE_S3, SSE_KMS, or CSE_KMS).
  • The workgroup enforces its own configuration so that individual users cannot override it and write results without encryption.

If a workgroup has no EncryptionConfiguration, or if it allows clients to override the settings, the check fails.

Note: Athena workgroups serve two purposes. They isolate query history and cost controls between teams, and they hold the result configuration (output location plus encryption). Settings can come from the workgroup or from a client-side request. The EnforceWorkGroupConfiguration flag decides which one wins.


Why it matters

Athena query results are not transient. They persist in S3 as physical objects, often in a folder like s3://aws-athena-query-results-<account>-<region>/, and they stick around until a lifecycle policy or someone cleans them up. Each file is the materialized output of a query, which means it frequently contains the sensitive columns analysts actually care about: customer emails, payment identifiers, internal financial figures, PII pulled from a data lake.

Here is what goes wrong when encryption is not enforced:

  • Plaintext data at rest. Without server-side encryption, the result objects sit in S3 unencrypted. If the bucket is misconfigured or shared too broadly, anyone with s3:GetObject reads the raw output directly.
  • Compliance gaps. Frameworks like PCI DSS, HIPAA, and SOC 2 expect encryption of sensitive data at rest. An unencrypted result bucket is an easy finding for an auditor, and harder to explain when the source tables were encrypted but the query output was not.
  • Inconsistent controls. Teams encrypt their data lake carefully, then leak the same data through query results that bypass those controls. The output bucket becomes a side door around your encryption posture.
  • Key-scoped access is lost. When you use SSE-KMS, access to the data depends on access to the KMS key, not just the bucket. Without KMS, a bucket policy is your only gate, and bucket policies drift.

A common breach pattern is not the breach of a primary database. It is the discovery of an exported copy, a backup, or a query result that nobody remembered was sitting in plaintext.


How to fix it

The fix is to set an encryption configuration on the workgroup and enforce it. You can do this in the console, the CLI, or infrastructure as code.

Option 1: AWS Console

  1. Open the Athena console and go to Workgroups.
  2. Select the workgroup and choose Edit.
  3. Under Query result configuration, set or confirm the S3 output location.
  4. Check Encrypt query results and pick an encryption type. For most cases, choose SSE-KMS and select a customer managed key.
  5. Check Override client-side settings. This is what enforces the workgroup config so users cannot opt out.
  6. Save.

Option 2: AWS CLI

Update an existing workgroup to enforce SSE-KMS encryption on results:

aws athena update-work-group \
  --work-group analytics-team \
  --configuration-updates '{
    "EnforceWorkGroupConfiguration": true,
    "ResultConfigurationUpdates": {
      "OutputLocation": "s3://aws-athena-query-results-123456789012-us-east-1/",
      "EncryptionConfiguration": {
        "EncryptionOption": "SSE_KMS",
        "KmsKey": "arn:aws:kms:us-east-1:123456789012:key/abcd1234-..."
      }
    }
  }'

If you only need server-side S3-managed encryption with no KMS key, the encryption block is simpler:

aws athena update-work-group \
  --work-group analytics-team \
  --configuration-updates '{
    "EnforceWorkGroupConfiguration": true,
    "ResultConfigurationUpdates": {
      "EncryptionConfiguration": { "EncryptionOption": "SSE_S3" }
    }
  }'

Verify the change:

aws athena get-work-group --work-group analytics-team \
  --query 'WorkGroup.Configuration.{Enforce:EnforceWorkGroupConfiguration,Enc:ResultConfiguration.EncryptionConfiguration}'

Warning: SSE-KMS adds KMS API calls for every result write, which has a small per-request cost and counts against KMS request quotas. For high-volume Athena usage this is usually negligible, but if you run thousands of queries an hour, consider a bucket key to reduce KMS calls. Enable it on the S3 bucket with BucketKeyEnabled.

Option 3: Terraform

resource "aws_athena_workgroup" "analytics" {
  name = "analytics-team"

  configuration {
    enforce_workgroup_configuration    = true
    publish_cloudwatch_metrics_enabled = true

    result_configuration {
      output_location = "s3://aws-athena-query-results-123456789012-us-east-1/"

      encryption_configuration {
        encryption_option = "SSE_KMS"
        kms_key_arn       = aws_kms_key.athena.arn
      }
    }
  }
}

Danger: If you switch an existing workgroup to SSE-KMS, every principal that reads query results now also needs kms:Decrypt on the key. Roll out the key policy change before or alongside the encryption change, or you will break dashboards, BI tools, and downstream jobs that read those result files. Test with a non-production workgroup first.

Tip: Encrypting the workgroup output does not encrypt result files written by older queries. Sweep the result bucket and re-encrypt or expire stale objects. An S3 lifecycle rule that expires query results after 30 days keeps the blast radius small and the storage bill lower.


How to prevent it from happening again

One-time fixes drift. New teams spin up new workgroups, and the default workgroup (primary) ships without enforced encryption. Bake the control in.

Block unenforced workgroups in CI/CD

If you manage Athena with Terraform, run a policy-as-code gate before apply. A Checkov example:

checkov -d ./infra --check CKV_AWS_82,CKV_AWS_159

Or write an OPA/Conftest rule that rejects any workgroup missing encryption enforcement:

package athena

deny[msg] {
  rc := input.resource.aws_athena_workgroup[name]
  not rc.configuration[_].enforce_workgroup_configuration
  msg := sprintf("workgroup %q must enforce workgroup configuration", [name])
}

deny[msg] {
  rc := input.resource.aws_athena_workgroup[name]
  cfg := rc.configuration[_]
  not cfg.result_configuration[_].encryption_configuration
  msg := sprintf("workgroup %q must set result encryption", [name])
}

Guardrail with SCPs and Config

Use AWS Config with a custom rule to continuously evaluate workgroups, and pair it with an auto-remediation that calls update-work-group when a non-compliant workgroup appears. For organization-wide enforcement, a Service Control Policy can deny athena:CreateWorkGroup and athena:UpdateWorkGroup calls that do not include an encryption configuration, though SCP condition support for these actions is limited, so treat Config remediation as the primary control.

Tip: Lensix runs this check continuously across your accounts and surfaces every workgroup, including the often-forgotten primary default, so you find drift the moment a new workgroup is created rather than at audit time.


Best practices

  • Always enforce, never just configure. Setting encryption without EnforceWorkGroupConfiguration = true lets clients override it. The enforce flag is the part that actually protects you.
  • Prefer SSE-KMS with a customer managed key for sensitive data. It lets you control access through the key policy and gives you a clean audit trail in CloudTrail for every decrypt.
  • Lock down the result bucket. Block public access, enable default bucket encryption, and scope the bucket policy to the workgroup's principals. Encryption is one layer, access control is another.
  • Expire results aggressively. Query results are usually disposable. A short lifecycle policy reduces both cost and the amount of sensitive data sitting around.
  • Don't ignore the default workgroup. Most accounts run queries through primary at some point. Apply the same enforcement there.
  • Encrypt the source too. Enforcing result encryption is pointless if the underlying tables in your data lake are unencrypted. Treat this as one piece of a consistent S3 encryption posture.

Athena makes querying data trivial, and that means it makes copying data trivial. Every result file is a copy. Enforcing encryption on the workgroup is a small configuration change that closes a quiet but real exposure, and it costs you almost nothing to keep enforced.