diff --git a/lfs/bash b/lfs/bash
index dbee213c2..245aaa791 100644
--- a/lfs/bash
+++ b/lfs/bash
@@ -25,7 +25,7 @@
 include Config
 
 VER        = 5.3
-PATCHVER   = 15
+PATCHVER   = 20
 
 THISAPP    = bash-$(VER)
 DL_FILE    = $(THISAPP).tar.gz
diff --git a/src/patches/bash/bash53-016 b/src/patches/bash/bash53-016
new file mode 100644
index 000000000..6aff3244c
--- /dev/null
+++ b/src/patches/bash/bash53-016
@@ -0,0 +1,136 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	5.3
+Patch-ID:	bash53-016
+
+Bug-Reported-by:	Ethan Pini <ethan@pini.dev>
+Bug-Reference-ID:	<sm8ZxfcmgU7_eiVLIsjNlax7oyAwwe1_uk2vaO0hp6nypbGnV7WStfE3rrHg_RV8BMSNRhhQmS2-7TpvzPxuK1NLLEWAyL9kbsZ2cA3nqIg=@pini.dev>
+Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2026-06/msg00126.html
+
+Bug-Description:
+
+On recent versions of macOS, the pipe size is dynamic and changes due to
+system-wide total pipe usage, so we have to check whether or not bash can
+use the size determined at compile time.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-5.3-patched/redir.c	Fri Mar  7 18:49:37 2025
+--- redir.c	Tue Jul  7 11:21:09 2026
+***************
+*** 473,477 ****
+--- 473,500 ----
+  #endif
+  
++ #if defined (PIPESIZE_DYNAMIC)
++       /* If we can't count on the pipe size determined at compile time to be
++ 	 constant across systems, define PIPESIZE_DYNAMIC in configure.ac.
++ 	 We set the pipe's write end to be non-blocking, try to write, and
++ 	 fall back to a temp file on error. */
++       if (sh_setnodelay (herepipe[1]) < 0)
++ 	{
++ 	  close (herepipe[0]);
++ 	  close (herepipe[1]);
++ 	  goto use_tempfile;
++ 	}
++ #endif
++       
+        r = heredoc_write (herepipe[1], document, document_len);
++ 
++ #if defined (PIPESIZE_DYNAMIC)
++       if (r == ENOSPC || r == EAGAIN)
++ 	{
++ 	  close (herepipe[0]);
++ 	  close (herepipe[1]);
++ 	  goto use_tempfile;
++ 	}
++ #endif
++ 	  
+        if (document != redirectee->word)
+  	free (document);
+*** ../bash-5.3-patched/general.c	Wed Jun 25 15:54:35 2025
+--- general.c	Tue Jul  7 11:12:10 2026
+***************
+*** 596,599 ****
+--- 596,620 ----
+  }
+  
++ int
++ sh_setnodelay (int fd)
++ {
++   int flags;
++ 
++   if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
++     return -1;
++ 
++   /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
++      and O_NDELAY is defined. */
++ #ifdef O_NONBLOCK
++   flags |= O_NONBLOCK;
++ #endif
++ 
++ #ifdef O_NDELAY
++   flags |= O_NDELAY;
++ #endif
++ 
++   return (fcntl (fd, F_SETFL, flags));
++ }
++ 
+  /* Just a wrapper for the define in include/filecntl.h */
+  int
+*** ../bash-5.3-patched/general.h	Wed Jun 25 15:52:47 2025
+--- general.h	Tue Jul  7 11:13:48 2026
+***************
+*** 318,321 ****
+--- 318,322 ----
+  
+  extern int sh_unset_nodelay_mode (int);
++ extern int sh_setnodelay (int);
+  extern int sh_setclexec (int);
+  extern int sh_validfd (int);
+*** ../bash-5.3-patched/configure.ac	Mon Jun 30 10:05:24 2025
+--- configure.ac	Tue Jul  7 11:25:32 2026
+***************
+*** 1210,1214 ****
+  isc*)		LOCAL_CFLAGS=-Disc386 ;;
+  rhapsody*)	LOCAL_CFLAGS=-DRHAPSODY ;;
+! darwin*)	LOCAL_CFLAGS=-DMACOSX ;;
+  sco3.2v5*)	LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+  sco3.2v4*)	LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
+--- 1210,1214 ----
+  isc*)		LOCAL_CFLAGS=-Disc386 ;;
+  rhapsody*)	LOCAL_CFLAGS=-DRHAPSODY ;;
+! darwin*)	LOCAL_CFLAGS="-DMACOSX -DPIPESIZE_DYNAMIC" ;;
+  sco3.2v5*)	LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+  sco3.2v4*)	LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
+*** ../bash-5.3-patched/configure	Mon Jun 30 10:05:30 2025
+--- configure	Tue Jul  7 11:25:36 2026
+***************
+*** 23134,23138 ****
+  isc*)		LOCAL_CFLAGS=-Disc386 ;;
+  rhapsody*)	LOCAL_CFLAGS=-DRHAPSODY ;;
+! darwin*)	LOCAL_CFLAGS=-DMACOSX ;;
+  sco3.2v5*)	LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+  sco3.2v4*)	LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
+--- 23134,23138 ----
+  isc*)		LOCAL_CFLAGS=-Disc386 ;;
+  rhapsody*)	LOCAL_CFLAGS=-DRHAPSODY ;;
+! darwin*)	LOCAL_CFLAGS="-DMACOSX -DPIPESIZE_DYNAMIC" ;;
+  sco3.2v5*)	LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+  sco3.2v4*)	LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
+*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
+--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 15
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/src/patches/bash/bash53-017 b/src/patches/bash/bash53-017
new file mode 100644
index 000000000..68617967e
--- /dev/null
+++ b/src/patches/bash/bash53-017
@@ -0,0 +1,62 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	5.3
+Patch-ID:	bash53-017
+
+Bug-Reported-by:	Lennart Ackermans <lennart@ackermans.ch>
+Bug-Reference-ID:	<d6f36c30-633a-4e5e-8212-806db6441bf1@ackermans.ch>
+Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2026-05/msg00066.html
+
+Bug-Description:
+
+If readline is invoked with the cursor somewhere other than column 0, and
+the prompt contains multibyte characters, the display algorithm needs to
+use a buffer offset, instead of the physical prompt length, to determine
+whether or not to reprint the prompt from column 0 because the cursor is
+before the last invisible character in the prompt string.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-5.3-patched/lib/readline/display.c	Thu Sep  4 11:55:37 2025
+--- lib/readline/display.c	Fri May 22 14:55:01 2026
+***************
+*** 1498,1502 ****
+  	     only need to reprint it if the cursor is before the last
+  	     invisible character in the prompt string. */
+- 	  /* XXX - why not use local_prompt_len? */
+  	  nleft = prompt_visible_length + wrap_offset;
+  	  if (cursor_linenum == prompt_last_screen_line)
+--- 1498,1501 ----
+***************
+*** 1510,1518 ****
+  	         buffer position, an index into curline
+  	         (local_prompt + pmt_offset) */
+! 	      cursor_bufpos = pmt_offset;
+! 	      if (mb_cur_max == 1 || rl_byte_oriented)
+! 		cursor_bufpos += _rl_last_c_pos;
+! 	      else
+! 		cursor_bufpos += _rl_last_c_pos + curline_invchars;
+  
+  	      if (local_prompt && local_prompt_invis_chars[cursor_linenum] &&
+--- 1509,1513 ----
+  	         buffer position, an index into curline
+  	         (local_prompt + pmt_offset) */
+! 	      cursor_bufpos = pmt_offset + local_prompt_len;
+  
+  	      if (local_prompt && local_prompt_invis_chars[cursor_linenum] &&
+*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
+--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 17
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/src/patches/bash/bash53-018 b/src/patches/bash/bash53-018
new file mode 100644
index 000000000..070e60d64
--- /dev/null
+++ b/src/patches/bash/bash53-018
@@ -0,0 +1,71 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	5.3
+Patch-ID:	bash53-018
+
+Bug-Reported-by:	Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
+			Derek Schrock <dereks@lifeofadishwasher.com>
+Bug-Reference-ID:	<CAB6pCSaUPimkEbQwTTkxD5vV14ZJRGCeK2W1ur8RqT1rPrd+Gw@mail.gmail.com>
+			<ajC1pZAV_95J3vsJ@ircbsd.lifeofadishwasher.com>
+Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-readline/2026-06/msg00005.html
+			https://lists.gnu.org/archive/html/bug-readline/2026-06/msg00002.html
+
+Bug-Description:
+
+Patch (apply with `patch -p0'):
+
+This patch fixes two problems with the redisplay code. The first is a
+crash that results if the initial prompt contains more than 256 wrapped
+lines. The second is a fix to the redisplay code when the first several
+characters of the prompt string are identical, but the prompt has changed
+and needs to be redrawn. If these first few characters are part of an escape
+sequence, the entire sequence needs to be redrawn.
+
+*** ../bash-5.3-patched/lib/readline/display.c	Fri May 22 14:55:01 2026
+--- lib/readline/display.c	Fri Jun 26 11:08:53 2026
+***************
+*** 1025,1028 ****
+--- 1025,1029 ----
+  	{
+  	  temp = local_prompt_newlines[newlines+1];
++ 	  CHECK_INV_LBREAKS ();
+  	  inv_lbreaks[++newlines] = temp;
+  	}  
+***************
+*** 2262,2270 ****
+    nd = nfd - new;	/* nd, od are buffer indexes */
+    if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+!       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
+        (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
+  		((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
+      {
+!       _rl_cr ();
+        if (modmark)
+  	_rl_output_some_chars ("*", 1);
+--- 2266,2275 ----
+    nd = nfd - new;	/* nd, od are buffer indexes */
+    if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+!       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos >= 0 &&
+        (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
+  		((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
+      {
+!       if (_rl_last_c_pos > 0)
+! 	_rl_cr ();
+        if (modmark)
+  	_rl_output_some_chars ("*", 1);
+*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
+--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 17
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 18
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/src/patches/bash/bash53-019 b/src/patches/bash/bash53-019
new file mode 100644
index 000000000..e70e5e995
--- /dev/null
+++ b/src/patches/bash/bash53-019
@@ -0,0 +1,133 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	5.3
+Patch-ID:	bash53-019
+
+Bug-Reported-by:	zheng <charname@qq.com>
+Bug-Reference-ID:	<tencent_19D6EE3366FEA3EF2C5FD6C23DF303156D09@qq.com>
+Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2026-08/msg00010.html
+
+Bug-Description:
+
+On some systems, macOS in particular, isalpha(3) returns true for bytes
+between 128 and 255. Bash uses this to determine whether or not these
+characters are permitted to be part of a shell identifier, and can
+consume one byte too many when determining the end of a variable name.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-5.3-patched/syntax.h	Mon Sep 14 10:20:05 2020
+--- syntax.h	Thu Aug  6 14:11:25 2026
+***************
+*** 64,67 ****
+--- 64,69 ----
+  #define CSUBSTOP	0x1000	/* values of OP for ${word[:]OPstuff} */
+  #define CBLANK		0x2000	/* whitespace (blank) character */
++ #define CNAME		0x4000	/* POSIX name character ([_0-9a-zA-Z]) */
++ #define CNAMESTART	0x8000	/* POSIX name start character ([_a-zA-Z]) */
+  
+  /* Defines for use by the rest of the shell. */
+*** ../bash-5.3-patched/mksyntax.c	Thu May 16 15:35:55 2024
+--- mksyntax.c	Wed Aug  5 15:27:45 2026
+***************
+*** 61,64 ****
+--- 61,66 ----
+  	{ CSUBSTOP,	"CSUBSTOP" },
+  	{ CBLANK,	"CBLANK" },
++ 	{ CNAME,	"CNAME" },
++ 	{ CNAMESTART,	"CNAMESTART" }
+  };
+  	
+***************
+*** 199,202 ****
+--- 201,243 ----
+  }
+  
++ static void
++ setnamechars(void)
++ {
++   lsyntax['_'] |= CNAME|CNAMESTART;
++ 
++   lsyntax['0'] |= CNAME; lsyntax['1'] |= CNAME; lsyntax['2'] |= CNAME;
++   lsyntax['3'] |= CNAME; lsyntax['4'] |= CNAME; lsyntax['5'] |= CNAME;
++   lsyntax['6'] |= CNAME; lsyntax['7'] |= CNAME; lsyntax['8'] |= CNAME;
++   lsyntax['9'] |= CNAME;
++ 
++   lsyntax['a'] |= CNAME|CNAMESTART; lsyntax['b'] |= CNAME|CNAMESTART;
++   lsyntax['c'] |= CNAME|CNAMESTART; lsyntax['d'] |= CNAME|CNAMESTART;
++   lsyntax['e'] |= CNAME|CNAMESTART; lsyntax['f'] |= CNAME|CNAMESTART;
++   lsyntax['g'] |= CNAME|CNAMESTART; lsyntax['h'] |= CNAME|CNAMESTART;
++   lsyntax['i'] |= CNAME|CNAMESTART; lsyntax['j'] |= CNAME|CNAMESTART;
++   lsyntax['k'] |= CNAME|CNAMESTART; lsyntax['l'] |= CNAME|CNAMESTART;
++   lsyntax['m'] |= CNAME|CNAMESTART; lsyntax['n'] |= CNAME|CNAMESTART;
++   lsyntax['o'] |= CNAME|CNAMESTART; lsyntax['p'] |= CNAME|CNAMESTART;
++   lsyntax['q'] |= CNAME|CNAMESTART; lsyntax['r'] |= CNAME|CNAMESTART;
++   lsyntax['s'] |= CNAME|CNAMESTART; lsyntax['t'] |= CNAME|CNAMESTART;
++   lsyntax['u'] |= CNAME|CNAMESTART; lsyntax['v'] |= CNAME|CNAMESTART;
++   lsyntax['w'] |= CNAME|CNAMESTART; lsyntax['x'] |= CNAME|CNAMESTART;
++   lsyntax['y'] |= CNAME|CNAMESTART; lsyntax['z'] |= CNAME|CNAMESTART;
++ 
++   lsyntax['A'] |= CNAME|CNAMESTART; lsyntax['B'] |= CNAME|CNAMESTART;
++   lsyntax['C'] |= CNAME|CNAMESTART; lsyntax['D'] |= CNAME|CNAMESTART;
++   lsyntax['E'] |= CNAME|CNAMESTART; lsyntax['F'] |= CNAME|CNAMESTART;
++   lsyntax['G'] |= CNAME|CNAMESTART; lsyntax['H'] |= CNAME|CNAMESTART;
++   lsyntax['I'] |= CNAME|CNAMESTART; lsyntax['J'] |= CNAME|CNAMESTART;
++   lsyntax['K'] |= CNAME|CNAMESTART; lsyntax['L'] |= CNAME|CNAMESTART;
++   lsyntax['M'] |= CNAME|CNAMESTART; lsyntax['N'] |= CNAME|CNAMESTART;
++   lsyntax['O'] |= CNAME|CNAMESTART; lsyntax['P'] |= CNAME|CNAMESTART;
++   lsyntax['Q'] |= CNAME|CNAMESTART; lsyntax['R'] |= CNAME|CNAMESTART;
++   lsyntax['S'] |= CNAME|CNAMESTART; lsyntax['T'] |= CNAME|CNAMESTART;
++   lsyntax['U'] |= CNAME|CNAMESTART; lsyntax['V'] |= CNAME|CNAMESTART;
++   lsyntax['W'] |= CNAME|CNAMESTART; lsyntax['X'] |= CNAME|CNAMESTART;
++   lsyntax['Y'] |= CNAME|CNAMESTART; lsyntax['Z'] |= CNAME|CNAMESTART;
++ }
++ 
+  /* load up the correct flag values in lsyntax */
+  static void
+***************
+*** 235,238 ****
+--- 276,281 ----
+  
+    addblanks ();
++ 
++   setnamechars ();
+  }
+  
+*** ../bash-5.3-patched/general.h	Tue Jul  7 11:13:48 2026
+--- general.h	Thu Aug  6 14:07:22 2026
+***************
+*** 111,116 ****
+  
+  /* Define exactly what a legal shell identifier consists of. */
+! #define legal_variable_starter(c) (ISALPHA(c) || (c == '_'))
+! #define legal_variable_char(c)	(ISALNUM(c) || c == '_')
+  
+  /* Definitions used in subst.c and by the `read' builtin for field
+--- 111,121 ----
+  
+  /* Define exactly what a legal shell identifier consists of. */
+! #if 0
+! #define legal_variable_starter(c) (c < 128 && (ISALPHA(c) || c == '_'))
+! #define legal_variable_char(c)	(c < 128 && (ISALNUM(c) || c == '_'))
+! #else
+! #define legal_variable_starter(c) (sh_syntaxtab[c] & CNAMESTART)
+! #define legal_variable_char(c)	(sh_syntaxtab[c] & CNAME)
+! #endif
+  
+  /* Definitions used in subst.c and by the `read' builtin for field
+*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
+--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 18
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 19
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/src/patches/bash/bash53-020 b/src/patches/bash/bash53-020
new file mode 100644
index 000000000..1e27d19bd
--- /dev/null
+++ b/src/patches/bash/bash53-020
@@ -0,0 +1,51 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	5.3
+Patch-ID:	bash53-020
+
+Bug-Reported-by:	Félix Bouynot <felix.bouynot@setenforce.one>
+Bug-Reference-ID:	<39c9472ddcf23881693380c4b895dd3799b45cec.camel@setenforce.one>
+Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2026-05/msg00065.html
+
+Bug-Description:
+
+If readline handles a SIGWINCH and resizes its idea of the screen
+dimensions, it needs to recompute the columns where the prompt wraps
+lines every time, not just when the screen width decreases.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-5.3-patched/lib/readline/display.c	Thu Sep  4 11:55:37 2025
+--- lib/readline/display.c	Fri May 22 14:55:01 2026
+***************
+*** 3526,3531 ****
+      rl_crlf ();
+  
+!   if (_rl_screenwidth < prompt_visible_length)
+!     _rl_reset_prompt ();		/* update local_prompt_newlines array */
+  
+    /* Redraw only the last line of a multi-line prompt. */
+--- 3521,3527 ----
+      rl_crlf ();
+  
+!   /* Let expand_prompt() update local_prompt_newlines and local_prompt_invis_chars
+!     arrays */
+!   _rl_reset_prompt ();
+  
+    /* Redraw only the last line of a multi-line prompt. */
+*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
+--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 19
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 20
+  
+  #endif /* _PATCHLEVEL_H_ */
