The cap_copy_int() function is quite permissive when reading externalized capabilities, but the cap_copy_ext() hard codes the size. It seems as if they could both be more flexible when the raised capabilities are all in the lower bits. That is, when libcap (v1) only supported 32-bit capabilities, it exported them with 3*4 byte vectors. These external vectors could be imported when applied on 64-bit capable systems. But the other direction (exported from 64-bit) was not supported even when only the first 32-capability bits were being used. While we are not yet close to expanding beyond 64 bits, I'd like to avoid this issue recurring.
It turns out that the Go functions cap.Import() and cap.Export() already work this way. That being said, in case anyone is using the libcap C functions and depends on their current behavior, I'm going to preserve cap_copy_ext() behavior for current external representations. All of the libcap/cap (Go) and libcap (C) functions interoperate on external data.
Fixed in: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=1a5a67b48cbcb83a968f973b2207c1d4b833a6dd