Skip to content

containment-broker: a malformed attestation escapes validatePrelaunchAttestation as a bare TypeError instead of an enumerated refusal #35

Description

@thegeorgepu

Found by adversarial review of #30 and reproduced locally — verified, not a report.

In the capability loop at vinci/containment-broker/src/admission.mjs:119-121 the guard is written
sortedUniqueStrings(capabilities ?? []), but the very next line uses sha256(capabilities) with no
?? []. When an attestation omits capabilities (or one of the five sets), capabilities is
undefined, sortedUniqueStrings([]) returns true, so the else if runs and
canonicalBytes(undefined) throws.

$ node -e 'validatePrelaunchAttestation({ attestation: { no_new_privs: true }, policy: {} })'
threw: TypeError | code: (none) | reasons: (none)
message: unsupported canonical value: undefined
CONFIRMED — escapes as a bare TypeError, not AdmissionRefusedError

Why it matters. validatePrelaunchAttestation is a refusal path: it is supposed to fail with
AdmissionRefusedError carrying code and an enumerated reasons list. A malformed attestation
instead escapes as a bare TypeError with neither. Any caller branching on e.code === "CONTAINMENT_ADMISSION_REFUSED"
mishandles it, and the enumerated refusal reasons — the thing that makes a refusal auditable — are lost.
A missing field should be a reason, not a crash.

Every sibling check in the same function (limits, supplementary_groups, inherited_fds,
ingress, controller_objects) is guarded. This one is the outlier.

Suggested fix. sha256(capabilities ?? []), and a test that a wholly empty attestation object
produces AdmissionRefusedError with reasons rather than a TypeError.

Not a regression from #30; pre-existing in the v3 boundary.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions