Skip to content

security(vault-backup): retire the CKV_K8S_40 exception by making snapshots group-readable, then raising the writers' UIDsΒ #3202

Closed

Description

@devantler

πŸ€– Generated by the Agentic Engineer

Evidence

CKV_K8S_40 (containers should run as a high UID to avoid host conflict) is the last checkov
finding on k8s/: a full local reproduction of MegaLinter's invocation reports
kubernetes … Failed checks: 2, and both are the vault-backup workloads β€”
Job.openbao.vault-snapshot-init and CronJob.openbao.vault-snapshot. #2904 dispositioned them as a
scoped, deferred exception; this issue is the durable fix that retires it.

Three facts were measured on the live cluster while dispositioning them, and together they decide the
shape of the fix:

  1. User namespaces are NOT in effect at these sites, so the risk is a host UID. The
    add-user-namespaces rule matches on the namespace label
    pod-security.devantler.tech/user-namespaces: enabled, which live carries exactly
    backstage, crossview, headlamp, homepage, umami, whoami β€” not openbao
    (kubectl get ns openbao -o jsonpath='{.metadata.labels}' returns no such label). The live
    CronJob's hostUsers is unset and the running pod reports HOSTUSERS <none>. So container
    UID 100 maps straight through to host UID 100.
    ⚠️ This refutes the basis security(k8s): CKV_K8S_40 needs one risk acceptance, not 11 per-site constraintsΒ #2904 originally proposed for accepting the finding β€” the
    user-namespace rollout is real, but it does not reach these two workloads.
  2. The snapshot lands -rw-------. From the nightly job's own ls -l:
    -rw------- 1 openbao openbao 459839 Aug 17 03:30 /snapshots/openbao-20260817-033025.snap.
    Owner is UID 100, group GID 1000 β€” and there is no group read bit.
  3. That is why the mirror container inherits 100. minio/mc mounts /snapshots readOnly
    and bakes no uid-100 entry of its own, so it reads the snapshot purely as its owner. Drop it
    to a high UID today and the off-cluster R2 mirror stops being able to open the file β€” silently,
    because the container would still start.

Why this needs its own slice

fsGroup: 1000 is not enough on its own. It fixes ownership and mode at mount time; the snapshot
is created afterwards by bao operator raft snapshot save at the process umask, which is what
produces the 0600 above.

Smallest useful change, in order

  1. Make the snapshot group-readable so access no longer depends on being its owner β€” set the
    umask (or chmod 0640) in the snapshot script, in both job.yaml and cron-job.yaml. Verify on
    the next nightly run that the file lands -rw-r----- and the mirror still uploads.
  2. Then move the UIDs, exactly as vault-config/job.yaml already does: pod-level
    runAsUser: 65532, with runAsUser: 100 set on the openbao container only, keeping
    runAsGroup: 1000 / fsGroup: 1000. The three vault-snapshots writers share one RWO PVC and
    must move together β€” job.yaml, cron-job.yaml and .github/workflows/dr-rebuild.yaml's helper
    pod.

Step 2 touches the DR restore path, so it wants a watched window: run a snapshot, confirm the mirror
uploaded, and confirm dr-rebuild can still read an existing snapshot.

Acceptance criteria

  • The nightly snapshot lands group-readable and the R2 mirror still uploads it.
  • All three vault-snapshots writers run a high pod UID, with 100 scoped to the openbao
    container only.
  • dr-rebuild reads a snapshot written before the change and one written after it.
  • The deferred checkov.io/skip for CKV_K8S_40 is removed from both manifests and checkov
    still reports 0 failed checks.

Rough size: small-to-medium, two steps, second one watched.


