Repository: valkey-io/valkey
File: src/acl.c (C)

Code before:
     * mentioned in the command arguments */
    const int channel_flags = CMD_CHANNEL_PUBLISH | CMD_CHANNEL_SUBSCRIBE;
    if (!(selector->flags & SELECTOR_FLAG_ALLCHANNELS) && doesCommandHaveChannelsWithFlags(cmd, channel_flags)) {
        getKeysResult channels;
        initGetKeysResult(&channels);
        getChannelsFromCommand(cmd, argv, argc, &channels);
        keyReference *channelref = channels.keys;
        for (int j = 0; j < channels.numkeys; j++) {
            int idx = channelref[j].pos;
            if (!(channelref[j].flags & channel_flags)) continue;
            int is_pattern = channelref[j].flags & CMD_CHANNEL_PATTERN;
            int ret =
                ACLCheckChannelAgainstList(selector->channels, argv[idx]->ptr, sdslen(argv[idx]->ptr), is_pattern);
            if (ret != ACL_OK) {
                if (keyidxptr) *keyidxptr = channelref[j].pos;
                getKeysFreeResult(&channels);
                return ret;
            }
        }
        getKeysFreeResult(&channels);
    }
    return ACL_OK;
}

/**
 * Checks whether the given user has permission to access a specified key.
 *
 * This function verifies the access control list (ACL) permissions for a user on a key.
 * If the user pointer is  NULL, the connection is considered authorized to run any
 * command and the function returns  ACL_OK.  Otherwise, the function iterates
 * through the user's ACL selectors and returns  ACL_OK as soon as any selector
 * grants permission.  If no selector grants permission,  ACL_DENIED_KEY is returned.
 *
 * Input parameters:
 *
 * - u Pointer to a user structure. If  NULL, the user is treated as
 *    having unrestricted access.
 * - key Pointer to the key string to check.
 * - keylen Length of the key string in bytes.
 * - flags Flags that may influence selector checks (implementation-specific).
 * - is_prefix true if key should be treated as a prefix in selector
 *    evaluation; false otherwise.
 *
 * Returns ACL_OK if access is granted, ACL_DENIED_KEY if access is denied.
 *
 * NOTE: The function performs no modification of the  user structure or the key;
 *       it only evaluates read-only selectors.
 */
int ACLUserCheckKeyPerm(user *u, const char *key, int keylen, int flags, bool is_prefix) {
    listIter li;
    listNode *ln;

Review comment (security):
```suggestion
/* Checks whether the given user has permission to access a specified key.
```

Code after:
    /* Check if the user can execute commands explicitly touching the channels
     * mentioned in the command arguments */
    const int channel_flags = CMD_CHANNEL_PUBLISH | CMD_CHANNEL_SUBSCRIBE;
    if (!(selector->flags & SELECTOR_FLAG_ALLCHANNELS) && doesCommandHaveChannelsWithFlags(cmd, channel_flags)) {
        getKeysResult channels;
        initGetKeysResult(&channels);
        getChannelsFromCommand(cmd, argv, argc, &channels);
        keyReference *channelref = channels.keys;
        for (int j = 0; j < channels.numkeys; j++) {
            int idx = channelref[j].pos;
            if (!(channelref[j].flags & channel_flags)) continue;
            int is_pattern = channelref[j].flags & CMD_CHANNEL_PATTERN;
            int ret =
                ACLCheckChannelAgainstList(selector->channels, argv[idx]->ptr, sdslen(argv[idx]->ptr), is_pattern);
            if (ret != ACL_OK) {
                if (keyidxptr) *keyidxptr = channelref[j].pos;
                getKeysFreeResult(&channels);
                return ret;
            }
        }
        getKeysFreeResult(&channels);
    }
    return ACL_OK;
}

/* Checks whether the given user has permission to access a specified key.
 *
 * This function verifies the access control list (ACL) permissions for a user on a key.
 * If the user pointer is  NULL, the connection is considered authorized to run any
 * command and the function returns  ACL_OK.  Otherwise, the function iterates
 * through the user's ACL selectors and returns  ACL_OK as soon as any selector
 * grants permission.  If no selector grants permission,  ACL_DENIED_KEY is returned.
 *
 * Input parameters:
 *
 * - u Pointer to a user structure. If  NULL, the user is treated as
 *    having unrestricted access.
 * - key Pointer to the key string to check.
 * - keylen Length of the key string in bytes.
 * - flags Flags that may influence selector checks (implementation-specific).
 * - is_prefix true if key should be treated as a prefix in selector
 *    evaluation; false otherwise.
 *
 * Returns ACL_OK if access is granted, ACL_DENIED_KEY if access is denied.
 *
 * NOTE: The function performs no modification of the  user structure or the key;
 *       it only evaluates read-only selectors.
 */
int ACLUserCheckKeyPerm(user *u, const char *key, int keylen, int flags, bool is_prefix) {
    listIter li;
    listNode *ln;