This is an automated email from the ASF dual-hosted git repository.

paulk-asert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new f02441ec9a minor edits clarify security stance for ASTTest
f02441ec9a is described below

commit f02441ec9a89effe9111738b279b35558944f770
Author: Paul King <[email protected]>
AuthorDate: Thu Jul 16 17:54:41 2026 +1000

    minor edits clarify security stance for ASTTest
---
 .github/SECURITY.md | 13 +++++++++++++
 AGENTS.md           |  9 ++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 3eddc86025..81fe6668f1 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -67,6 +67,19 @@ may arrive as a single report bundling many candidate 
findings: each is
 assigned one disposition from the threat model, and only confirmed issues
 enter the private reporting flow below.
 
+**Compiling untrusted Groovy is already code execution — not only
+running it.** Groovy runs code *during* compilation: global AST
+transforms on the compile classpath, static initializers, `@Grab`
+dependency resolution, and the `@ASTTest` annotation (whose closure is
+evaluated at compile time in a fresh shell). A pipeline that *compiles*
+attacker-supplied Groovy for analysis, linting, or type-checking — but
+deliberately never runs the output — is therefore **not** a safety
+boundary; it has already granted code execution. Treat "compile-only"
+as equivalent to "run": keep `@Grab` off for such input
+(`-Dgroovy.grape.enable=false`), and note that `SecureASTCustomizer` is
+a best-effort grammar filter, not a sandbox, so it does not change this.
+See [`THREAT_MODEL.md`](../THREAT_MODEL.md) §3.
+
 ## Reporting a Vulnerability
 
 Do **not** open a public JIRA issue, GitHub issue, pull request, or
diff --git a/AGENTS.md b/AGENTS.md
index d349500273..859801bb6e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -199,7 +199,14 @@ restating it.
   pulls, dynamic code), the exact code and command are shown to
   a human who explicitly chooses to run / sandbox / skip, and
   dependency resolution (`@Grab`) is **off by default**
-  (`-Dgroovy.grape.enable=false`) until a human permits it. With
+  (`-Dgroovy.grape.enable=false`) until a human permits it. Note
+  that **compiling** a reproducer is not a safe halfway step
+  short of running it: Groovy executes code at compile time via
+  global AST transforms, static initializers, `@Grab`, and
+  `@ASTTest` (whose closure is evaluated during compilation), so
+  "we only compiled it, we didn't run it" is not a safety argument —
+  the pre-screen and the run / sandbox / skip gate apply to
+  compilation, not just execution. With
   no human available (a batch sweep), flagged code is **not
   run** — it is set aside for review. The pre-screen is a
   fallible aid, never a substitute for the human reading the

Reply via email to