Summary
public/formulation/wrappers.go wraps anysdk.Schema values without nil-checking the inner value:
func newWrappedSchemaFromAnySdkSchema(inner anysdk.Schema) Schema {
return &wrappedSchema{inner: inner}
}
When inner is nil this returns a non-nil interface wrapping a nil pointer (the classic Go typed-nil gotcha). Downstream != nil guards pass, and the first accessor call dereferences the nil inner:
func (w *wrappedSchema) GetType() string {
r0 := w.inner.GetType() // panics when inner is nil
return r0
}
All other accessor methods on wrappedSchema (and sibling wrappers constructed the same way) have the same exposure.
Impact
stackql (which pins any-sdk v0.5.3-alpha11, but the code is unchanged at any-sdk HEAD) crashes with a SIGSEGV at plan build time for any EXEC method whose 2xx response schema is an object that does not contain a property matching an exec parameter name (e.g. id). stackql's unary selection deliberately admits param-only columns with a nil schema, passes the nil into formulation.NewColumnDescriptor, and the wrapper converts it into a typed-nil that defeats the nil guard in drm_cfg.go.
In the okta provider alone, 33 operations across 12 services hit this (e.g. activate_user -> UserActivationToken, expire_password_with_temp_password -> tempPassword), and it affects any provider with the same response shape.
Steps to reproduce
No credentials required - the panic occurs at plan build, before auth resolution:
stackql exec "registry pull okta"
stackql exec "EXEC okta.users.users.activate_user @id='dummy', @subdomain='dummy'"
Result:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xc8 pc=0x1b06dd5]
goroutine 1 [running]:
github.com/stackql/any-sdk/public/formulation.(*wrappedSchema).GetType(...)
.../any-sdk@v0.5.3-alpha11/public/formulation/wrappers.go:1378
github.com/stackql/stackql/internal/stackql/drm.(*staticDRMConfig).GenerateSelectDML(...)
.../internal/stackql/drm/drm_cfg.go:725
github.com/stackql/stackql/internal/stackql/primitivegenerator.(*standardPrimitiveGenerator).assembleUnarySelectionBuilder(...)
.../internal/stackql/primitivegenerator/unary_selection.go:118
github.com/stackql/stackql/internal/stackql/primitivegenerator.(*standardPrimitiveGenerator).AnalyzeUnaryExec(...)
.../internal/stackql/primitivegenerator/statement_analyzer.go:672
Working control case: EXEC okta.users.users.expire_password @id='dummy', @subdomain='dummy' plans and dispatches fine, because the User response schema contains an id property, so the schema lookup for the projected id column succeeds.
Proposed fix
newWrappedSchemaFromAnySdkSchema (and the analogous wrapper factories) should return a nil interface when inner is nil, so existing != nil guards in consumers work as written.
- Defense in depth: nil-guard the accessor methods on
wrappedSchema (return zero values for nil inner), since the wrappers are the public API boundary.
Fixing this at the factory kills the whole class of typed-nil crashes at a single choke point. A companion issue will be raised in stackql/stackql to consume the fix and harden its side (param-only columns pushed with nil schema, and the defeated nil guard).
Summary
public/formulation/wrappers.gowrapsanysdk.Schemavalues without nil-checking the inner value:When
inneris nil this returns a non-nil interface wrapping a nil pointer (the classic Go typed-nil gotcha). Downstream!= nilguards pass, and the first accessor call dereferences the nil inner:All other accessor methods on
wrappedSchema(and sibling wrappers constructed the same way) have the same exposure.Impact
stackql (which pins
any-sdk v0.5.3-alpha11, but the code is unchanged at any-sdk HEAD) crashes with a SIGSEGV at plan build time for anyEXECmethod whose 2xx response schema is an object that does not contain a property matching an exec parameter name (e.g.id). stackql's unary selection deliberately admits param-only columns with a nil schema, passes the nil intoformulation.NewColumnDescriptor, and the wrapper converts it into a typed-nil that defeats the nil guard indrm_cfg.go.In the okta provider alone, 33 operations across 12 services hit this (e.g.
activate_user->UserActivationToken,expire_password_with_temp_password->tempPassword), and it affects any provider with the same response shape.Steps to reproduce
No credentials required - the panic occurs at plan build, before auth resolution:
Result:
Working control case:
EXEC okta.users.users.expire_password @id='dummy', @subdomain='dummy'plans and dispatches fine, because theUserresponse schema contains anidproperty, so the schema lookup for the projectedidcolumn succeeds.Proposed fix
newWrappedSchemaFromAnySdkSchema(and the analogous wrapper factories) should return a nil interface wheninneris nil, so existing!= nilguards in consumers work as written.wrappedSchema(return zero values for nil inner), since the wrappers are the public API boundary.Fixing this at the factory kills the whole class of typed-nil crashes at a single choke point. A companion issue will be raised in stackql/stackql to consume the fix and harden its side (param-only columns pushed with nil schema, and the defeated nil guard).