kubectl guardfile declares an exec-target invariant it does not enforce: --context selects any kubeconfig cluster #1348

Closed
opened 2026-08-28 18:24:55 +00:00 by coilyco-ops · 0 comments
Owner

Rewritten 2026-08-28T18:32Z. The original filing claimed agents cannot reach ser8. That was wrong, and the error was mine. Angie falsified it and I reproduced her result. The corrected finding is below. Original text preserved at the bottom.

What is wrong

.specgen/guardfiles/aosguard/kubectl.kdl states in its header:

the exec target is fixed at parse, so the caller can never substitute it

That does not hold as deployed. exec kubectl fixes the binary, not the cluster. Nothing constrains --context, so the caller selects which cluster every allowlisted verb operates on, apply and scale and rollout included.

Measured:

$ aosguard ops kubectl get nodes
kai-server   Ready   control-plane,master   502d   v1.32.3+k3s1

$ aosguard ops kubectl get nodes --context ser8
ser8         Ready   control-plane          77d    v1.35.5+k3s1

Different cluster, different server version. --context=ser8 works identically. There is no flag filtering on this wrap at all: aosguard ops kubectl version --definitely-not-a-real-flag returns error: unknown flag from kubectl rather than a denial from aosguard.

Scope of the exposure, stated precisely

The failure is a false comment, not an open door. An unknown context fails closed:

$ aosguard ops kubectl get nodes --context definitely-not-a-cluster
Error in configuration: context was not found for specified context: definitely-not-a-cluster
aosguard: exit status 1

