Skip to content

commandstore cache poisoning after transient Get failure following successful status update #7230

Description

@vanshika2720

Description

commandstore can cache an invalid zero-value Command when backend.Get fails immediately after UpdateStatus succeeds.

Details

  • pkg/app/server/commandstore/store.go:106-120
  • pkg/app/server/commandstore/cache.go:29-48

If backend.Get fails after UpdateStatus has already succeeded, the error is effectively swallowed and the resulting nil command is passed to the cache.

The nil value is marshaled to JSON as null. When null is later unmarshaled into a non-pointer Command struct, Go treats it as a no-op, leaving a zero-value Command, including PipedId="".

Subsequent Get calls can therefore return a valid-looking zero-value command instead of the actual command.

This can cause ReportCommandHandled to return PermissionDenied for the legitimate piped. Since ReportCommandHandled is also the RPC that could otherwise repair the cache, this can leave manual-approval/cancel commands stuck indefinitely.

Suggested fix

Either:

  • return the backend.Get error instead of continuing and caching the invalid result, or
  • skip cache.Put when cmd == nil.

Additionally, add a nil guard in commandCache.Put so a nil command cannot be cached accidentally.

Tests

There currently does not appear to be a test file for this package.

Add a regression test covering the following sequence:

  1. UpdateStatus succeeds.
  2. The subsequent backend.Get fails.
  3. The failed result is not cached.
  4. A later Get does not return a zero-value Command.
  5. ReportCommandHandled continues to work for the legitimate piped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugSomething isn't working as expected

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions