I think this source code from cgoCheckPointer hints at the reason:
// When and if we implement a moving garbage collector,
// cgoCheckPointer will pin the pointer for the duration of the cgo
// call. (This is necessary but not sufficient; the cgo program will
// also have to change to pin Go pointers that cannot point to Go
// pointers.)
If passing pointers to pointers was allowed, then if/when Go ever starts moving its allocations, though the slice itself was pinned, any pointer elements within the slice could be moved at any time and cgo could end up accessing freed/repurposed memory. To prevent that, cgoCheckPointer would have to do something like recursivelly pin the entire graph of pointers to pointers to pointers…, disable moving all together for programs that use cgo, perhaps disable moving during a cgo call, etc.