diff --git a/src/util.c b/src/util.c
index efa73ca..8615a9a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1294,6 +1294,61 @@ cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
        'p' then points to static string ".".  So caller needs to ensure there
        are at least two bytes available in 'name' buffer so memmove succeeds. */
     memmove (name, p, (size_t)(strlen (p) + 1));
+
+  if (!absolute_names)
+    {
+      /* safer_name_suffix() strips only leading "../" sequences.  A name
+         like "sub/../../evil" would still escape the current directory if
+         the leading "sub/" exists, defeating --no-absolute-filenames.
+         Collapse any remaining "xxx/../" sequences so the result cannot
+         name a file outside the current directory.  E.g. "sub/../../evil"
+         becomes "evil".  */
+      char *q;
+      while ((q = strstr (name, "/../")) != NULL)
+        {
+          char *s = q;
+          while (s > name && s[-1] != '/')
+            --s;
+          /* Delete the preceding component together with the "/../".  */
+          memmove (s, q + 4, strlen (q + 4) + 1);
+        }
+
+      /* A trailing "/.." (e.g. "sub/..") is not matched above.  */
+      {
+        size_t len = strlen (name);
+        while (len > 3 && strcmp (name + len - 3, "/..") == 0)
+          {
+            name[len - 3] = '\0';
+            char *s = strrchr (name, '/');
+            if (s == NULL)
+              name[0] = '\0';
+            else
+              *s = '\0';
+            len = strlen (name);
+          }
+      }
+
+      /* Collapsing may have exposed new leading "../" sequences
+         (e.g. "sub/../../evil" first collapses to "../evil").  Strip
+         them the same way safer_name_suffix() does.  */
+      while (name[0] == '.' && name[1] == '.'
+             && (name[2] == '/' || name[2] == '\0'))
+        {
+          if (name[2] == '\0')
+            break;
+          memmove (name, name + 3, strlen (name + 3) + 1);
+        }
+      if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
+        {
+          name[0] = '.';
+          name[1] = '\0';
+        }
+      else if (name[0] == '\0')
+        {
+          name[0] = '.';
+          name[1] = '\0';
+        }
+    }
 }
 
 
