jamesfredley commented on code in PR #15664: URL: https://github.com/apache/grails-core/pull/15664#discussion_r3274456091
########## THREAT_MODEL.md: ########## @@ -0,0 +1,501 @@ +<!-- +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> + +# Threat Model - Apache Grails + +## §1 Header + +- **Project**: Apache Grails (`apache/grails-core`) +- **Version binding**: 8.0.x branch. A report against version *N* is triaged against this document as it stood at *N*, not at HEAD. +- **Date**: 2026-01 +- **Author**: Apache Grails PMC and contributors (initial draft). +- **Status**: **DRAFT** - not yet ratified by maintainers. Open questions in §14 must be resolved before this document is binding. +- **Reporting cross-reference**: findings that may violate a property claimed in §8 should be reported privately per [`SECURITY.md`](./SECURITY.md) (which routes to the [ASF Security Team](https://www.apache.org/security/)). Findings that fall under §3 (out of scope), §9 (disclaimed properties), or §11a (known non-findings) will be closed publicly citing the relevant section of this document. +- **Provenance legend**: every non-trivial claim is tagged. + - *(documented)* - stated in the project's own docs ([`grails-doc/src/en/guide/security/`](./grails-doc/src/en/guide/security/), [`SECURITY.md`](./SECURITY.md), [`README.md`](./README.md), [`AGENTS.md`](./AGENTS.md), or the public Grails Guide). + - *(maintainer)* - stated by a maintainer in response to a question from this drafting process. + - *(inferred)* - reasoned from code structure, absence of a feature, or general domain knowledge. Each must have a matching entry in §14. +- **Draft confidence**: ~46 *(documented)* / 0 *(maintainer)* / ~58 *(inferred)*. This model is a draft-first artifact per the rubric §3.2 - the *(inferred)* count is expected to drop sharply once §14 is worked through with the PMC. + +**Project description**: Apache Grails is an opinionated, full-stack web application framework for the JVM. It composes Apache Groovy, Spring Framework, Spring Boot, GORM (Hibernate / MongoDB / Neo4j data mapping), and GSP/JSON view rendering, and ships a CLI (`grails-shell-cli`, `grails-forge-cli`) plus an HTTP application generator (`grails-forge`). Grails is **embedded into a user-authored web application**; it is not deployed as a standalone network service by the project. The unit of trust modeled here is "an application using the Grails framework," not "a Grails server." *(documented: [README.md](./README.md))* + +--- + +## §2 Scope and intended use + +**Primary intended use**: building server-side web applications in Groovy/Java on the JVM, deployed as Spring Boot executable JARs or WARs running under an operator the application owner controls. *(documented: [README.md](./README.md))* + +**Secondary intended use**: project scaffolding and code generation via the CLI tools and `grails-forge` HTTP API at <https://start.grails.org>. *(documented: [README.md](./README.md))* + +**Caller roles** (the model distinguishes three; this is not a network-service split since the framework is in-process within the user's app): + +| Role | Trust level | Description | +|---|---|---| +| **End user (HTTP client)** | **Untrusted** | Sends HTTP requests to a deployed Grails application. Source of all attacker-controllable input considered in this model. *(inferred)* | +| **Application developer / operator** | **Trusted** | Writes controllers, services, domain classes, URL mappings, GSP templates; configures `application.yml` / `application.groovy`; runs the CLI; chooses plugins. *(inferred)* | +| **Plugin / profile author** | **Trusted-by-association** | Author of a third-party Grails plugin or `grails-forge` profile. Code from a plugin runs with full application privileges. The framework does not isolate plugin code. *(inferred)* | + +### Component-family table + +The framework is large; not every module has the same threat profile. The model carves the framework into the following families: + +| Family | Representative entry point(s) | Touches outside process? | In or out of model | +|---|---|---|---| +| HTTP request ingress | [`GrailsDispatcherServlet`](./grails-web-mvc/src/main/groovy/org/grails/web/servlet/mvc/GrailsDispatcherServlet.groovy), [`UrlMappingsHandlerMapping`](./grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy) | Yes - network (via Spring Boot embedded container) | **In** | +| Interceptors / controllers | [`GrailsInterceptorHandlerInterceptorAdapter`](./grails-interceptors/src/main/groovy/org/grails/plugins/web/interceptors/GrailsInterceptorHandlerInterceptorAdapter.groovy), `grails.artefact.Controller` trait | Yes - via Spring MVC | **In** | +| Data binding | [`GrailsWebDataBinder`](./grails-web-databinding/src/main/groovy/grails/web/databinding/GrailsWebDataBinder.groovy), `SimpleDataBinder`, [`DefaultDataBindingSourceRegistry`](./grails-web-databinding/src/main/groovy/org/grails/web/databinding/bindingsource/DefaultDataBindingSourceRegistry.groovy) | Indirectly (consumes request body) | **In** | +| View rendering (GSP, JSON, Markup) | [`GroovyPageCompiler`](./grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageCompiler.groovy), [`ResolvableGroovyTemplateEngine`](./grails-views-core/src/main/groovy/grails/views/ResolvableGroovyTemplateEngine.groovy), [`SmartViewResolver`](./grails-views-core/src/main/groovy/grails/views/mvc/SmartViewResolver.groovy) | Filesystem (template files) | **In** | +| Codecs / output encoding | [`grails-encoder`](./grails-encoder/), [`HTMLCodec`](./grails-encoder/src/main/groovy/org/grails/encoder/CodecFactory.java) and siblings | No | **In** | +| GORM mapping / validation integration | [`GormEntityTransformation`](./grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy), [`PersistentEntityValidator`](./grails-datamapping-validation/src/main/groovy/grails/gorm/validation/PersistentEntityValidator.groovy), [`HibernateMappingBuilder`](./grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy) | Yes - JDBC / DB driver | **In** | +| Configuration loading | [`ExternalConfigRunListener`](./grails-core/src/main/groovy/grails/config/external/ExternalConfigRunListener.groovy), [`GroovyConfigPropertySourceLoader`](./grails-core/src/main/groovy/org/grails/core/cfg/GroovyConfigPropertySourceLoader.groovy), [`GrailsApplicationPostProcessor`](./grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy) | Yes - filesystem, env, system properties | **In** | +| Plugin / artefact discovery | [`PluginManagerLoader`](./grails-core/src/main/groovy/grails/plugins/PluginManagerLoader.groovy), [`ClassPathScanner`](./grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy), [`GrailsFactoriesLoader`](./grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy) | Filesystem (classpath JARs) | **In** | +| Compile-time AST transforms | [`GlobalGrailsClassInjectorTransformation`](./grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy), [`ResourceTransform`](./grails-rest-transforms/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy), [`ViewsTransform`](./grails-views-core/src/main/groovy/grails/views/compiler/ViewsTransform.groovy) | No (build only) | **In** (developer-trusted inputs only - see §6) | +| CLI / shell (`grails-shell-cli`) | [`GrailsCli`](./grails-shell-cli/src/main/groovy/org/grails/cli/GrailsCli.groovy), [`MavenProfileRepository`](./grails-shell-cli/src/main/groovy/org/grails/cli/profile/repository/MavenProfileRepository.groovy) | Yes - network (Maven), filesystem | **In** (with caveats - see §3 and §7) | +| Interactive consoles (`grails-console`) | [`GrailsShell`](./grails-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy), `GroovyConsoleApplicationContext` | Local I/O | **Out** - developer-only tool, see §3 | +| `grails-forge` HTTP API (start.grails.org) | [`ZipCreateController`](./grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/zip/ZipCreateController.java), [`GitHubCreateController`](./grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/github/GitHubCreateController.java) | Yes - network | **Out** - separate Micronaut-based service deployed independently from any application built with Grails; modeled separately by the operators of start.grails.org. *(inferred)* | +| Generated application scaffolding | `grails-profiles/`, files emitted by `create-app` | n/a | **Out** - separately authored; the framework's contract does not extend to scaffolded code once it is in the user's repository. See §3. | +| `grails-test-examples/`, demo apps | n/a | n/a | **Out** - test/demo code, not shipped. See §3. | + +--- + +## §3 Out of scope (explicit non-goals) + +The framework **does not** attempt to defend against, and **does not** model, the following. Triagers may close findings citing this section. + +- **Application-level authentication and authorization.** The framework ships no built-in user store, login flow, or session-based auth. The user is expected to integrate with the Spring Security plugin, Apache Shiro, or an equivalent. The `grails-shell-cli` `SpringSecurityCompilerAutoConfiguration` is a compile-time hook for the plugin, not an auth implementation. *(documented: [grails-doc/src/en/guide/security/authentication.adoc](./grails-doc/src/en/guide/security/authentication.adoc), [grails-doc/src/en/guide/security/securityPlugins.adoc](./grails-doc/src/en/guide/security/securityPlugins.adoc))* +- **Transport security (TLS).** Provided by the Spring Boot embedded container (Tomcat / Jetty / Undertow / Netty) or by a reverse proxy in front of the application. Out of layer. *(inferred)* +- **Database engine, JDBC driver, and JVM vulnerabilities.** The framework is a consumer; bugs in these layers are upstream. *(inferred)* +- **Spring Framework, Spring Boot, Hibernate, GORM datastore implementations.** Triaged in their own projects; the framework re-exposes their public APIs but does not own their threat models. *(inferred)* +- **Third-party Grails plugins** (anything not in this repository). Plugins run with full application privileges; their threat models are the responsibility of their authors. *(inferred)* +- **Generated application scaffolding output** (files emitted by `create-app` or `grails-forge`). Once written to the user's filesystem, the output is the user's code. The generator does not promise the generated code remains free of advisories as Grails evolves. *(inferred)* +- **`grails-test-examples/`, demo and reproducer modules**, and any `examples/` or scaffold output checked into the repository. Not shipped in framework distributions; threat-model separately if used as a starting point. *(inferred)* +- **Interactive consoles (`grails-console` module: `GrailsShell`, `GroovyConsole`).** These provide arbitrary Groovy code execution with full application-context access **by design**. They are developer tools. Reachability of these consoles from a deployed application is a deployment-configuration finding against the operator, not a framework vulnerability. *(inferred)* +- **`grails-forge` HTTP service at start.grails.org**, including the `ZipCreateController` / `GitHubCreateController` endpoints. The Micronaut-based service is deployed independently, has its own operator, and is modeled separately. The Grails framework neither runs this service inside user applications nor inherits its risk. *(inferred)* Review Comment: I am torn, I don't want to care about the production runtime for start.grails.org on grails-core, but do care separately. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
