diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 0fff4b140177b2bd9f46993490e2ac99dcfdedc4..2627e0977e0133efa1eca46c4170d177b4a9bef4 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -12770,8 +12770,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 			struct ast_variable *v, *tmpvar;
 			for (v = conf->chan.vars ; v ; v = v->next) {
 				if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
-					tmpvar->next = tmp->vars;
-					tmp->vars = tmpvar;
+					if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
+						tmpvar->next = tmp->vars;
+						tmp->vars = tmpvar;
+					}
 				}
 			}
 		}
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index add593d9b2a03ed09f9c7992f0ffb7a048489f4c..db4bef31bfa1059b0281ebbd5360a98ed3ca40d1 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -7916,9 +7916,11 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
 		/* We found our match (use the first) */
 		/* copy vars */
 		for (v = user->vars ; v ; v = v->next) {
-			if((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
-				tmpvar->next = iaxs[callno]->vars;
-				iaxs[callno]->vars = tmpvar;
+			if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
+				if (ast_variable_list_replace(&iaxs[callno]->vars, tmpvar)) {
+					tmpvar->next = iaxs[callno]->vars;
+					iaxs[callno]->vars = tmpvar;
+				}
 			}
 		}
 		/* If a max AUTHREQ restriction is in place, activate it */
@@ -13179,9 +13181,11 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
 				if ((varval = strchr(varname, '='))) {
 					*varval = '\0';
 					varval++;
-					if((tmpvar = ast_variable_new(varname, varval, ""))) {
-						tmpvar->next = user->vars;
-						user->vars = tmpvar;
+					if ((tmpvar = ast_variable_new(varname, varval, ""))) {
+						if (ast_variable_list_replace(&user->vars, tmpvar)) {
+							tmpvar->next = user->vars;
+							user->vars = tmpvar;
+						}
 					}
 				}
 			} else if (!strcasecmp(v->name, "allow")) {
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 9f01b515fd728214766454877ab368cffdd253e1..80040aee42172955d8cedb8c2c820b39708e433f 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -31366,8 +31366,10 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
 	if ((varval = strchr(varname, '='))) {
 		*varval++ = '\0';
 		if ((tmpvar = ast_variable_new(varname, varval, ""))) {
-			tmpvar->next = list;
-			list = tmpvar;
+			if (ast_variable_list_replace(&list, tmpvar)) {
+				tmpvar->next = list;
+				list = tmpvar;
+			}
 		}
 	}
 	return list;
diff --git a/include/asterisk/config.h b/include/asterisk/config.h
index 9908b905beabdb6c8e8a34f7818b95d68c036cd1..1775dfe53ccd5b7b34305809ed8198b0d8fbe515 100644
--- a/include/asterisk/config.h
+++ b/include/asterisk/config.h
@@ -948,6 +948,24 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s
 	struct ast_variable *new_var);
 #define ast_variable_list_append(head, new_var) ast_variable_list_append_hint(head, NULL, new_var)
 
+/*!
+ * \brief Replace a variable in the given list with a new value
+ * \since 13.30.0
+ *
+ * \param head A pointer to an ast_variable * of the existing variable list head. May NOT be NULL
+ * but the content may be to initialize a new list.  If so, upon return, this parameter will be updated
+ * with a pointer to the new list head.
+ * \param replacement The variable that replaces another variable in the list with the
+ * same name.
+ *
+ * \retval 0 if a variable was replaced in the list
+ * \retval -1 if no replacement occured
+ *
+ * \note The variable name comparison is performed case-sensitively
+ * \note If a variable is replaced, its memory is freed.
+ */
+int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement);
+
 /*!
  * \brief Update variable value within a config
  *
diff --git a/main/config.c b/main/config.c
index 5660fbe963e39f785bf75b1093faebfc0220ffba..002ae2fc9966546515946cff2ac8e378017a4373 100644
--- a/main/config.c
+++ b/main/config.c
@@ -665,6 +665,22 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s
 	return curr;
 }
 
+int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
+{
+	struct ast_variable *v, **prev = head;
+
+	for (v = *head; v; prev = &v->next, v = v->next) {
+		if (!strcmp(v->name, replacement->name)) {
+			replacement->next = v->next;
+			*prev = replacement;
+			ast_free(v);
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
 const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
 {
 	const char *tmp;
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 050073b80a36dacd99355ada2b8ca1f9e2f3a3e7..355b5957dba9c8bde4c1126ccbbdc3209be04c1b 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1044,7 +1044,9 @@ static int set_var_handler(const struct aco_option *opt,
 		return -1;
 	}
 
-	ast_variable_list_append(&endpoint->channel_vars, new_var);
+	if (ast_variable_list_replace(&endpoint->channel_vars, new_var)) {
+		ast_variable_list_append(&endpoint->channel_vars, new_var);
+	}
 
 	return 0;
 }