You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(execution): enforce suspension on every personal-secret path, and align webhook cleanup
Review round 2 (Greptile P1 security, cubic P0 — both found the same gap).
The suspension check sat next to the split-identity access lookups, so it was
skipped by the single-identity shortcut above it. That shortcut is taken whenever
the two identities coincide — which is exactly what happens when a custom-block
publisher is also their workspace's billing account. The check now runs before
the shortcut, unconditionally.
Round 1's placement rested on "admission already cleared this identity", and that
is not true everywhere: a custom-block child is admitted by
`admitCustomBlockChildExecution`, which checks usage limits and nothing else, and
a provider URL-validation challenge resolves its secret with no admission at all.
Neither path has ever had a ban gate.
Only the personal namespace is withheld. Workspace variables belong to the
workspace rather than to a person, so they keep resolving and a suspended
member's teammates keep working — the reason admission stopped blocking on this
identity to begin with.
Webhook cleanup now resolves through the same two-identity reader as delivery.
Reading both slices as the owner let cleanup see a narrower selection than the
delivery that created the subscription: a non-admin owner without a credential
grant left `{{VAR}}` unresolved, the provider was handed the literal reference as
its credential, and the non-fatal catch silently orphaned the subscription.
`resolveBackgroundWebhookEnv` imports the billing reader statically. The dynamic
import bought nothing — every boundary audit passes without it — and made each
worker pay a cold module load on the first webhook resolution.
Restores the `@sim/testing` mock-shape test, which pins that the default snapshot
carries every field of the real one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments