This is related to #14150 and possibly others, but it's actually a separate issue.

For instance, when using the following query:
`bitcoin-cli scantxoutset start '[{"desc":"wpkh(xpubABCDEF/0/*)", "range":100}]'`
I can get a list of UTXOs, but no way to get back the index which derived that particular UTXO. So it's not much better than deriving on the user side and specifying addresses one by one, so that I already have a cache of addresses to match.

Not sure what the solution looks like. One way is to repeat the full descriptor in the utxo. That might get verbose though.
"    addr(<address>)                      Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n"
            "    raw(<hex script>)                    Outputs whose scriptPubKey equals the specified hex scripts\n"
            "    combo(<pubkey>)                      P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
            "    pkh(<pubkey>)                        P2PKH outputs for the given pubkey\n"
            "    sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
            "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
            "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
            "unhardened or hardened child keys.\n"
            "In the latter case, a range needs to be specified by below if different from 1000.\n"
            "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n"
            "\nArguments:\n"
            "1. \"action\"                       (string, required) The action to execute\n"
            "                                      \"start\" for starting a scan\n"
            "                                      \"abort\" for aborting the current scan (returns true when abort was successful)\n"
            "                                      \"status\" for progress report (in %) of the current scan\n"
            "2. \"scanobjects\"                  (array, required) Array of scan objects\n"
            "    [                             Every scan object is either a string descriptor or an object:\n"
            "        \"descriptor\",             (string, optional) An output descriptor\n"
            "        {                         (object, optional) An object with output descriptor and metadata\n"
            "          \"desc\": \"descriptor\",   (string, required) An output descriptor\n"
            "          \"range\": n,             (numeric, optional) Up to what child index HD chains should be explored (default: 1000)\n"
            "        },\n"
            "        ...\n"
            "    ]\n"
            "\nResult:\n"
            "{\n"
            "  \"unspents\": [\n"
            "    {\n"
            "    \"txid\" : \"transactionid\",     (string) The transaction id\n"
            "    \"vout\": n,                    (numeric) the vout value\n"