Common Weakness Enumeration

CWE-552

Allowed

Files or Directories Accessible to External Parties

Abstraction: Base · Status: Draft

The product makes files or directories accessible to unauthorized actors, even though they should not be.

750 vulnerabilities reference this CWE, most recent first.

GHSA-FM6M-FMH2-F72V

Vulnerability from github – Published: 2024-06-12 12:30 – Updated: 2024-06-12 12:30
VLAI
Details

CWE-552: Files or Directories Accessible to External Parties vulnerability exists which may prevent user to update the device firmware and prevent proper behavior of the webserver when specific files or directories are removed from the filesystem.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-5056"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-06-12T12:15:10Z",
    "severity": "MODERATE"
  },
  "details": "CWE-552: Files or Directories Accessible to External Parties vulnerability exists which may\nprevent user to update the device firmware and prevent proper behavior of the webserver when\nspecific files or directories are removed from the filesystem.",
  "id": "GHSA-fm6m-fmh2-f72v",
  "modified": "2024-06-12T12:30:41Z",
  "published": "2024-06-12T12:30:41Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-5056"
    },
    {
      "type": "WEB",
      "url": "https://download.schneider-electric.com/files?p_Doc_Ref=SEVD-2024-163-01\u0026p_enDocType=Security+and+Safety+Notice\u0026p_File_Name=SEVD-2024-163-01.pdf"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FP63-499M-HQ6M

Vulnerability from github – Published: 2021-07-12 16:53 – Updated: 2021-07-09 14:04
VLAI
Summary
Files or Directories Accessible to External Parties in ether/logs
Details

Impact

A vulnerability was found that allowed authenticated admin users to access any file on the server.

Patches

The vulnerability has been fixed in 3.0.4.

Workarounds

We recommend disabling the plugin if untrustworthy sources have admin access.

For more information

If you have any questions or comments about this advisory: * Open an issue in ether/logs

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "ether/logs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.0.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2021-32752"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-07-09T14:04:21Z",
    "nvd_published_at": "2021-07-09T14:15:00Z",
    "severity": "HIGH"
  },
  "details": "### Impact\nA vulnerability was found that allowed authenticated admin users to access any file on the server.\n\n### Patches\nThe vulnerability has been fixed in 3.0.4.\n\n### Workarounds\nWe recommend disabling the plugin if untrustworthy sources have admin access.\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [ether/logs](https://github.com/ethercreative/logs/issues)\n",
  "id": "GHSA-fp63-499m-hq6m",
  "modified": "2021-07-09T14:04:21Z",
  "published": "2021-07-12T16:53:00Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ethercreative/logs/security/advisories/GHSA-fp63-499m-hq6m"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32752"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ethercreative/logs/commit/eb225cc78b1123a10ce2784790f232d71c2066c4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ethercreative/logs/releases/tag/3.0.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Files or Directories Accessible to External Parties in ether/logs"
}

GHSA-FPVG-M786-H5VR

Vulnerability from github – Published: 2023-06-13 18:30 – Updated: 2023-06-26 20:55
VLAI
Summary
Dolibarr vulnerable to unauthenticated database access
Details

An issue in Dolibarr v16.0.0 to v16.0.5 allows unauthenticated attackers to perform a database dump and access a company's entire customer file, prospects, suppliers, and employee information if a contact file exists.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "dolibarr/dolibarr"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "16.0.0"
            },
            {
              "fixed": "16.0.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2023-33568"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-552"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2023-06-14T16:23:01Z",
    "nvd_published_at": "2023-06-13T15:15:14Z",
    "severity": "HIGH"
  },
  "details": "An issue in Dolibarr v16.0.0 to v16.0.5 allows unauthenticated attackers to perform a database dump and access a company\u0027s entire customer file, prospects, suppliers, and employee information if a contact file exists.",
  "id": "GHSA-fpvg-m786-h5vr",
  "modified": "2023-06-26T20:55:12Z",
  "published": "2023-06-13T18:30:39Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-33568"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Dolibarr/dolibarr/commit/bb7b69ef43673ed403436eac05e0bc31d5033ff7"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Dolibarr/dolibarr/commit/be82f51f68d738cce205f4ce5b469ef42ed82d9e"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Dolibarr/dolibarr"
    },
    {
      "type": "WEB",
      "url": "https://www.dolibarr.org/forum/t/dolibarr-16-0-security-breach/23471"
    },
    {
      "type": "WEB",
      "url": "https://www.dolibarr.org/forum/t/dolibarr-16-0-security-breach/23471/1"
    },
    {
      "type": "WEB",
      "url": "https://www.dsecbypass.com/en/dolibarr-pre-auth-contact-database-dump"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dolibarr vulnerable to unauthenticated database access"
}