Blocker: CLEARED 2026-08-20 β€” acceptance criterion 1 is met on a real snapshot, so step 2 is
now actionable. Verified live against the 2026-08-20T03:30:27Z CronJob run, the first since
#3246 reconciled:

  • the snapshot lands group-readable β€” the job's own ls -l reports
    -rw-r----- 1 openbao openbao 459839 Aug 20 03:30 /snapshots/openbao-20260820-033021.snap,
    against the -rw------- this issue recorded before the change;
  • the mirror still uploads it β€” mc transferred 449.06 KiB of that file to
    backup/platform-backups/openbao-snapshots/, and the post-upload listing shows it present.

⚠️ One nuance the criterion does not by itself settle: on this run the mirror container read the
snapshot as its owner (it still inherits uid 100), so what is proven is that the file is now
group-readable and the pipeline is unbroken β€” not yet that a high-UID mirror can read it. That
is step 2's own watched verification. The supporting mechanism was measured separately in #3258
(fsGroup supplies the group via supplementary groups and the volume setgid bit), so the remaining
risk is the sequencing rather than the premise.

Step 1 merged as #3246 at 2026-08-19T17:41Z and is already reconciled into the live cluster (the
deployed CronJob.openbao.vault-snapshot carries chmod 0640 "$SNAP"). But the last successful
snapshot was 2026-08-19T03:30:27Z β€” before that merge β€” so no group-readable snapshot exists yet
and the mirror has never been exercised against one.

The CronJob schedule is 30 3 * * *, so the first snapshot that proves criterion 1 is the
2026-08-20T03:30Z run. Starting step 2 before then would move the writers' UIDs while the only
evidence that the mirror can still read the file is the reasoning in this issue β€” which is exactly
the silent-failure mode described above (the mirror container would still start, and simply stop
being able to open the snapshot).

Next action on/after 2026-08-20T03:30Z: confirm the new snapshot lands -rw-r----- and that the
mirror container still uploaded it; then criterion 1 is met and step 2 becomes actionable.