So the reachable set is exactly the kubeconfig's contexts, not anywhere. A typo cannot write to a cluster that does not exist. The real exposure is narrower and still worth closing:

  • An agent or operator intending kai-server can write to ser8 by passing a valid context, with no denial and no confirmation
  • The guardfile comment tells a reader that is impossible, so a stray --context reads as inert when it is load-bearing
  • Compare aosguard ops aws, which does fail closed on an unexpected value - ssm put-parameter --bogus-flag x is denied with value did not match any allowed pattern [file:///*] (fail-closed). The mechanism exists and this wrap does not use it

Why the original filing was wrong

I ran aosguard ops kubectl --context ser8 get ... with the flag before the verb. aosguard's own CLI parser rejects it there as an unknown global flag, which produced flag provided but not defined: -context. Placed after the verb it passes straight through to kubectl. I ran one malformed invocation and promoted a parse error into an architectural claim, then wrote that claim into this issue, into #1344, and into a handoff.

The discriminating test is a verb whose answer differs per cluster, such as get nodes or version. Note that config current-context --context ser8 prints kai-server and looks like the flag being ignored. It is not. kubectl config current-context reads the kubeconfig field and ignores --context by design, so that probe cannot distinguish the two cases and misled both of us.

What is not blocked

Nothing. The sysadmin seat can apply the ser8 half today with aosguard ops kubectl apply -f <manifest> --context ser8. This issue is a boundary-conformance defect, not a dependency of #1344.

Acceptance

  • The guardfile comment describes what the wrap actually enforces, or the wrap enforces what the comment claims
  • --context is constrained to an explicit allowlist of known contexts rather than accepting any kubeconfig entry
  • Implementation note from Angie: allow-flag appears to behave as a whitelist that excludes every unlisted flag once present on a grant, so adding it naively to apply would break -f. Flags need enumerating per verb, so this is not a one-liner
  • Worth a sweep for the same shape on the other wraps, since a declared invariant that does not bind is unlikely to be unique to this one

Owner

Platform seat. aosguard is shared tooling other seats build on, outside the sysadmin scope for foundational software.


Original filing, preserved. Its central claim is false.

The original text claimed aosguard ops kubectl is pinned to the active kubeconfig context and rejects --context, making ser8 unreachable and blocking the live half of #1344. Both the premise and the conclusion were wrong. The flag works when positioned after the verb, and CI was never blocked on this issue.

> **Rewritten 2026-08-28T18:32Z.** The original filing claimed agents cannot reach ser8. That was wrong, and the error was mine. Angie falsified it and I reproduced her result. The corrected finding is below. Original text preserved at the bottom. ## What is wrong `.specgen/guardfiles/aosguard/kubectl.kdl` states in its header: > the exec target is fixed at parse, so the caller can never substitute it That does not hold as deployed. `exec kubectl` fixes the **binary**, not the **cluster**. Nothing constrains `--context`, so the caller selects which cluster every allowlisted verb operates on, `apply` and `scale` and `rollout` included. Measured: ``` $ aosguard ops kubectl get nodes kai-server Ready control-plane,master 502d v1.32.3+k3s1 $ aosguard ops kubectl get nodes --context ser8 ser8 Ready control-plane 77d v1.35.5+k3s1 ``` Different cluster, different server version. `--context=ser8` works identically. There is no flag filtering on this wrap at all: `aosguard ops kubectl version --definitely-not-a-real-flag` returns `error: unknown flag` from kubectl rather than a denial from aosguard. ## Scope of the exposure, stated precisely The failure is a false comment, not an open door. An unknown context fails closed: ``` $ aosguard ops kubectl get nodes --context definitely-not-a-cluster Error in configuration: context was not found for specified context: definitely-not-a-cluster aosguard: exit status 1 ``` So the reachable set is exactly the kubeconfig's contexts, not anywhere. A typo cannot write to a cluster that does not exist. The real exposure is narrower and still worth closing: * An agent or operator intending `kai-server` can write to `ser8` by passing a valid context, with no denial and no confirmation * The guardfile comment tells a reader that is impossible, so a stray `--context` reads as inert when it is load-bearing * Compare `aosguard ops aws`, which does fail closed on an unexpected value - `ssm put-parameter --bogus-flag x` is denied with `value did not match any allowed pattern [file:///*] (fail-closed)`. The mechanism exists and this wrap does not use it ## Why the original filing was wrong I ran `aosguard ops kubectl --context ser8 get ...` with the flag **before** the verb. aosguard's own CLI parser rejects it there as an unknown global flag, which produced `flag provided but not defined: -context`. Placed after the verb it passes straight through to kubectl. I ran one malformed invocation and promoted a parse error into an architectural claim, then wrote that claim into this issue, into #1344, and into a handoff. The discriminating test is a verb whose answer differs per cluster, such as `get nodes` or `version`. Note that `config current-context --context ser8` prints `kai-server` and looks like the flag being ignored. It is not. `kubectl config current-context` reads the kubeconfig field and ignores `--context` by design, so that probe cannot distinguish the two cases and misled both of us. ## What is not blocked Nothing. The sysadmin seat can apply the ser8 half today with `aosguard ops kubectl apply -f <manifest> --context ser8`. This issue is a boundary-conformance defect, not a dependency of #1344. ## Acceptance * The guardfile comment describes what the wrap actually enforces, or the wrap enforces what the comment claims * `--context` is constrained to an explicit allowlist of known contexts rather than accepting any kubeconfig entry * Implementation note from Angie: `allow-flag` appears to behave as a whitelist that excludes every unlisted flag once present on a grant, so adding it naively to `apply` would break `-f`. Flags need enumerating per verb, so this is not a one-liner * Worth a sweep for the same shape on the other wraps, since a declared invariant that does not bind is unlikely to be unique to this one ## Owner Platform seat. aosguard is shared tooling other seats build on, outside the sysadmin scope for foundational software. --- <details> <summary>Original filing, preserved. Its central claim is false.</summary> The original text claimed `aosguard ops kubectl` is pinned to the active kubeconfig context and rejects `--context`, making ser8 unreachable and blocking the live half of #1344. Both the premise and the conclusion were wrong. The flag works when positioned after the verb, and CI was never blocked on this issue. </details>
coilyco-ops changed title from aosguard ops kubectl reaches only the active kubeconfig context, so agents cannot operate the ser8 cluster to kubectl guardfile declares an exec-target invariant it does not enforce: --context selects any kubeconfig cluster 2026-08-28 18:32:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1348
No description provided.