microsoft/aspire · critical · InvalidOperationException

ASPIRERADIUS063

ASPIRERADIUS063

Error message

Secret store '{storeName}' references a SealedSecret manifest at '{manifestPath}' whose '{LastAppliedConfigurationAnnotation}' annotation embeds a plaintext Kubernetes Secret (kind 'Secret' with 'data'/'stringData'), or content that cannot be verified as sealed. Such annotations are copied verbatim into publish artifacts and applied to the cluster, so the cleartext would leak. Re-seal from a clean manifest without the annotation. Diagnostic: ASPIRERADIUS063.

What it means

The sealed-secrets workflow can leave a last-applied-configuration annotation embedding the original plaintext Secret JSON (with data/stringData). Since Aspire copies the SealedSecret manifest verbatim into publish artifacts, such an annotation would leak cleartext credentials; validation fails closed when the annotation exists and either is not a JSON string scalar or embeds a plaintext Secret.

Solutions

  1. Remove the last-applied-configuration annotation from the SealedSecret and re-seal from a clean manifest.
  2. Re-generate with kubeseal from a fresh source Secret: 'kubectl create secret generic x --from-literal=... -o yaml --dry-run=client | kubeseal -o yaml > sealed.yaml' (dry-run output carries no recorded annotation).
  3. If the annotation is intentionally non-secret JSON that fails the check, remove it anyway — the validator cannot verify it is sealed and fails closed.

Example fix

// before (metadata.annotations contains)
kubectl.kubernetes.io/last-applied-configuration: '{"kind":"Secret","data":{"password":"cGFzcw=="}}'
// after
metadata:
  name: my-secret  # annotation removed; re-sealed from clean manifest
Defensive patterns

Strategy: validation

Validate before calling

var annotations = doc["metadata"]?["annotations"];
if (annotations?["kubectl.kubernetes.io/last-applied-configuration"] is { }) throw new InvalidOperationException("SealedSecret embeds last-applied-configuration annotation; re-seal from a clean manifest.");

Type guard

bool HasLastAppliedAnnotation(YamlNode root) => root is YamlMappingNode m && m["metadata"] is YamlMappingNode md && md["annotations"] is YamlMappingNode a && a.Children.ContainsKey(new YamlScalarNode("kubectl.kubernetes.io/last-applied-configuration"));

Try / catch

try { store = ReadValidated(...); } catch (InvalidOperationException ex) when (ex.Message.Contains("ASPIRERADIUS063")) { // strip the annotation and re-seal; do NOT commit the manifest }

Prevention

When it happens

Trigger: CheckLastAppliedAnnotation (called by RejectPlaintextLastAppliedAnnotation during manifest validation) finds the last-applied-configuration annotation whose value is not a plain JSON string scalar, or whose embedded JSON contains a 'Secret' kind with data/stringData.

Common situations: Manifest created by 'kubectl apply -f secret.yaml && kubeseal' without cleaning the recorded annotation (kubectl apply records it), or an annotation value that is a YAML mapping/null rather than a JSON string.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/c46ebff8e8009c7d. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Radius/Secrets/SealedSecretManifest.cs:351

    }

    private static void CheckLastAppliedAnnotation(
        string storeName, string manifestPath, YamlMappingNode owner)
    {
        if (!TryGetNode(owner, "metadata", out var metadataNode) || metadataNode is not YamlMappingNode metadata ||
            !TryGetNode(metadata, "annotations", out var annotationsNode) || annotationsNode is not YamlMappingNode annotations ||
            !TryGetNode(annotations, LastAppliedConfigurationAnnotation, out var valueNode))
        {
            return;
        }

        // The annotation is present. A legitimate value is always a JSON string scalar (Kubernetes
        // annotation values are `map[string]string`). Anything else — a YAML mapping/sequence, or a
        // null/empty scalar where we expected JSON — cannot be verified free of cleartext, so fail
        // closed rather than skip it.
        if (valueNode is not YamlScalarNode { Value: { } lastApplied } || EmbedsPlaintextSecret(lastApplied))
        {
            throw new InvalidOperationException(
                $"Secret store '{storeName}' references a SealedSecret manifest at '{manifestPath}' whose " +
                $"'{LastAppliedConfigurationAnnotation}' annotation embeds a plaintext Kubernetes Secret " +
                "(kind 'Secret' with 'data'/'stringData'), or content that cannot be verified as sealed. Such " +
                "annotations are copied verbatim into publish artifacts and applied to the cluster, so the " +
                "cleartext would leak. Re-seal from a clean manifest without the annotation. " +
                "Diagnostic: ASPIRERADIUS063.");
        }
    }

    // Example annotation value (a single JSON string):
    //   {"apiVersion":"v1","kind":"Secret","metadata":{...},"data":{"password":"cGFzcw=="}}
    // Returns true when that JSON is a plaintext Secret carrying data/stringData, or when it cannot
    // be parsed as the expected object (fail closed). An embedded SealedSecret returns false.
    private static bool EmbedsPlaintextSecret(string lastAppliedJson)
    {
        try
        {
            using var document = JsonDocument.Parse(lastAppliedJson);

View on GitHub (pinned to 25830f84bd)