diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c
index 6a8c3955ba39630bdab5c83d3d836409ab96c656..3c2ea38706b547c4512cff27a22f735c47675595 100644
--- a/apps/app_agent_pool.c
+++ b/apps/app_agent_pool.c
@@ -455,11 +455,17 @@ struct agents_cfg {
 	struct ao2_container *agents;
 };
 
+static const char *agent_type_blacklist[] = {
+	"general",
+	"agents",
+	NULL,
+};
+
 static struct aco_type agent_type = {
 	.type = ACO_ITEM,
 	.name = "agent-id",
-	.category_match = ACO_BLACKLIST,
-	.category = "^(general|agents)$",
+	.category_match = ACO_BLACKLIST_ARRAY,
+	.category = (const char *)agent_type_blacklist,
 	.item_alloc = agent_cfg_alloc,
 	.item_find = agent_cfg_find,
 	.item_offset = offsetof(struct agents_cfg, agents),
@@ -471,8 +477,8 @@ static struct aco_type *agent_types[] = ACO_TYPES(&agent_type);
 static struct aco_type general_type = {
 	.type = ACO_GLOBAL,
 	.name = "global",
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 static struct aco_file agents_conf = {
diff --git a/apps/app_skel.c b/apps/app_skel.c
index b3c887685753806813661c90d20fbc39ae6e5d4f..68f313feed0052d5dae61f3ef17135ad0715d467 100644
--- a/apps/app_skel.c
+++ b/apps/app_skel.c
@@ -242,8 +242,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "globals",
 	.item_offset = offsetof(struct skel_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -253,18 +253,24 @@ static struct aco_type sound_option = {
 	.type = ACO_GLOBAL,
 	.name = "sounds",
 	.item_offset = offsetof(struct skel_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^sounds$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "sounds",
 };
 
 struct aco_type *sound_options[] = ACO_TYPES(&sound_option);
 
+static const char *level_categories[] = {
+	"general",
+	"sounds",
+	NULL,
+};
+
 /*! \brief An aco_type structure to link the everything but the "general" and "sounds" categories to the skel_level type */
 static struct aco_type level_option = {
 	.type = ACO_ITEM,
 	.name = "level",
-	.category_match = ACO_BLACKLIST,
-	.category = "^(general|sounds)$",
+	.category_match = ACO_BLACKLIST_ARRAY,
+	.category = (const char *)level_categories,
 	.item_alloc = skel_level_alloc,
 	.item_find = skel_level_find,
 	.item_offset = offsetof(struct skel_config, levels),
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index 6659305760dbf300c50fb11011f86fad39db865d..99eea0a27ab2eb7b519547a2ea4582270406bc15 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -409,7 +409,7 @@
 						regardless if this limit is reached or not.
 					</para></description>
 				</configOption>
-				<configOption name="^sound_">
+				<configOption name="sound_">
 					<synopsis>Override the various conference bridge sound files</synopsis>
 					<description><para>
 						All sounds in the conference are customizable using the bridge profile options below.
@@ -639,8 +639,8 @@ static void *bridge_profile_find(struct ao2_container *container, const char *ca
 static struct aco_type bridge_type = {
 	.type = ACO_ITEM,
 	.name = "bridge_profile",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.matchfield = "type",
 	.matchvalue = "bridge",
 	.item_alloc = bridge_profile_alloc,
@@ -676,8 +676,8 @@ static void *user_profile_find(struct ao2_container *container, const char *cate
 static struct aco_type user_type = {
 	.type = ACO_ITEM,
 	.name  = "user_profile",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.matchfield = "type",
 	.matchvalue = "user",
 	.item_alloc = user_profile_alloc,
@@ -707,8 +707,8 @@ static void *menu_find(struct ao2_container *container, const char *category)
 static struct aco_type menu_type = {
 	.type = ACO_ITEM,
 	.name = "menu",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.matchfield = "type",
 	.matchvalue = "menu",
 	.item_alloc = menu_alloc,
@@ -725,8 +725,8 @@ static struct aco_type *user_types[] = ACO_TYPES(&user_type);
 static struct aco_type general_type = {
 	.type = ACO_GLOBAL,
 	.name = "global",
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 static struct aco_file confbridge_conf = {
@@ -2235,7 +2235,7 @@ int conf_load_config(void)
 	aco_option_register(&cfg_info, "record_command", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_command));
 	aco_option_register(&cfg_info, "regcontext", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, regcontext));
 	aco_option_register(&cfg_info, "language", ACO_EXACT, bridge_types, "en", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, language));
-	aco_option_register_custom(&cfg_info, "^sound_", ACO_REGEX, bridge_types, NULL, sound_option_handler, 0);
+	aco_option_register_custom(&cfg_info, "sound_", ACO_PREFIX, bridge_types, NULL, sound_option_handler, 0);
 	aco_option_register(&cfg_info, "video_update_discard", ACO_EXACT, bridge_types, "2000", OPT_UINT_T, 0, FLDSET(struct bridge_profile, video_update_discard));
 	/* This option should only be used with the CONFBRIDGE dialplan function */
 	aco_option_register_custom(&cfg_info, "template", ACO_EXACT, bridge_types, NULL, bridge_template_handler, 0);
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index 210cf36c6c7cffd96d8eea3e1a6fc9687a2e3d93..6e8ce354a1c4c207f6fcf835b071017ba4675f5d 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -541,8 +541,8 @@ static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
 static struct aco_type endpoint_option = {
 	.type = ACO_ITEM,
 	.name = "endpoint",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.item_alloc = jingle_endpoint_alloc,
 	.item_find = jingle_endpoint_find,
 	.item_offset = offsetof(struct jingle_config, endpoints),
diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h
index f4c3db188fd4ac7c221536d6551a943bfe56e81f..3227f94eb9c5825e73c9862b7dc2d4a1359f1fe0 100644
--- a/include/asterisk/config_options.h
+++ b/include/asterisk/config_options.h
@@ -40,18 +40,30 @@ struct aco_type_internal;
 enum aco_type_t {
 	ACO_GLOBAL,
 	ACO_ITEM,
+	ACO_IGNORE,
 };
 
-/*! \brief Whether a category regex is a blackist or a whitelist */
+/*! Type of category matching to perform */
 enum aco_category_op {
+	/*! Regex based blacklist. */
 	ACO_BLACKLIST = 0,
+	/*! Regex based whitelist. */
 	ACO_WHITELIST,
+	/*! Blacklist with a single string matched with strcasecmp. */
+	ACO_BLACKLIST_EXACT,
+	/*! Whitelist with a single string matched with strcasecmp. */
+	ACO_WHITELIST_EXACT,
+	/*! Blacklist with a NULL terminated array of strings matched with strcasecmp. */
+	ACO_BLACKLIST_ARRAY,
+	/*! Whitelist with a NULL terminated array of strings matched with strcasecmp. */
+	ACO_WHITELIST_ARRAY,
 };
 
 /*! \brief What kind of matching should be done on an option name */
 enum aco_matchtype {
 	ACO_EXACT = 1,
 	ACO_REGEX,
+	ACO_PREFIX,
 };
 
 /*! Callback functions for option parsing via aco_process_config() */
diff --git a/main/cdr.c b/main/cdr.c
index 0e0366836656618116ad39b77d60147a3b4d456f..0f6a66517fb0d288a532609d6d2ae1027007346f 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -238,8 +238,29 @@ static struct aco_type general_option = {
 	.type = ACO_GLOBAL,
 	.name = "general",
 	.item_offset = offsetof(struct module_config, general),
-	.category = "^general$",
-	.category_match = ACO_WHITELIST,
+	.category = "general",
+	.category_match = ACO_WHITELIST_EXACT,
+};
+
+/*! Config sections used by existing modules. Do not add to this list. */
+static const char *ignore_categories[] = {
+	"csv",
+	"custom",
+	"manager",
+	"odbc",
+	"pgsql",
+	"radius",
+	"sqlite",
+	"tds",
+	"mysql",
+	NULL,
+};
+
+static struct aco_type ignore_option = {
+	.type = ACO_IGNORE,
+	.name = "modules",
+	.category = (const char*)ignore_categories,
+	.category_match = ACO_WHITELIST_ARRAY,
 };
 
 static void *module_config_alloc(void);
@@ -249,8 +270,7 @@ static void module_config_post_apply(void);
 /*! \brief The file definition */
 static struct aco_file module_file_conf = {
 	.filename = "cdr.conf",
-	.skip_category = "(^csv$|^custom$|^manager$|^odbc$|^pgsql$|^radius$|^sqlite$|^tds$|^mysql$)",
-	.types = ACO_TYPES(&general_option),
+	.types = ACO_TYPES(&general_option, &ignore_option),
 };
 
 CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
diff --git a/main/cel.c b/main/cel.c
index faf4fde7164873be8855b8407ae6cf865cf58d56..cec0a85e4931d4930c5f11c3e681c374215e25b4 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -242,15 +242,28 @@ static struct aco_type general_option = {
 	.type = ACO_GLOBAL,
 	.name = "general",
 	.item_offset = offsetof(struct cel_config, general),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
+};
+
+/*! Config sections used by existing modules. Do not add to this list. */
+static const char *ignore_categories[] = {
+	"manager",
+	"radius",
+	NULL,
+};
+
+static struct aco_type ignore_option = {
+	.type = ACO_IGNORE,
+	.name = "modules",
+	.category = (const char*)ignore_categories,
+	.category_match = ACO_WHITELIST_ARRAY,
 };
 
 /*! \brief The config file to be processed for the module. */
 static struct aco_file cel_conf = {
 	.filename = "cel.conf",                  /*!< The name of the config file */
-	.types = ACO_TYPES(&general_option),     /*!< The mapping object types to be processed */
-	.skip_category = "(^manager$|^radius$)", /*!< Config sections used by existing modules. Do not add to this list. */
+	.types = ACO_TYPES(&general_option, &ignore_option),     /*!< The mapping object types to be processed */
 };
 
 static int cel_pre_apply_config(void);
diff --git a/main/config_options.c b/main/config_options.c
index a9a145b96a166947fe33b00a65cb7503982bb192..1f4f99b722495b196769bb5dbdfacea3668c1e84 100644
--- a/main/config_options.c
+++ b/main/config_options.c
@@ -131,7 +131,7 @@ static int noop_handler_fn(const struct aco_option *opt, struct ast_variable *va
 static int chararray_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
 
 #ifdef AST_XML_DOCS
-static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, unsigned int matches);
+static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, enum aco_category_op category_match);
 static int xmldoc_update_config_option(struct aco_type **types, const char *module, const char *name, const char *object_name, const char *default_value, unsigned int regex, enum aco_option_type type);
 #endif
 
@@ -373,6 +373,8 @@ static int find_option_cb(void *obj, void *arg, int flags)
 	switch (match->match_type) {
 	case ACO_EXACT:
 		return strcasecmp(name, match->name) ? 0 : CMP_MATCH | CMP_STOP;
+	case ACO_PREFIX:
+		return strncasecmp(name, match->name, strlen(match->name)) ? 0 : CMP_MATCH | CMP_STOP;
 	case ACO_REGEX:
 		return regexec(match->name_regex, name, 0, NULL, 0) ? 0 : CMP_MATCH | CMP_STOP;
 	}
@@ -402,6 +404,45 @@ struct ao2_container *aco_option_container_alloc(void)
 	return ao2_container_alloc(CONFIG_OPT_BUCKETS, config_opt_hash, config_opt_cmp);
 }
 
+static int internal_aco_type_category_check(struct aco_type *match, const char *category)
+{
+	const char **categories = (const char **)match->category;
+
+	switch (match->category_match) {
+	case ACO_WHITELIST:
+		return regexec(match->internal->regex, category, 0, NULL, 0);
+
+	case ACO_BLACKLIST:
+		return !regexec(match->internal->regex, category, 0, NULL, 0);
+
+	case ACO_WHITELIST_EXACT:
+		return strcasecmp(match->category, category);
+
+	case ACO_BLACKLIST_EXACT:
+		return !strcasecmp(match->category, category);
+
+	case ACO_WHITELIST_ARRAY:
+		while (*categories) {
+			if (!strcasecmp(*categories, category)) {
+				return 0;
+			}
+			categories++;
+		}
+		return -1;
+
+	case ACO_BLACKLIST_ARRAY:
+		while (*categories) {
+			if (!strcasecmp(*categories, category)) {
+				return -1;
+			}
+			categories++;
+		}
+		return 0;
+	}
+
+	return -1;
+}
+
 static struct aco_type *internal_aco_type_find(struct aco_file *file, struct ast_config *cfg, const char *category)
 {
 	size_t x;
@@ -410,7 +451,7 @@ static struct aco_type *internal_aco_type_find(struct aco_file *file, struct ast
 
 	for (x = 0, match = file->types[x]; match; match = file->types[++x]) {
 		/* First make sure we are an object that can service this category */
-		if (!regexec(match->internal->regex, category, 0, NULL, 0) == !match->category_match) {
+		if (internal_aco_type_category_check(match, category)) {
 			continue;
 		}
 
@@ -483,6 +524,10 @@ static int process_category(struct ast_config *cfg, struct aco_info *info, struc
 		return -1;
 	}
 
+	if (type->type == ACO_IGNORE) {
+		return 0;
+	}
+
 	field = info->internal->pending + type->item_offset;
 	if (!*field) {
 		ast_log(LOG_ERROR, "In %s: %s - No object to update!\n", file->filename, cat);
@@ -631,6 +676,10 @@ enum aco_process_status aco_process_config(struct aco_info *info, int reload)
 		for (i = 0, match = file->types[i]; match; match = file->types[++i]) {
 			void **field = info->internal->pending + match->item_offset;
 
+			if (match->type == ACO_IGNORE) {
+				continue;
+			}
+
 			if (match->type != ACO_GLOBAL || !*field) {
 				continue;
 			}
@@ -797,9 +846,19 @@ static int internal_type_init(struct aco_type *type)
 		return -1;
 	}
 
-	if (!(type->internal->regex = build_regex(type->category))) {
-		internal_type_destroy(type);
-		return -1;
+	switch (type->category_match) {
+	case ACO_BLACKLIST:
+	case ACO_WHITELIST:
+		if (!(type->internal->regex = build_regex(type->category))) {
+			internal_type_destroy(type);
+			return -1;
+		}
+		break;
+	case ACO_BLACKLIST_EXACT:
+	case ACO_WHITELIST_EXACT:
+	case ACO_BLACKLIST_ARRAY:
+	case ACO_WHITELIST_ARRAY:
+		break;
 	}
 
 	if (!(type->internal->opts = aco_option_container_alloc())) {
@@ -828,7 +887,8 @@ int aco_info_init(struct aco_info *info)
 #ifdef AST_XML_DOCS
 			if (!info->hidden &&
 				!type->hidden &&
-				xmldoc_update_config_type(info->module, type->name, type->category, type->matchfield, type->matchvalue, type->category_match == ACO_WHITELIST)) {
+				type->type != ACO_IGNORE &&
+				xmldoc_update_config_type(info->module, type->name, type->category, type->matchfield, type->matchvalue, type->category_match)) {
 				goto error;
 			}
 #endif /* AST_XML_DOCS */
@@ -989,7 +1049,7 @@ static char *complete_config_option(const char *module, const char *option, cons
 /*! \internal
  * \brief Update the XML documentation for a config type based on its registration
  */
-static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, unsigned int matches)
+static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, enum aco_category_op category_match)
 {
 	RAII_VAR(struct ast_xml_xpath_results *, results, NULL, ast_xml_xpath_results_free);
 	RAII_VAR(struct ast_xml_doc_item *, config_info, ao2_find(xmldocs, module, OBJ_KEY), ao2_cleanup);
@@ -1028,7 +1088,18 @@ static int xmldoc_update_config_type(const char *module, const char *name, const
 	}
 
 	ast_xml_set_text(tmp, category);
-	ast_xml_set_attribute(tmp, "match", matches ? "true" : "false");
+	switch (category_match) {
+	case ACO_WHITELIST:
+	case ACO_WHITELIST_EXACT:
+	case ACO_WHITELIST_ARRAY:
+		ast_xml_set_attribute(tmp, "match", "true");
+		break;
+	case ACO_BLACKLIST:
+	case ACO_BLACKLIST_EXACT:
+	case ACO_BLACKLIST_ARRAY:
+		ast_xml_set_attribute(tmp, "match", "false");
+		break;
+	}
 
 	if (!ast_strlen_zero(matchfield) && !(tmp = ast_xml_new_child(matchinfo, "field"))) {
 		ast_log(LOG_WARNING, "Could not add %s attribute for type '%s' in module '%s'\n", matchfield, name, module);
diff --git a/main/features_config.c b/main/features_config.c
index 72cd0404f7a64d14233fe33bb284c85c3055ced2..a773f497fd5b51fcbbae0a994b1275d95bde41bc 100644
--- a/main/features_config.c
+++ b/main/features_config.c
@@ -219,7 +219,7 @@
 					The <replaceable>DYNAMIC_FEATURES</replaceable> is a <literal>#</literal> separated list of
 					either applicationmap item names or featuregroup names.</para>
 				</description>
-				<configOption name="^.*$" regex="true">
+				<configOption name="">
 					<synopsis>A custom feature to invoke during a bridged call</synopsis>
 					<description>
 						<para>Each item listed here is a comma-separated list of parameters that determine
@@ -272,7 +272,7 @@
 					DTMF sequence used to invoke an applicationmap item to be overridden with
 					a different sequence.</para>
 				</description>
-				<configOption name="^.*$" regex="true">
+				<configOption name="">
 					<synopsis>Applicationmap item to place in the feature group</synopsis>
 					<description>
 						<para>Each item here must be a name of an item in the applicationmap. The
@@ -578,24 +578,24 @@ struct features_config {
 static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "globals",
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 	.item_offset = offsetof(struct features_config, global),
 };
 
 static struct aco_type featuremap_option = {
 	.type = ACO_GLOBAL,
 	.name = "featuremap",
-	.category_match = ACO_WHITELIST,
-	.category = "^featuremap$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "featuremap",
 	.item_offset = offsetof(struct features_config, featuremap),
 };
 
 static struct aco_type applicationmap_option = {
 	.type = ACO_GLOBAL,
 	.name = "applicationmap",
-	.category_match = ACO_WHITELIST,
-	.category = "^applicationmap$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "applicationmap",
 	.item_offset = offsetof(struct features_config, applicationmap),
 };
 
@@ -1851,13 +1851,13 @@ static int load_config(void)
 	aco_option_register_custom(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
 			DEFAULT_FEATUREMAP_AUTOMIXMON, featuremap_handler, 0);
 
-	aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, applicationmap_options,
+	aco_option_register_custom(&cfg_info, "", ACO_PREFIX, applicationmap_options,
 			"", applicationmap_handler, 0);
 
-	aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, featuregroup_options,
+	aco_option_register_custom(&cfg_info, "", ACO_PREFIX, featuregroup_options,
 			"", featuregroup_handler, 0);
 
-	aco_option_register_custom_nodoc(&cfg_info, "^.*$", ACO_REGEX, parkinglot_options,
+	aco_option_register_custom_nodoc(&cfg_info, "", ACO_PREFIX, parkinglot_options,
 			"", unsupported_handler, 0);
 
 	if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
diff --git a/main/named_acl.c b/main/named_acl.c
index 8b5aedabb1b1a0bbb3b44bd2097b79982a6421e2..393532a5351c8fb5a7f0d3209c9b47ca31f052a6 100644
--- a/main/named_acl.c
+++ b/main/named_acl.c
@@ -80,8 +80,8 @@ static void *named_acl_find(struct ao2_container *container, const char *cat);
 static struct aco_type named_acl_type = {
 	.type = ACO_ITEM,                  /*!< named_acls are items stored in containers, not individual global objects */
 	.name = "named_acl",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",           /*!< Match everything but "general" */
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",           /*!< Match everything but "general" */
 	.item_alloc = named_acl_alloc,     /*!< A callback to allocate a new named_acl based on category */
 	.item_find = named_acl_find,       /*!< A callback to find a named_acl in some container of named_acls */
 	.item_offset = offsetof(struct named_acl_config, named_acl_list), /*!< Could leave this out since 0 */
diff --git a/main/stasis.c b/main/stasis.c
index 186d88fddecf53c5034cb9ae1295702153fa2b89..77bf340826e4b74e888ddcb01dd8c58abc589927 100644
--- a/main/stasis.c
+++ b/main/stasis.c
@@ -1434,8 +1434,8 @@ static struct aco_type threadpool_option = {
 	.type = ACO_GLOBAL,
 	.name = "threadpool",
 	.item_offset = offsetof(struct stasis_config, threadpool_options),
-	.category = "^threadpool$",
-	.category_match = ACO_WHITELIST,
+	.category = "threadpool",
+	.category_match = ACO_WHITELIST_EXACT,
 };
 
 static struct aco_type *threadpool_options[] = ACO_TYPES(&threadpool_option);
@@ -1445,8 +1445,8 @@ static struct aco_type declined_option = {
 	.type = ACO_GLOBAL,
 	.name = "declined_message_types",
 	.item_offset = offsetof(struct stasis_config, declined_message_types),
-	.category_match = ACO_WHITELIST,
-	.category = "^declined_message_types$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "declined_message_types",
 };
 
 struct aco_type *declined_options[] = ACO_TYPES(&declined_option);
diff --git a/main/udptl.c b/main/udptl.c
index d982f6bcb0e9d37aef3ba2f7b210f2a31d63c929..5a491e65cd29a5230c907d03a84d913966bce010 100644
--- a/main/udptl.c
+++ b/main/udptl.c
@@ -237,9 +237,9 @@ static int udptl_pre_apply_config(void);
 static struct aco_type general_option = {
 	.type = ACO_GLOBAL,
 	.name = "global",
-	.category_match = ACO_WHITELIST,
+	.category_match = ACO_WHITELIST_EXACT,
 	.item_offset = offsetof(struct udptl_config, general),
-	.category = "^general$",
+	.category = "general",
 };
 
 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
diff --git a/res/ari/config.c b/res/ari/config.c
index a080bb713fea56d4538839ca6ea211d865363afd..46d23c61d1bc60ec83d0bd3f4ab90821aa3fbcd5 100644
--- a/res/ari/config.c
+++ b/res/ari/config.c
@@ -39,8 +39,8 @@ static struct aco_type general_option = {
 	.type = ACO_GLOBAL,
 	.name = "general",
 	.item_offset = offsetof(struct ast_ari_conf, general),
-	.category = "^general$",
-	.category_match = ACO_WHITELIST,
+	.category = "general",
+	.category_match = ACO_WHITELIST_EXACT,
 };
 
 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
@@ -156,8 +156,8 @@ static void *user_find(struct ao2_container *tmp_container, const char *cat)
 static struct aco_type user_option = {
 	.type = ACO_ITEM,
 	.name = "user",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.matchfield = "type",
 	.matchvalue = "user",
 	.item_alloc = user_alloc,
diff --git a/res/res_hep.c b/res/res_hep.c
index ba036d70f6618041045049fce4c18080758dde79..4e548e274f8a6db1f16958e1756cf793b04cb118 100644
--- a/res/res_hep.c
+++ b/res/res_hep.c
@@ -258,8 +258,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "general",
 	.item_offset = offsetof(struct module_config, general),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 struct aco_type *global_options[] = ACO_TYPES(&global_option);
diff --git a/res/res_parking.c b/res/res_parking.c
index 2dbe6f7d5a1bd81335ae180c4f9b79ea895093ab..5d1b30c2305792a04c6e525e923aab6706de35d6 100644
--- a/res/res_parking.c
+++ b/res/res_parking.c
@@ -289,8 +289,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "globals",
 	.item_offset = offsetof(struct parking_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -298,8 +298,8 @@ struct aco_type *global_options[] = ACO_TYPES(&global_option);
 static struct aco_type parking_lot_type = {
 	.type = ACO_ITEM,
 	.name = "parking_lot",
-	.category_match = ACO_BLACKLIST,
-	.category = "^(general)$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.item_alloc = parking_lot_cfg_alloc,
 	.item_find = named_item_find,
 	.item_offset = offsetof(struct parking_config, parking_lots),
diff --git a/res/res_pjsip_notify.c b/res/res_pjsip_notify.c
index 8de88c7e89992a4ca25af5167afd19fdff6530a8..59b7c6ea454849e6c908b6563352a75e9b9b54d7 100644
--- a/res/res_pjsip_notify.c
+++ b/res/res_pjsip_notify.c
@@ -82,7 +82,7 @@
 					order; any other header is treated as part of the SIP
 					request.</para>
 				</description>
-				<configOption name="^.*$">
+				<configOption name="">
 					<synopsis>A key/value pair to add to a NOTIFY request.</synopsis>
 					<description>
 						<para>If the key is <literal>Content</literal>,
@@ -234,8 +234,8 @@ static void *notify_cfg_alloc(void)
 static struct aco_type notify_option = {
 	.type = ACO_ITEM,
 	.name = "notify",
-	.category_match = ACO_BLACKLIST,
-	.category = "^general$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.item_offset = offsetof(struct notify_cfg, notify_options),
 	.item_alloc = notify_option_alloc,
 	.item_find = notify_option_find
@@ -993,7 +993,7 @@ static int load_module(void)
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
-	aco_option_register_custom(&notify_cfg, "^.*$", ACO_REGEX, notify_options,
+	aco_option_register_custom(&notify_cfg, "", ACO_PREFIX, notify_options,
 				   "", notify_option_handler, 0);
 
 	if (aco_process_config(&notify_cfg, 0)) {
diff --git a/res/res_resolver_unbound.c b/res/res_resolver_unbound.c
index 3c78050100e076891cf5e452958963d9f06f8423..25f61509aa6e277cd2902388d72ec5d9aeb92b0d 100644
--- a/res/res_resolver_unbound.c
+++ b/res/res_resolver_unbound.c
@@ -142,8 +142,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "general",
 	.item_offset = offsetof(struct unbound_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
diff --git a/res/res_statsd.c b/res/res_statsd.c
index aee0bcd5a00a97df4525d20a8c25cd1a09f4e7ed..221b359c9e878fce45ea2d3749f3eb6e65d8e19b 100644
--- a/res/res_statsd.c
+++ b/res/res_statsd.c
@@ -231,8 +231,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "global",
 	.item_offset = offsetof(struct conf, global),
-	.category = "^general$",
-	.category_match = ACO_WHITELIST
+	.category = "general",
+	.category_match = ACO_WHITELIST_EXACT,
 };
 
 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
diff --git a/res/res_xmpp.c b/res/res_xmpp.c
index f683557a5a96c7684c839581cc50207f90fd637f..b72581fa5434d46eff7446fe1fa1f0d73fe537f5 100644
--- a/res/res_xmpp.c
+++ b/res/res_xmpp.c
@@ -820,8 +820,8 @@ static struct aco_type global_option = {
 	.type = ACO_GLOBAL,
 	.name = "global",
 	.item_offset = offsetof(struct xmpp_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "general",
 };
 
 struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -829,8 +829,8 @@ struct aco_type *global_options[] = ACO_TYPES(&global_option);
 static struct aco_type client_option = {
 	.type = ACO_ITEM,
 	.name = "client",
-	.category_match = ACO_BLACKLIST,
-	.category = "^(general)$",
+	.category_match = ACO_BLACKLIST_EXACT,
+	.category = "general",
 	.item_alloc = ast_xmpp_client_config_alloc,
 	.item_find = xmpp_config_find,
 	.item_prelink = xmpp_config_prelink,
diff --git a/tests/test_config.c b/tests/test_config.c
index d74726a1a78e71386041c7d0ab63278533bd0f10..de85f23b0c487891b8055daad6cf1a8c836a04c9 100644
--- a/tests/test_config.c
+++ b/tests/test_config.c
@@ -1456,13 +1456,19 @@ static struct aco_type global = {
 static struct aco_type global_defaults = {
 	.type = ACO_GLOBAL,
 	.item_offset = offsetof(struct test_config, global_defaults),
-	.category_match = ACO_WHITELIST,
-	.category = "^global_defaults$",
+	.category_match = ACO_WHITELIST_EXACT,
+	.category = "global_defaults",
+};
+static const char *item_blacklist[] = {
+	"global",
+	"global_defaults",
+	NULL,
 };
+
 static struct aco_type item = {
 	.type = ACO_ITEM,
-	.category_match = ACO_BLACKLIST,
-	.category = "^(global|global_defaults)$",
+	.category_match = ACO_BLACKLIST_ARRAY,
+	.category = (const char *)item_blacklist,
 	.item_alloc = test_item_alloc,
 	.item_find = test_item_find,
 	.item_offset = offsetof(struct test_config, items),