GHSA-FQPQ-36Q8-XC95

Vulnerability from github – Published: 2022-12-19 15:30 – Updated: 2022-12-23 15:30
VLAI
Details

The Wholesale Market for WooCommerce WordPress plugin before 1.0.8 does not validate user input used to generate system path, allowing high privilege users such as admin to download arbitrary file from the server even when they should not be able to (for example in multisite)

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-4108"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-12-19T14:15:00Z",
    "severity": "MODERATE"
  },
  "details": "The Wholesale Market for WooCommerce WordPress plugin before 1.0.8 does not validate user input used to generate system path, allowing high privilege users such as admin to download arbitrary file from the server even when they should not be able to (for example in multisite)",
  "id": "GHSA-fqpq-36q8-xc95",
  "modified": "2022-12-23T15:30:24Z",
  "published": "2022-12-19T15:30:29Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-4108"
    },
    {
      "type": "WEB",
      "url": "https://wpscan.com/vulnerability/9d1770df-91f0-41e3-af0d-522ae4e62470"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FRC9-5H6P-F7F3

Vulnerability from github – Published: 2022-05-13 01:38 – Updated: 2022-05-13 01:38
VLAI
Details

Files or directories accessible to external parties vulnerability in picasa.php in Synology Photo Station before 6.8.1-3458 and before 6.3-2970 allows remote attackers to obtain arbitrary files via prog_id field.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-12079"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-12-04T19:29:00Z",
    "severity": "HIGH"
  },
  "details": "Files or directories accessible to external parties vulnerability in picasa.php in Synology Photo Station before 6.8.1-3458 and before 6.3-2970 allows remote attackers to obtain arbitrary files via prog_id field.",
  "id": "GHSA-frc9-5h6p-f7f3",
  "modified": "2022-05-13T01:38:15Z",
  "published": "2022-05-13T01:38:15Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-12079"
    },
    {
      "type": "WEB",
      "url": "https://www.synology.com/en-global/support/security/Synology_SA_17_63_Photo_Station"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FRR3-HPW2-J7CQ

Vulnerability from github – Published: 2026-04-10 12:31 – Updated: 2026-04-10 12:31
VLAI
Details

A files or directories accessible to external parties vulnerability in Synology SSL VPN Client before 1.4.5-0684 allows remote attackers to access files within the installation directory via a local HTTP server bound to the loopback interface. By leveraging user interaction with a crafted web page, attackers may retrieve sensitive files such as configuration files, certificates, and logs, leading to information disclosure.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-47960"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-10T10:16:02Z",
    "severity": "MODERATE"
  },
  "details": "A files or directories accessible to external parties vulnerability in Synology SSL VPN Client before 1.4.5-0684 allows remote attackers to access files within the installation directory via a local HTTP server bound to the loopback interface. By leveraging user interaction with a crafted web page, attackers may retrieve sensitive files such as configuration files, certificates, and logs, leading to information disclosure.",
  "id": "GHSA-frr3-hpw2-j7cq",
  "modified": "2026-04-10T12:31:44Z",
  "published": "2026-04-10T12:31:44Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-47960"
    },
    {
      "type": "WEB",
      "url": "https://www.synology.com/en-global/security/advisory/Synology_SA_26_05"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FW23-X6WC-FGHC

Vulnerability from github – Published: 2023-06-29 03:30 – Updated: 2024-04-04 05:17
VLAI
Details

A Directory Browsing vulnerability in MCL-Net version 4.3.5.8788 webserver running on default port 5080, allows attackers to gain sensitive information about the configured databases via the "/file" endpoint.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-34834"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-06-29T03:15:09Z",
    "severity": "MODERATE"
  },
  "details": "A Directory Browsing vulnerability in MCL-Net version 4.3.5.8788 webserver running on default port 5080, allows attackers to gain sensitive information about the configured databases via the \"/file\" endpoint.",
  "id": "GHSA-fw23-x6wc-fghc",
  "modified": "2024-04-04T05:17:11Z",
  "published": "2023-06-29T03:30:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-34834"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/51542"
    },
    {
      "type": "WEB",
      "url": "http://www.mclv4.mcl-collection.com/index.php"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FX8P-8GCH-GJP7

Vulnerability from github – Published: 2022-01-11 00:00 – Updated: 2022-01-15 00:03
VLAI
Details

Implicit Intent hijacking vulnerability in ActivityMetricsLogger prior to SMR Jan-2022 Release 1 allows attackers to get running application information.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-22267"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-01-10T14:12:00Z",
    "severity": "LOW"
  },
  "details": "Implicit Intent hijacking vulnerability in ActivityMetricsLogger prior to SMR Jan-2022 Release 1 allows attackers to get running application information.",
  "id": "GHSA-fx8p-8gch-gjp7",
  "modified": "2022-01-15T00:03:22Z",
  "published": "2022-01-11T00:00:56Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-22267"
    },
    {
      "type": "WEB",
      "url": "https://security.samsungmobile.com/securityUpdate.smsb?year=2022\u0026month=1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-FXC4-GGQH-5WG4

Vulnerability from github – Published: 2022-05-24 19:03 – Updated: 2022-08-06 00:00
VLAI
Details

It has been discovered that redhat-certification does not restrict file access in the /update/results page. A remote attacker could use this vulnerability to remove any file accessible by the user which is running httpd. This flaw affects redhat-certification version 7.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-10867"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-552"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-05-26T19:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "It has been discovered that redhat-certification does not restrict file access in the /update/results page. A remote attacker could use this vulnerability to remove any file accessible by the user which is running httpd. This flaw affects redhat-certification version 7.",
  "id": "GHSA-fxc4-ggqh-5wg4",
  "modified": "2022-08-06T00:00:44Z",
  "published": "2022-05-24T19:03:19Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-10867"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2018-10867"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1593764"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-G29J-RWFV-H99W

Vulnerability from github – Published: 2026-09-02 22:12 – Updated: 2026-09-02 22:12
VLAI
Summary
Handlebars.java: Arbitrary file read in `SpringTemplateLoader` via URL-fragment suffix bypass
Details

Summary

com.github.jknack.handlebars.springmvc.SpringTemplateLoader resolves Spring MVC view names into URLs via Spring's ResourceLoader without applying the path-containment check that protects every other URL-based loader in the project (ClassPathTemplateLoader, FileTemplateLoader, ServletContextTemplateLoader - all hardened by commit d177cdee).

The only remaining defense for file: / classpath: view names is the unconditional .hbs suffix appended by AbstractTemplateLoader.resolve(...). This suffix is the load-bearing security boundary that prevents a request like view=file:/etc/passwd from reading /etc/passwd instead of /etc/passwd.hbs.

This boundary is bypassed by a single character: # (the URL fragment delimiter).

When the view name ends with #, the appended .hbs lands inside the URL fragment. Both Spring's FileUrlResource.exists() (via URI.getSchemeSpecificPart()) and the JDK's URL.openStream() (via URL.getFile()) silently discard the fragment, so the file actually opened is the bare path the attacker specified - for example /etc/passwd rather than /etc/passwd.hbs. The compiled "template" is then parsed and rendered into the HTTP response body.

Result: unauthenticated, network-reachable, arbitrary file read of any file readable by the JVM process on any Spring MVC application that uses a default-configured HandlebarsViewResolver and exposes a controller that returns a (fully or partly) user-influenced view name.

Vulnerable Code

SpringTemplateLoader.resolve - preserves file: / classpath: and applies suffix to the path portion

// handlebars-springmvc/.../SpringTemplateLoader.java:66-77
@Override
public String resolve(final String location) {
  String protocol = null;
  if (location.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
    protocol = ResourceUtils.CLASSPATH_URL_PREFIX;
  } else if (location.startsWith(ResourceUtils.FILE_URL_PREFIX)) {
    protocol = ResourceUtils.FILE_URL_PREFIX;          // matches "file:"
  }
  if (protocol == null) {
    return super.resolve(location);
  }
  return protocol + super.resolve(location.substring(protocol.length()));
}

SpringTemplateLoader.getResource - no containment check

// handlebars-springmvc/.../SpringTemplateLoader.java:57-63
@Override
protected URL getResource(final String location) throws IOException {
  Resource resource = loader.getResource(location);   // trust Spring blindly
  if (!resource.exists()) {
    return null;
  }
  return resource.getURL();
}

Contrast with the hardened sibling ClassPathTemplateLoader.getResource, which delegates to URLTemplateLoader.classpathResource(...) - the containment helper added by commit d177cdee:

// handlebars/.../io/URLTemplateLoader.java:75-93   (the d177cdee hardening)
protected final String classpathResource(String location) {
  String resolvedPath =
      Paths.get(location).normalize().toString().replace(java.io.File.separatorChar, '/');
  if (location.startsWith("/") && !resolvedPath.startsWith("/")) {
    resolvedPath = "/" + resolvedPath;
  }
  String prefix = getPrefix();
  if (!prefix.equals("/") && !resolvedPath.startsWith(prefix)) {
    throw new IllegalArgumentException(
        "Path traversal attempt detected. Resolved path escapes base prefix: " + location);
  }
  return resolvedPath;
}

SpringTemplateLoader.getResource never calls this helper.

HandlebarsViewResolver - strips the outer prefix/suffix and forwards to compile, no validation

// handlebars-springmvc/.../HandlebarsViewResolver.java:112-117
public HandlebarsViewResolver(final Class<? extends HandlebarsView> viewClass) {
  setViewClass(viewClass);
  setContentType(DEFAULT_CONTENT_TYPE);
  setPrefix(TemplateLoader.DEFAULT_PREFIX);   // "/"
  setSuffix(TemplateLoader.DEFAULT_SUFFIX);   // ".hbs"
}

// handlebars-springmvc/.../HandlebarsViewResolver.java:163-178
protected AbstractUrlBasedView configure(final HandlebarsView view) throws IOException {
  String url = view.getUrl();
  url = url.substring(getPrefix().length(), url.length() - getSuffix().length());
  try {
    view.setTemplate(handlebars.compile(url));      // ← attacker-controlled url
    view.setValueResolver(valueResolvers.toArray(new ValueResolver[0]));
  } catch (IOException ex) {
    if (failOnMissingFile) throw ex;
    logger.debug("File not found: " + url);
  }
  return view;
}

AbstractTemplateLoader.resolve - the load-bearing .hbs gate

// handlebars/.../io/AbstractTemplateLoader.java:47-50
@Override
public String resolve(final String uri) {
  return prefix + normalize(uri) + suffix;   // "/" + path + ".hbs"
}

The suffix string is concatenated as a string. Whether that string lands in the path component, query component, or fragment component of the resulting URL is decided by Spring's URL parsing - not by Handlebars.

Impact

Direct primitive

Unauthenticated arbitrary file read of any file readable by the JVM process UID.

Real-world attack chains (downstream impact)

  1. Read application.yml -> extract jwt.secret / spring.datasource.password -> forge admin JWT or directly connect to the database. Common Spring Boot deployment pattern; one request to game-over.
  2. Read AWS / GCP credentials -> assume role -> exfiltrate buckets, modify infrastructure.
  3. Read K8s service-account token -> API-server access scoped to the pod's role -> namespace lateral movement, secret exfiltration.
  4. Read /proc/self/environ -> harvest CI/CD-injected secrets that never appear on disk.
  5. Read private keys (id_rsa, TLS keys) -> impersonate host / decrypt MITM'd traffic / sign commits.
  6. Read the application's source-code-on-disk to discover further server-side endpoints, hardcoded credentials, or chains.

Indirect

  • Confirmed reachable from any controller that returns user-influenced view names - a documented Spring anti-pattern that nevertheless appears in production (CMS preview endpoints, theme switchers, multi-tenant view routing, @RequestMapping("/{view}") patterns, DefaultRequestToViewNameTranslator-driven URL->view mappings).
  • No authentication, no privilege, no clicks - a single Internet HTTP GET.

Remediation

Any of the following independently closes the bypass. We recommend implementing #1 and #2 for defense in depth.

Apply the containment helper to SpringTemplateLoader.getResource (parity with d177cdee)

// handlebars-springmvc/.../SpringTemplateLoader.java
@Override
protected URL getResource(final String location) throws IOException {
  // For classpath: locations, delegate to the hardened helper as ClassPathTemplateLoader does.
  // For file: locations, perform an explicit canonical-path containment check.
  Resource resource = loader.getResource(location);
  if (!resource.exists()) {
    return null;
  }
  URL url = resource.getURL();
  validateNoUnsafeUrlComponents(url);   // see 9.3
  return url;
}

Validate the resolved URL components

private static void validateNoUnsafeUrlComponents(URL url) {
  if (url.getRef() != null) {
    throw new IllegalArgumentException(
        "Template URL must not contain a fragment: " + url);
  }
  if (url.getQuery() != null) {
    throw new IllegalArgumentException(
        "Template URL must not contain a query: " + url);
  }
}

This is the structural fix - it ensures the textual .hbs check matches the resolved-file behavior regardless of input shape.

Remove the protocol short-circuit entirely

If the supported deployment model is "templates live in one well-known prefix", SpringTemplateLoader.resolve should not preserve file: / classpath: prefixes from user input at all. Either remove that branch, or require an explicit allow-list in the constructor:

public SpringTemplateLoader(ResourceLoader loader, boolean allowProtocolPrefixes) { ... }

with the default being false.

Validate the stripped view name in HandlebarsViewResolver.configure

// handlebars-springmvc/.../HandlebarsViewResolver.java:163-178
protected AbstractUrlBasedView configure(final HandlebarsView view) throws IOException {
  String url = view.getUrl();
  url = url.substring(getPrefix().length(), url.length() - getSuffix().length());
  if (url.contains(":") || url.contains("#") || url.contains("..")) {
    throw new IllegalArgumentException("Unsafe view name: " + url);
  }
  // ...
}

This is a defense-in-depth check that rejects view names containing protocols, fragments, or traversal sequences. It does not by itself remove the SpringTemplateLoader weakness (developers calling handlebars.compile(...) directly still bypass it), but it eliminates the most common reach pattern.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "com.github.jknack:handlebars-springmvc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.5.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-63490"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22",
      "CWE-23",
      "CWE-552"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-02T22:12:03Z",
    "nvd_published_at": "2026-08-20T15:18:04Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n`com.github.jknack.handlebars.springmvc.SpringTemplateLoader` resolves Spring MVC view names into URLs via Spring\u0027s `ResourceLoader` **without applying the path-containment check** that protects every other URL-based loader in the project (`ClassPathTemplateLoader`, `FileTemplateLoader`, `ServletContextTemplateLoader` - all hardened by commit `d177cdee`).\n\nThe only remaining defense for `file:` / `classpath:` view names is the unconditional `.hbs` suffix appended by `AbstractTemplateLoader.resolve(...)`. This suffix is the load-bearing security boundary that prevents a request like `view=file:/etc/passwd` from reading `/etc/passwd` instead of `/etc/passwd.hbs`.\n\n**This boundary is bypassed by a single character: `#` (the URL fragment delimiter).**\n\nWhen the view name ends with `#`, the appended `.hbs` lands inside the URL fragment. Both Spring\u0027s `FileUrlResource.exists()` (via `URI.getSchemeSpecificPart()`) and the JDK\u0027s `URL.openStream()` (via `URL.getFile()`) **silently discard the fragment**, so the file actually opened is the bare path the attacker specified - for example `/etc/passwd` rather than `/etc/passwd.hbs`. The compiled \"template\" is then parsed and rendered into the HTTP response body.\n\nResult: **unauthenticated, network-reachable, arbitrary file read** of any file readable by the JVM process on any Spring MVC application that uses a default-configured `HandlebarsViewResolver` and exposes a controller that returns a (fully or partly) user-influenced view name.\n\n### Vulnerable Code\n\n#### `SpringTemplateLoader.resolve` - preserves `file:` / `classpath:` and applies suffix to the path portion\n\n```java\n// handlebars-springmvc/.../SpringTemplateLoader.java:66-77\n@Override\npublic String resolve(final String location) {\n  String protocol = null;\n  if (location.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {\n    protocol = ResourceUtils.CLASSPATH_URL_PREFIX;\n  } else if (location.startsWith(ResourceUtils.FILE_URL_PREFIX)) {\n    protocol = ResourceUtils.FILE_URL_PREFIX;          // matches \"file:\"\n  }\n  if (protocol == null) {\n    return super.resolve(location);\n  }\n  return protocol + super.resolve(location.substring(protocol.length()));\n}\n```\n\n#### `SpringTemplateLoader.getResource` - **no containment check**\n\n```java\n// handlebars-springmvc/.../SpringTemplateLoader.java:57-63\n@Override\nprotected URL getResource(final String location) throws IOException {\n  Resource resource = loader.getResource(location);   // trust Spring blindly\n  if (!resource.exists()) {\n    return null;\n  }\n  return resource.getURL();\n}\n```\n\nContrast with the hardened sibling `ClassPathTemplateLoader.getResource`, which delegates to `URLTemplateLoader.classpathResource(...)` - the containment helper added by commit `d177cdee`:\n\n```java\n// handlebars/.../io/URLTemplateLoader.java:75-93   (the d177cdee hardening)\nprotected final String classpathResource(String location) {\n  String resolvedPath =\n      Paths.get(location).normalize().toString().replace(java.io.File.separatorChar, \u0027/\u0027);\n  if (location.startsWith(\"/\") \u0026\u0026 !resolvedPath.startsWith(\"/\")) {\n    resolvedPath = \"/\" + resolvedPath;\n  }\n  String prefix = getPrefix();\n  if (!prefix.equals(\"/\") \u0026\u0026 !resolvedPath.startsWith(prefix)) {\n    throw new IllegalArgumentException(\n        \"Path traversal attempt detected. Resolved path escapes base prefix: \" + location);\n  }\n  return resolvedPath;\n}\n```\n\n`SpringTemplateLoader.getResource` never calls this helper.\n\n#### `HandlebarsViewResolver` - strips the outer prefix/suffix and forwards to compile, no validation\n\n```java\n// handlebars-springmvc/.../HandlebarsViewResolver.java:112-117\npublic HandlebarsViewResolver(final Class\u003c? extends HandlebarsView\u003e viewClass) {\n  setViewClass(viewClass);\n  setContentType(DEFAULT_CONTENT_TYPE);\n  setPrefix(TemplateLoader.DEFAULT_PREFIX);   // \"/\"\n  setSuffix(TemplateLoader.DEFAULT_SUFFIX);   // \".hbs\"\n}\n\n// handlebars-springmvc/.../HandlebarsViewResolver.java:163-178\nprotected AbstractUrlBasedView configure(final HandlebarsView view) throws IOException {\n  String url = view.getUrl();\n  url = url.substring(getPrefix().length(), url.length() - getSuffix().length());\n  try {\n    view.setTemplate(handlebars.compile(url));      // \u2190 attacker-controlled url\n    view.setValueResolver(valueResolvers.toArray(new ValueResolver[0]));\n  } catch (IOException ex) {\n    if (failOnMissingFile) throw ex;\n    logger.debug(\"File not found: \" + url);\n  }\n  return view;\n}\n```\n\n#### `AbstractTemplateLoader.resolve` - the load-bearing `.hbs` gate\n\n```java\n// handlebars/.../io/AbstractTemplateLoader.java:47-50\n@Override\npublic String resolve(final String uri) {\n  return prefix + normalize(uri) + suffix;   // \"/\" + path + \".hbs\"\n}\n```\n\nThe suffix string is concatenated as a string. Whether that string lands in the path component, query component, or fragment component of the resulting URL is decided by Spring\u0027s URL parsing - not by Handlebars.\n\n### Impact\n\n#### Direct primitive\n\nUnauthenticated arbitrary file read of any file readable by the JVM process UID.\n\n#### Real-world attack chains (downstream impact)\n\n1. **Read `application.yml` -\u003e extract `jwt.secret` / `spring.datasource.password` -\u003e forge admin JWT or directly connect to the database.** Common Spring Boot deployment pattern; one request to game-over.\n2. **Read AWS / GCP credentials -\u003e assume role -\u003e exfiltrate buckets, modify infrastructure.**\n3. **Read K8s service-account token -\u003e API-server access scoped to the pod\u0027s role -\u003e namespace lateral movement, secret exfiltration.**\n4. **Read `/proc/self/environ` -\u003e harvest CI/CD-injected secrets that never appear on disk.**\n5. **Read private keys (`id_rsa`, TLS keys) -\u003e impersonate host / decrypt MITM\u0027d traffic / sign commits.**\n6. **Read the application\u0027s source-code-on-disk** to discover further server-side endpoints, hardcoded credentials, or chains.\n\n#### Indirect\n\n* Confirmed reachable from any controller that returns user-influenced view names - a documented Spring anti-pattern that nevertheless appears in production (CMS preview endpoints, theme switchers, multi-tenant view routing, `@RequestMapping(\"/{view}\")` patterns, `DefaultRequestToViewNameTranslator`-driven URL-\u003eview mappings).\n* No authentication, no privilege, no clicks - a single Internet HTTP GET.\n\n### Remediation\n\nAny of the following independently closes the bypass. We recommend implementing **#1 and #2** for defense in depth.\n\n#### Apply the containment helper to `SpringTemplateLoader.getResource` (parity with d177cdee)\n\n```java\n// handlebars-springmvc/.../SpringTemplateLoader.java\n@Override\nprotected URL getResource(final String location) throws IOException {\n  // For classpath: locations, delegate to the hardened helper as ClassPathTemplateLoader does.\n  // For file: locations, perform an explicit canonical-path containment check.\n  Resource resource = loader.getResource(location);\n  if (!resource.exists()) {\n    return null;\n  }\n  URL url = resource.getURL();\n  validateNoUnsafeUrlComponents(url);   // see 9.3\n  return url;\n}\n```\n\n#### Validate the resolved URL components\n\n```java\nprivate static void validateNoUnsafeUrlComponents(URL url) {\n  if (url.getRef() != null) {\n    throw new IllegalArgumentException(\n        \"Template URL must not contain a fragment: \" + url);\n  }\n  if (url.getQuery() != null) {\n    throw new IllegalArgumentException(\n        \"Template URL must not contain a query: \" + url);\n  }\n}\n```\n\nThis is the **structural** fix - it ensures the textual `.hbs` check matches the resolved-file behavior regardless of input shape.\n\n#### Remove the protocol short-circuit entirely\n\nIf the supported deployment model is \"templates live in one well-known prefix\", `SpringTemplateLoader.resolve` should not preserve `file:` / `classpath:` prefixes from user input at all. Either remove that branch, or require an explicit allow-list in the constructor:\n\n```java\npublic SpringTemplateLoader(ResourceLoader loader, boolean allowProtocolPrefixes) { ... }\n```\n\nwith the default being `false`.\n\n#### Validate the stripped view name in `HandlebarsViewResolver.configure`\n\n```java\n// handlebars-springmvc/.../HandlebarsViewResolver.java:163-178\nprotected AbstractUrlBasedView configure(final HandlebarsView view) throws IOException {\n  String url = view.getUrl();\n  url = url.substring(getPrefix().length(), url.length() - getSuffix().length());\n  if (url.contains(\":\") || url.contains(\"#\") || url.contains(\"..\")) {\n    throw new IllegalArgumentException(\"Unsafe view name: \" + url);\n  }\n  // ...\n}\n```\n\nThis is a defense-in-depth check that rejects view names containing protocols, fragments, or traversal sequences. It does not by itself remove the SpringTemplateLoader weakness (developers calling `handlebars.compile(...)` directly still bypass it), but it eliminates the most common reach pattern.",
  "id": "GHSA-g29j-rwfv-h99w",
  "modified": "2026-09-02T22:12:03Z",
  "published": "2026-09-02T22:12:03Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/jknack/handlebars.java/security/advisories/GHSA-g29j-rwfv-h99w"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63490"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jknack/handlebars.java/commit/61f43423a337b87db5fec1fe59f0725aaaa38df5"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jknack/handlebars.java"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jknack/handlebars.java/releases/tag/v4.5.3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Handlebars.java: Arbitrary file read in `SpringTemplateLoader` via URL-fragment suffix bypass"
}

Mitigation
Implementation System Configuration Operation

When storing data in the cloud (e.g., S3 buckets, Azure blobs, Google Cloud Storage, etc.), use the provider's controls to disable public access.

CAPEC-150: Collect Data from Common Resource Locations

An adversary exploits well-known locations for resources for the purposes of undermining the security of the target. In many, if not most systems, files and resources are organized in a default tree structure. This can be useful for adversaries because they often know where to look for resources or files that are necessary for attacks. Even when the precise location of a targeted resource may not be known, naming conventions may indicate a small area of the target machine's file tree where the resources are typically located. For example, configuration files are normally stored in the /etc director on Unix systems. Adversaries can take advantage of this to commit other types of attacks.

CAPEC-639: Probe System Files

An adversary obtains unauthorized information due to improperly protected files. If an application stores sensitive information in a file that is not protected by proper access control, then an adversary can access the file and search for sensitive information.