Activity

  1. moved this to πŸ“₯ Backlog in 🌊 Project Boardon Aug 18, 2026
  2. coderabbitai commented on Aug 18, 2026

    @coderabbitai
    Contributor
    πŸ”— Related PRs

    #3116 - fix(umami): run the tenant-provisioning container on a read-only root filesystem [merged]
    #3203 - security(vault-backup): disposition the last two CKV_K8S_40 findings as one deferred exception [merged]
    #3246 - security(vault-backup): make the raft snapshot group-readable [merged]
    #3249 - security(umami): raise the provisioning CronJob above the UID/GID floor [merged]
    #3257 - security(k8s): disposition trivy KSV-0020 on the vault-config Job, guarded per container [merged]


    πŸ“ Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    πŸ§ͺ Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    πŸ’¬ Have feedback or questions? Drop into our discord!

  3. devantler commented on Aug 19, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Scope note: this issue owns 14 of the 16 remaining KSV-0020/0021 findings

    Measured on main @4d2a3dc4 with scripts/megalinter-scan-counts.sh --trivy-only (trivy 0.74.0),
    with a per-target breakdown of the same scan:

    file KSV-0020 KSV-0021 total
    k8s/bases/infrastructure/vault-config/job.yaml 2 4 6
    k8s/bases/infrastructure/vault-backup/job.yaml 2 2 4
    k8s/bases/infrastructure/vault-backup/cron-job.yaml 2 2 4
    this issue's total 6 8 14

    The other 2 are umami's, tracked separately in #3221 (which has been rescoped to umami only β€” its
    original text mis-stated the cause as a missing runAsUser/runAsGroup; all these files set both,
    and the findings fire because the values are <= 10000).

    In vault-config/job.yaml the 6 are per-container overrides rather than the pod default: the pod
    runs runAsUser: 65532 / runAsGroup: 1000, and fetch-snapshot, store-keys, vault-init and
    vault-config restate the lower openbao 100:1000 identity. So the sequencing this issue describes
    has to cover the container-level fields too, not just the pod securityContext.

    Expected delta when this lands: trivy 24 β†’ 10, with KSV-0020 7 β†’ 1 and KSV-0021 9 β†’ 1.

  4. self-assigned this
    on Aug 19, 2026
  5. added a commit that references this issue on Aug 19, 2026
  6. devantler commented on Aug 19, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Step 1 shipped; two measured notes that change step 2's scope

    Step 1 is in #3246 β€” chmod 0640 on the snapshot in both writers, so the mirror can read
    it as GROUP rather than as OWNER. Deliberately not Fixes: the UID move is still open here.

    1. chmod, not umask β€” the issue offers them as alternatives, but only one works

    The issue suggests "set the umask (or chmod 0640)". umask cannot do this job: it only ever
    CLEARS permission bits, never adds them. The snapshot lands 0600 under what is presumably a normal
    0022 umask, which means bao is requesting 0600 explicitly β€” and no umask value can widen an
    explicit mode. Lowering the umask would have been a silent no-op that still looked like a fix.
    chmod is correct under either hypothesis, so it is what shipped.

    2. dr-rebuild is a third file-CREATOR, not just a third UID β€” step 2 needs its mode too

    The issue lists dr-rebuild.yaml's helper pod among the three writers that must move UID together.
    Measured while working step 1: that helper also creates a file on the shared PVC β€”
    .github/workflows/dr-rebuild.yaml:428 does
    mc cp "backup/$R2_BUCKET/openbao-snapshots/$NEWEST" "/snapshots/$NEWEST", downloading a snapshot
    from R2 for the restore path.

    So it is not only a UID to raise: the snapshot it writes is read afterwards by the vault-config
    restore Job, and once the UIDs diverge that read depends on the downloaded file's mode exactly the
    way the mirror's read depends on the nightly one. Step 2 should set the mode there as well, or the
    restore path acquires the same owner-coupling step 1 just removed from the backup path.

    Acceptance criteria status

    • Nightly snapshot lands group-readable and the mirror still uploads β€” awaiting the next 03:30 UTC run; the existing ls -l "$SNAP" in both scripts prints the mode, so the job log is the evidence.
    • All three writers on a high pod UID β€” step 2.
    • dr-rebuild reads a pre- and post-change snapshot β€” step 2.
    • checkov.io/skip for CKV_K8S_40 removed β€” step 2 (the skip is deliberately still in place; step 1 does not change any UID).
  7. devantler commented on Aug 20, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    The GID question in step 2 is already answered β€” #3258 measured it.

    The plan here keeps runAsGroup: 1000 at pod level while raising the UIDs, which leaves the
    mirror container inheriting a low primary GID it has no image-baked reason for. That is the same
    defect the UID split fixes, one field over, and it is why the four vault-backup KSV-0021 findings
    survive this issue as written.

    #3258 established, with a paired control, that cross-container access does not depend on a
    shared primary GID: fsGroup sets the volume group and the setgid bit, so files inherit group
    1000 whatever GID their writer runs as, and fsGroup joins every container's supplementary groups.
    With the setgid bit a file written at gid 65532 lands group 1000 and a uid-100/gid-1000 reader can
    read it; without it the file lands group 65532 and that reader cannot.

    So step 2 can raise runAsGroup to 65532 alongside runAsUser, pinning 100/1000 to the openbao
    container only β€” no separate investigation needed. #3264 does exactly that for vault-config.

    ⚠️ This does not touch this issue's own blocker: the snapshot must still land group-readable and
    be mirrored before the UIDs move. Only the GID design question is settled.

  8. added 2 commits that reference this issue on Aug 20, 2026
  9. 10 remaining items

  10. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    #3279 is merged (05:55:11Z), and here is what it actually moved β€” measured, not asserted.

    Like-for-like, one binary. Both numbers come from scripts/megalinter-scan-counts.sh --trivy-only
    run locally with the same trivy 0.74.0, scanned from the repository root with the ignorefile (the
    helper warns that narrowing the target to k8s/ silently inflates the count β€” it does; my first
    attempt did exactly that and reported hundreds of ignorefile-suppressed KSV-0039 rows):

    tree trivy misconfigurations
    main @ b83c9c20 (pre-merge) 8 β€” 4Γ— KSV-0021, 4Γ— KSV-0020
    #3279 head @ 92221a1a 6 β€” 4Γ— KSV-0021, 2Γ— KSV-0020

    So #3279 retires 2 real KSV-0020 findings. That comparison is the point of running both sides
    myself: the issue's standing "8" was measured under trivy 0.73.0, and the helper explicitly warns
    that a rule-set difference between versions can look like backlog movement. Comparing my 6 against
    that 0.73.0 figure would have been an invalid before/after β€” the movement is real precisely because
    both sides were measured with the same binary on the same day.

    The residual 6, named per container (--exit-code 1 --ignorefile .trivyignore.yaml --skip-dirs tests --config-data .trivy/data .):

    workload check container what it wants
    cron-job.yaml (vault-snapshot) KSV-0020 snapshot runAsUser > 10000
    cron-job.yaml KSV-0021 snapshot, mirror runAsGroup > 10000
    job.yaml (vault-snapshot-init) KSV-0020 snapshot runAsUser > 10000
    job.yaml KSV-0021 snapshot, mirror runAsGroup > 10000

    Both residual classes are load-bearing, which is why they did not fall out with the rest:

    • KSV-0020 Γ—2 β€” snapshot at UID 100. That is the openbao image's baked openbao:x:100:1000
      user, which runAsUser/runAsGroup merely restate; the same identity already carries a scoped
      CKV_K8S_40 disposition in these files for checkov. Raising it means the openbao binary no longer
      runs as the user its image provisions.
    • KSV-0021 Γ—4 β€” runAsGroup/fsGroup 1000. This is exactly the mechanism security(vault-backup): raise the snapshot writers off the host UIDΒ #3279 just built: the
      snapshot is written 0640 and mirror reads it as a group member rather than by being its owner.
      Raising the GID above 10000 without changing the image would break the handoff this issue exists to
      create.

    I am deliberately NOT filing "disposition the residual 6" as ready work. Whether the GID can be
    raised depends on whether the openbao image tolerates a runAsGroup other than its baked 1000, and I
    have not tested that. That is a real fix if it holds and a scoped .trivyignore.yaml disposition only
    if it does not β€” and the ladder says try the fix first. Getting that order right needs one experiment,
    not an assumption.

    Recording this against #2787 as well, since REPOSITORY_TRIVY cannot leave DISABLE_ERRORS_LINTERS
    until this residual is at zero.

  11. added a commit that references this issue on Aug 21, 2026
  12. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Step 2 started in #3281 β€” the mirror half of it.

    Measured, not inherited. Re-ran the repo's own scan (scripts/megalinter-scan-counts.sh --trivy-only, trivy 0.74.0, scan root the repository root, repo flags) against main at a0537f33: 6 misconfigurations β€” KSV-0021 Γ—4, KSV-0020 Γ—2, all on vault-backup's job.yaml and cron-job.yaml. After #3281: 4.

    The 6 split into two genuinely different causes, which is what makes half of this shippable now:

    Container Finding Cause Disposition
    mirror (minio/mc) KSV-0021 Γ—2 inherited pod runAsGroup: 1000 fixed in #3281 β€” mc bakes no group, so 1000 was never its identity
    snapshot (openbao) KSV-0021 Γ—2, KSV-0020 Γ—2 image-baked openbao:x:100:1000 still open β€” the actual "raise the writers' UIDs" half

    The mirror half needed no experiment: fsGroup supplies cross-container access through supplementary groups and the volume setgid bit, so reading the 0640 snapshot #3279 established never depended on the mirror's primary gid. vault-config already does exactly this (pod runAsGroup: 65532, fsGroup: 1000) and pinned the mechanism there against a paired control (#3258).

    The snapshot half is NOT ready and I did not guess at it. Raising UID 100 means running the openbao binary as an identity its own image does not define, and the honest test is to run that pinned digest under a non-baked uid/gid and observe it. I could not do that this run β€” the local container runtime is not available, and I will not mutate prod to find out. So it stays open with the experiment named rather than asserted.

  13. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Correcting my previous comment. I wrote that the mirror half "needed no experiment". That was wrong, and #3281 is closed because of it.

    scripts/tests/test-vault-snapshot-group-readable.sh pins pod runAsGroup: 1000 deliberately, and states the mechanism it is protecting: the mirror reads the snapshot on its primary GROUP entry alone β€” "a pod-level property, which is why this does not depend on the volume's setgid bit."

    My justification leaned on vault-config, which does run pod runAsGroup: 65532 with fsGroup: 1000. It differs exactly where it matters: its shared paths are emptyDir; /snapshots is a PVC. The setgid + supplementary-group behaviour #3258 verified was verified on emptyDir, and the guard's author chose primary-GID sharing here precisely so this path would not depend on it. I treated the two as equivalent on the one point where they are not.

    So the residual is 4, not 2 β€” and the two halves are coupled, which is the substantive correction to my earlier table:

    Container Finding Blocked on
    mirror (minio/mc) KSV-0021 Γ—2 proving a non-primary group entry can read the 0640 snapshot off the PVC
    snapshot (openbao) KSV-0021 Γ—2, KSV-0020 Γ—2 running the pinned openbao digest under a non-baked uid/gid

    Concrete next step, so this is a design rather than an open question: pod-level supplementalGroups: [1000] grants group 1000 to every container explicitly, independent of both the primary GID and the setgid bit. That would let runAsGroup rise above 10000 while making the invariant stronger than it is today, because the access no longer rests on an implicit mechanism.

    It also implies the guard should assert the property rather than the implementation β€” "the mirror holds group 1000", by primary or supplemental β€” instead of runAsGroup == 1000. That is a widening of what the test accepts, so it only goes in together with evidence, never ahead of it.

    The evidence still owed is one read: a gid-65532 process opening a 0640 snapshot on that PVC. Until someone runs it, this stays open rather than shipped β€” the failure mode is the nightly backup silently ceasing to mirror, which is not a thing to infer.

  14. added 2 commits that reference this issue on Aug 21, 2026
  15. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Re-measured on a0537f33 with trivy v0.74.0, since this issue's own note says the counts drift.

    The residual is 6, not 8, and it splits unevenly:

    check job.yaml cron-job.yaml what carries it
    KSV-0020 (UID ≀ 10000) 1 1 snapshot only β€” openbao image-defined UID 100
    KSV-0021 (GID ≀ 10000) 2 2 snapshot (image-defined) and mirror (inherits pod GID 1000)

    Two measurement notes, both of which cost a wrong reading if skipped:

    • KSV-0125 "trusted registries" is a phantom unless the scan passes --data .trivy/data. Without it, four extra MEDIUM findings appear on these two files that CI never sees.
    • Scanning k8s/ rather than the repo root makes trivy report targets relative to k8s/, so the ignorefile's k8s/-prefixed paths: stop matching and already-dispositioned findings reappear β€” including vault-config's. That is an artifact of the invocation, not a regression.

    Why the two halves need different answers. The KSV-0020 premise is settled: all four openbao container references in this repository pin the identical digest sha256:fdc6da21ca…171f0806, so the /etc/passwd//etc/group measurement behind vault-config's accepted disposition is a measurement of this image rather than an analogy to it. Ruled on in #3282.

    KSV-0021 is not settled, and this is where #3281 went wrong. Its premise requires the pod default GID to be high so the non-openbao container takes it; here the pod default is 1000, so mirror inherits a group chosen for openbao and minio/mc bakes no such identity. vault-config can make that split because its shared paths are emptyDir, where fsGroup's setgid bit carries the group whatever gid the writer runs as (#3258). These snapshots live on a PVC, where that has not been established.

    The decisive missing evidence is one line: whether /snapshots actually carries the setgid bit. Nothing currently logs it β€” the snapshot script prints ls -l of the file, whose group is 1000 either way, so it cannot distinguish setgid inheritance from the shared primary GID. An ls -ld /snapshots in the snapshot container would settle it on the next nightly run.

    Step 1 is confirmed complete in production: the 2026-08-21 03:30 run logged Widened 14 snapshot(s) on the shared PVC to 0640 with zero warnings, so every retained snapshot is already group-readable and no longer depends on the writer owning it.

  16. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Criterion 1 re-verified live β€” now on a second consecutive run

    Re-checked against the cluster rather than inheriting the 2026-08-20 note, because a cleared blocker
    is exactly the kind of record that goes stale in the wrong direction. It has not: the
    2026-08-21T03:30Z run completed successfully, and both halves hold again.

    The snapshot lands group-readable:

    -rw-r----- 1 openbao openbao 457274 Aug 21 03:30 /snapshots/openbao-20260821-033020.snap
    

    And the mirror still uploaded it β€” the post-upload remote listing shows
    openbao-20260821-033020.snap present, alongside an unbroken daily series.

    One thing worth recording that the earlier check did not mention: the job also reports

    Widened 14 snapshot(s) on the shared PVC to 0640.
    

    so the backfill covers the existing snapshots on the PVC, not just newly written ones. A
    high-UID reader introduced by step 2 would therefore find the whole retained set readable, not only
    files created after the change β€” which removes a retention-window edge this issue would otherwise
    have had to reason about.

    Status

    Criterion 1 is met on two consecutive runs (2026-08-20 and 2026-08-21), so step 2 remains
    actionable
    and is not blocked. The residual risk is unchanged and is sequencing, not premise: the
    mirror container has so far read the snapshot as its owner, so a high-UID mirror reading it by
    group is still what step 2's own watched verification has to establish. The supporting mechanism
    (fsGroup supplying the group via supplementary groups plus the volume setgid bit) was measured in
    #3258.

    The live CronJob confirms the pod carries fsGroup: 1000 alongside runAsGroup: 1000, so the
    supplementary-group path is present in the deployed spec.

    ⚠️ Note for whoever picks this up: the verification is next-day, because the schedule is
    30 3 * * *. Step 2 should be started early enough in a run to land before a 03:30Z boundary, or
    explicitly handed forward with the watch recorded β€” not merged and forgotten.

    Part of #2787.

  17. devantler commented on Aug 21, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Correcting the previous comment: step 2 is MERGED and LIVE, not "still actionable"

    The 11:11Z comment above concluded "step 2 remains actionable and is not blocked". That was
    already wrong when it was written: #3279 β€” which is step 2 β€” merged at 05:55:11Z, and the
    comment at 05:56:55Z on this same issue says so. The 11:11Z status was re-derived from this
    issue's body rather than from main, which is exactly the failure mode
    monorepo#2967 was filed about.

    Verified live, from the deployed spec β€” the manifest change has reconciled:

    runAsUser
    pod default 65532 (runAsGroup/fsGroup 1000)
    init/snapshot 100 β€” the openbao image's baked identity, scoped to this container alone
    ctr/mirror inherits 65532 ← the behaviour under test

    πŸ”΄ But the run that has already happened under the new identity is a VACUOUS PASS β€” do not close on it

    A vault-snapshot-init Job ran at 05:52:21Z, its frozen pod spec carries exactly the new
    identity above, and it Succeeded. That is a very easy thing to mistake for this issue's
    acceptance evidence, so it is worth stating plainly why it is not:

    • the init/snapshot container logged A snapshot from today already exists β€” nothing to do, so
      no new snapshot was written;
    • the mirror container therefore reported Total 0 B / Transferred 0 B and listed an unbroken
      remote series.

    mc mirror decides "nothing to transfer" by listing and comparing source against destination,
    which needs traverse/read on the directory. It does not establish that a process at UID 65532
    can open a snapshot file. The property this issue actually has to prove β€” the mirror reading the
    snapshot by group rather than by ownership β€” was not exercised by that run.

    The supporting mechanism is sound and measured (pod-level runAsGroup: 1000 makes 1000 the mirror's
    primary group, and the snapshot lands -rw-r----- owned by group 1000, re-confirmed on the
    2026-08-21 nightly), but a mechanism argument is not the E2E observation the acceptance criteria ask
    for.

    Named measurement date

    The first nightly that can supply the evidence is 2026-08-22T03:30Z β€” the schedule is
    30 3 * * * and #3279 merged after today's 03:30Z run, so no nightly has yet written a snapshot
    with the mirror at 65532. Until then this is skip-clause-(d) work: delivered, awaiting a named future
    measurement, not unstarted.

    What that run must show, all three together β€” a snapshot written today, a non-zero transfer by
    the mirror at 65532, and a successful upload. A Succeeded Job with a 0 B transfer is the vacuous
    case above and does not count.

    One criterion needs a decision, separately

    Acceptance criterion 4 asks for the checkov.io/skip for CKV_K8S_40 to be removed from both
    manifests with checkov still at 0 failed. As shipped, the skip is retained but narrowed β€” #3282
    re-based it on the openbao image's own openbao:x:100:1000 identity, scoped to the single container
    that cannot avoid it. Removing it now would simply make checkov fail, since that container still runs
    UID 100 by construction.

    That is the "scoped, justified exception for a genuinely irreducible control" rung of the
    fix-vs-except ladder rather than a retired exception, so criterion 4 as literally written is not
    reachable without rebuilding the upstream image. Flagging it rather than rewriting it unilaterally,
    since the delivering PR deliberately used Part of, not Fixes.

    Part of #2787.

  18. devantler commented on Aug 22, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    First non-vacuous nightly verification passed

    The scheduled 2026-08-22 03:30 UTC run exercised the property this issue was waiting for:

    • the pod default and mirror ran at UID 65532, while only the OpenBao snapshot container used its image-defined UID 100;
    • the new snapshot landed mode 0640;
    • the mirror transferred a non-zero 448.56 KiB and the new object appeared in the remote listing;
    • both containers exited successfully.

    This clears the watched UID-migration acceptance window. The permanent CKV_K8S_40 disposition remains correctly scoped to the OpenBao image container; removing it literally would fail Checkov without changing that image-defined identity. The four KSV-0021 group findings remain visible under #2787 and are not being folded into this verdict.

    Draft #3298 updates exact-main comments that still described the UID disposition as deferred and the mirror as the file owner. Keep this issue open until that documentation correction lands; then the UID-migration leaf can close without losing the separate KSV-0021 residual.

  19. devantler commented on Aug 22, 2026

    @devantler
    ContributorAuthor

    πŸ€– Generated by the Agentic Engineer

    Completed by #3298 at reviewed head 144f680e7299c1607b277aa1a8bfb87b0198c0a1, merged as signed main@554a3c85a5dc98e8004081bbf4bbb7ca0a423042.

    Merge-group CI and deployment run 32559633335 succeeded; Flux applied latest@sha256:a81046eac9a76708a7d87c7857f93b91bb2d8c816cd0a739c00858023e9f8ca9 Ready. This closes the UID/CKV_K8S_40 leaf after the accepted nightly backup proof with mode 0640.

    The four KSV-0021 group-identity findings remain live under #2787; this closure does not disposition them.

  20. moved this from πŸ‘€ In Review to βœ… Done in 🌊 Project Boardon Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Fields

No fields configured for Security.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions