master/maintenance branches of the in-scope repositories as of the date below. Because Maven is mid-transition from the 3.x to the 4.x runtime line, this model carries a 3.x-vs-4.x axis as a first-class distinction rather than describing a single profile (see §2, §4, §5a, §6).master HEAD. Each branch-target (§2) binds to the releases cut from that branch. See §14 Q20.What Maven is. Apache Maven is a build-automation and dependency-management tool for JVM projects. Given a project description in pom.xml (the Project Object Model), Maven resolves declared dependencies and build plugins from configured repositories into a local repository (~/.m2/repository), then executes a lifecycle of plugin goals — compiling, testing, packaging, signing, and deploying code. Plugins and build extensions are ordinary JVM artifacts that Maven downloads and executes as arbitrary code in the build JVM. Maven is invoked from the CLI (mvn, or the mvnd daemon, or a project-local mvnw wrapper) by a developer or a CI runner. Its security model is therefore fundamentally a supply-chain and arbitrary-code-execution model, and — by explicit design — Maven does not sandbox the code it is asked to build or the plugins it is asked to run.
Primary intended use. Building, testing, packaging, and publishing JVM software from a trusted pom.xml in a developer or CI environment, resolving dependencies and plugins from repositories the operator has chosen to configure and trust. (documented — security.html: “the Maven security model assumes you trust the pom.xml and the code, dependencies and repositories that are used in your build”.)
Caller roles. Unlike a network service, Maven has no anonymous client. The roles are:
pom.xml, settings.xml, and .mvn/ config; chooses repositories; runs mvn. Trusted — this actor has already chosen what code to execute. (inferred, Q10)The 3.x-vs-4.x axis (carried on this table). Maven is mid-transition. Most plugin master branches still compile and run against the Maven 3.9.x API; seven “split” plugins have moved master to the Maven 4 API and keep a *-3.x maintenance branch on the 3.9.x API. The runtime line changes the trust surface (consumer-POM transform, mvnenc, resolver 2.x, mvnup — all Maven-4-only; see §6/§9). Each branch-target is therefore tagged with the Maven API line it targets, and a finding is triaged against that line's surface.
| # | Repository / component | Branch-target(s) | Maven API line | Touches outside process | In model? |
|---|---|---|---|---|---|
| Core & runtime | |||||
| 1 | maven (core) | master (4.0.x); maven-3.9.x/3.10.x maint. | both | reads POM/settings/~/.m2, spawns plugin code, network resolve | yes |
| 2 | maven-resolver | master (2.x); 1.9.x maint. | both | HTTP(S) transport, local-repo I/O | yes |
| 3 | maven-mvnd (daemon) | master | 4.x-oriented | long-lived JVM, sockets, filesystem | yes |
| 4 | maven-wrapper | master | line-agnostic | downloads + executes a Maven distribution | yes |
| 5 | maven-build-cache-extension | master | 4.x-oriented | reads/writes build-output cache | yes |
| Single-line master plugins (Maven 3.9.x API) | |||||
| 6 | maven-surefire (surefire + failsafe) | master | 3.x | forks test JVMs, runs test code | yes |
| 7 | maven-javadoc-plugin | master | 3.x | forks javadoc, unpacks archives | yes |
| 8 | maven-dependency-plugin | master | 3.x | resolves + unpacks artifacts | yes |
| 9 | maven-checkstyle-plugin | master | 3.x | reads source, resolves rulesets | yes |
| 10 | maven-release-plugin | master | 3.x | SCM writes, invokes nested Maven | yes |
| 11 | maven-shade-plugin | master | 3.x | rewrites/merges JAR bytecode | yes |
| 12 | maven-assembly-plugin | master | 3.x | reads/writes archives | yes |
| 13 | maven-scm | master | 3.x | invokes SCM clients (git/svn/…) | yes |
| 14 | maven-site-plugin | master | 3.x | renders site, resolves skins/reports | yes |
| 15 | maven-enforcer | master | 3.x | evaluates rules over the build | yes |
| 16 | maven-archetype | master | 3.x | scaffolds projects from templates | yes |
| 17 | maven-resolver-ant-tasks | master | 3.x | Ant-side resolution/transport | yes |
| 18 | maven-indexer | master | 3.x | parses repository index metadata | yes |
| 19 | maven-war-plugin | master | 3.x | assembles WAR archives (overlays, resource filtering) | yes |
| 20 | maven-ear-plugin | master | 3.x | assembles EAR archives from module artifacts | yes |
Split plugins — master on Maven 4 API + *-3.x maintenance | |||||
| 21 | maven-compiler-plugin | master (M4); *-3.x | both (two targets) | forks/embeds compiler, reads source | yes |
| 22 | maven-jar-plugin | master (M4); *-3.x | both | writes JARs | yes |
| 23 | maven-clean-plugin | master (M4); *-3.x | both | deletes filesystem paths | yes |
| 24 | maven-deploy-plugin | master (M4); *-3.x | both | uploads artifacts to remote repo | yes |
| 25 | maven-install-plugin | master (M4); *-3.x | both | writes to local repo | yes |
| 26 | maven-resources-plugin | master (M4); *-3.x | both | copies/filters resource files | yes |
| 27 | maven-source-plugin | master (M4); *-3.x | both | packages source JARs | yes |
| Shared libraries (build/release path; no standalone CLI) | |||||
| 28 | maven-filtering | master | line-agnostic | interpolates ${...} into resource files (used by resources/war plugins) | yes |
| 29 | maven-shared-utils | master | line-agnostic | shared IO / process-exec / CLI helpers used across plugins | yes |
| 30 | maven-archiver | master | line-agnostic | shared archive + JAR/WAR manifest assembly used by packaging plugins | yes |
| 31 | maven-dependency-analyzer | master | line-agnostic | bytecode analysis of used-vs-declared dependencies (engine behind dependency:analyze) | yes |
| 32 | maven-shared-io | master | line-agnostic | shared file/resource IO helpers; low activity, likely near-defunct but still resolved by some plugins | yes |
Counting the two targets each for rows 1, 2, and 21–27 yields ~41 branch-targets across ~32 repositories. mvnup and mvnenc ship inside the Maven 4 core distribution (row 1, master) and are in model. See §14 Q3.
maven-parent, apache parent, plugin/plugins parents) — configuration aggregation, no runtime surface of their own. (inferred, Q2)maven-studies — experimental/incubating code, not a supported product. (inferred, Q2)maven-site, Fluido/skin projects) — presentation, not the tool. (inferred, Q2)Maven is not a network service; it is a local process that pulls remote inputs and executes them. The meaningful trust transitions are:
Local config → build JVM (trusted → trusted). pom.xml, settings.xml, .mvn/extensions.xml, .mvn/maven.config, and the existing contents of ~/.m2/repository are treated as already-authorized by the operator. Malicious content here is out of model — the operator supplying it has already won. (inferred, Q5) The exception the operator must understand: cloning and building an untrusted third-party project makes that project's pom.xml/.mvn/ a trusted input to Maven even though the operator did not author it (see §11). (inferred, Q10)
Remote repository → local repository (semi-trusted → trusted-on-arrival). This is the primary security boundary. Artifacts and metadata arrive over resolver transport from repositories/mirrors. Maven verifies transport integrity (checksums) but does not, in core, verify publisher authenticity (PGP signatures) — see §8/§9. Once an artifact lands in ~/.m2/repository it is thereafter treated as trusted local input (transition 1). A poisoned local repo is out of model; poisoning it over the wire is in model. (inferred, Q4, Q5, Q6, Q11)
Resolved plugin/extension → arbitrary code execution (BY DESIGN). A resolved plugin, build extension, or ${...}-driven lifecycle binding runs as arbitrary JVM code in the build. There is no trust boundary here — crossing from “declared in POM” to “executing” is the intended behavior, not a violation. (documented — security.html trust statement.)
Maven-4-only transitions (in model only for 4.x branch-targets):
install/deploy, Maven 4 rewrites the source pom.xml into a flattened consumer POM that is what downstream actually resolves. The published POM deliberately differs from the source POM. (documented — whatsnewinmaven4: consumer POM is flattened, drops parent references, flattens BOM imports, keeps only compile/runtime transitive deps.) See §9 / §11a / Q7.mvnup → source pom.xml rewrite. The Maven 4 upgrade tool writes back into the user's pom.xml in place. (documented — whatsnewinmaven4.) The write target (the source tree) is a trusted output location; the transform inputs are the trusted POM. (inferred, Q8) See Q8.mvnenc → encrypted settings-security/vault. Maven 4 reworks settings encryption from Maven 3‘s obfuscation to real encryption with optional external vault. (documented — whatsnewinmaven4.) Key/vault material is outside Maven’s boundary (§10). (inferred, Q9)Reachability precondition (the triager's first test). A finding is in-model only if it is reachable from a remote-repository-supplied artifact/metadata byte (transition 2), from resolver transport, or from the Maven-4 transform surfaces above — without first assuming the operator supplied malicious local config or a pre-poisoned ~/.m2. A finding that requires attacker control of pom.xml/settings.xml/~/.m2 on a build the operator authored is OUT-OF-MODEL: trusted-input (§6, §13).
~/.m2 are trusted. (inferred, Q5)http:// external repositories are treated as untrusted and are blocked by default in the shipped conf/settings.xml via the external:http:* mirror / <blocked> mechanism. (documented — security.html, CVE-2021-26291 mitigation.)~/.m2/repository and the project target/, open network connections to configured repositories, fork child JVMs/processes (plugins, test runners, compilers, SCM clients), and read environment variables and settings.xml (which may contain plaintext or obfuscated credentials). mvnd additionally runs a long-lived daemon JVM reused across builds. These are all intended. (inferred, Q5, Q12)| Knob | Default | Effect on model | Maintainer stance |
|---|---|---|---|
Resolver checksum policy (-C/--strict-checksums vs -c/--lax-checksums; checksumPolicy) | warn (lax) | warn logs but does not fail on checksum mismatch → integrity not enforced by default | to confirm — Q4 |
| PGP signature verification | off in core (no signature check) | authenticity of publisher unverified unless an extension is added | to confirm — Q6 |
maven.consumer.pom.flatten (M4) | on for install/deploy | published POM ≠ source POM | to confirm — Q7 |
settings.xml credential encryption | Maven 3: obfuscation; Maven 4: mvnenc real encryption | master-password/vault protects at-rest creds | to confirm — Q9 |
external:http:* repo blocking | on (shipped settings.xml) | plaintext external repos rejected | documented (security.html) |
mvnd daemon reuse | on when invoked as mvnd | cross-build JVM state reuse | to confirm — Q12 |
Insecure-default question (Q4, wave 1). Resolver's default checksum policy is warn, not fail. Is warn the supported production posture (so “a corrupted artifact was accepted with only a warning” is BY-DESIGN/downstream-responsibility), or is fail/--strict-checksums the intended posture for anything trust-sensitive (making a silent-accept report VALID-HARDENING)? This reshapes §8, §9, §10, §11a, §13 at once.
Maven's inputs split cleanly into operator-supplied (trusted) and repository-supplied (semi-trusted). Where the trust posture differs between the 3.x and 4.x lines, the table has a Line column.
| Input | Line | Origin | Attacker-controllable? | Caller/operator must enforce |
|---|---|---|---|---|
pom.xml (source/build POM) | both | operator's project | no — trusted local config | don't build untrusted projects unsandboxed (§10) (inferred, Q5) |
settings.xml (+ settings-security) | both | operator ~/.m2 | no — trusted; holds credentials | protect the file / key material (inferred, Q5, Q9) |
.mvn/extensions.xml, .mvn/maven.config | both | operator project | no — trusted; loads extensions as code | same as pom.xml (inferred, Q5) |
Existing ~/.m2/repository contents | both | prior builds | no — trusted-on-arrival | don't share a poisoned local repo (inferred, Q11) |
| Resolved dependency/plugin/extension bytes | both | remote repo/mirror | yes | checksum policy; add signature verification; pin versions (inferred, Q4, Q6) |
Repository metadata (maven-metadata.xml, checksums, index) | both | remote repo/mirror | yes | resolver parses these before trust is established (inferred, Q4, Q18) |
| Resolver transport (HTTP responses, redirects, TLS) | both | network/mirror | yes | HTTPS; block plaintext external repos (documented — security.html) |
| Archive contents unpacked by plugins (zip/tar/jar) | both | remote artifact | yes | path-traversal (zip-slip) surface in unpack plugins (documented — security.html Plexus Archiver) |
Consumer-POM transform input (mvn deploy) | 4.x only | operator project → published | source no; the published result is a new surface for downstream | verify what you publish matches intent (inferred, Q7) |
mvnup rewrite input | 4.x only | operator pom.xml | no — trusted, but written back in place | review the diff mvnup produces (inferred, Q8) |
mvnenc secrets / vault | 4.x only | operator | no — trusted | manage the master key/vault (§10) (inferred, Q9) |
Size/shape. Maven imposes no general bound on POM size, dependency-graph depth, or artifact size; resolution of a hostile dependency graph (deep transitive fan-out, decompression of hostile archives) is a resource surface. (inferred, Q17)
In scope:
http://) transport the operator has not blocked. (documented — security.html, CVE-2021-26291/CVE-2013-0253/CVE-2012-6153.)Explicitly out of scope:
pom.xml, settings.xml, .mvn/, or ~/.m2. They have already chosen the code that runs. (documented — security.html trust statement.)~/.m2 or the source tree. (inferred, Q5)For each: property → violation symptom → severity → provenance.
conf/settings.xml blocks external:http:* so a plaintext external mirror cannot silently substitute artifacts. Symptom: a MITM downgrades resolution to plaintext and substitutes bytes. Severity: high. (documented — security.html.)mvnenc, Maven 4). Server credentials in settings.xml can be encrypted (real encryption in 4.x; obfuscation only in 3.x). Symptom: plaintext credential recovery from settings.xml. Severity: medium (3.x is obfuscation, not a confidentiality guarantee — §9). (documented — whatsnewinmaven4.)OutOfMemoryError — a robustness bug, not memory unsafety. Severity: correctness-only unless it enables the above. (inferred, Q2)No resource-exhaustion guarantee is made. Maven does not bound POM size, transitive-graph size, archive decompression, or plugin CPU/memory. A hostile dependency graph or archive that exhausts memory/CPU is not a §8 violation. (inferred, Q17) See §9.
This is the load-bearing section for triage. State each plainly.
pom.xml it is given, which “commonly includes compiling and running the associated code and using plugins and dependencies”. A plugin, extension, test, or lifecycle binding running arbitrary code is the intended behavior, not a vulnerability. (documented — security.html.) A scanner reporting “plugin/extension/test executes arbitrary code” is a BY-DESIGN non-finding, not a vulnerability. See §11a.~/.m2/repository, they are trusted. Maven does not re-validate them against a remote source on each build. (inferred, Q11)settings.xml and settings-security.xml. Use mvnenc (4.x). (documented — whatsnewinmaven4: Maven 3's scheme “more accurately called password obfuscation”.)pom.xml” is BY-DESIGN, not tampering. (documented — whatsnewinmaven4.) See §11a.mvnup's rewrite is safe to apply unreviewed — it rewrites your pom.xml; the operator must review the diff. (inferred, Q8)mvnd. The daemon reuses a JVM across builds; it is not an isolation boundary between projects built by the same daemon. (inferred, Q12)maven-build-cache-extension keys outputs by hashes; a shared/remote cache is only as trustworthy as its writers. (inferred, Q14)maven-wrapper. mvnw downloads and executes whatever Maven distribution distributionUrl names; checksum pinning (distributionSha256Sum) is optional and operator-supplied. (inferred, Q13)For Maven, “downstream” is the build author / operator / CI owner.
external:http:* block; use a controlled proxy/mirror rather than arbitrary third-party repos. (documented — security.html.)--strict-checksums and add signature-verification tooling if your threat model needs publisher authenticity. (inferred, Q4, Q6)LATEST/RELEASE for plugins and dependencies) to reduce dependency-confusion and surprise-upgrade risk. (inferred, Q17)settings.xml and key material. Use mvnenc (4.x); manage the master password / external vault; never commit credentials. (inferred, Q9)mvnup diffs before committing the rewritten pom.xml. (inferred, Q8)distributionSha256Sum, wrapperSha256Sum) if you commit mvnw into a repo others run. (inferred, Q13)mvn ... (or opening it in an IDE that auto-imports) executes that project's plugins/extensions as you. What to do instead: build unknown projects only inside a disposable container/VM. (inferred, Q10)http:// repository or disabling the external:http:* block. Reopens the MITM/substitution vector CVE-2021-26291 closed. (documented — security.html.)mvnd across mutually-distrusting projects and assuming isolation. The daemon JVM is shared. (inferred, Q12)mvnw wrapper with an unpinned distributionUrl. Anyone who moves/poisons that URL controls the Maven that runs. (inferred, Q13)Feed this list to scanners as a suppression / negative prompt.
BY-DESIGN per §9 — this is Maven's core function, not a vulnerability. Applies to exec-style goals, code-generating plugins, surefire-forked test code, shade bytecode rewriting, etc. (documented — security.html.)pom.xml.” BY-DESIGN per §9 (Maven 4 consumer-POM transform). Not tampering. (documented — whatsnewinmaven4.)test-scope, provided-scope, or integration-test-only dependencies of the Maven repos themselves. These do not ship in released Maven artifacts and are not reachable in a consuming build → OUT-OF-MODEL: trusted-input/unsupported-surface for the Maven product. (inferred, Q17)settings.xml contains a credential.” Expected — that is what settings.xml is for; confidentiality is mvnenc‘s job at rest, not a finding against the file’s existence. (inferred, Q9)BY-DESIGN/downstream, not a bug. (inferred, Q4)BY-DESIGN — the resolve-and-execute model per §4/§9. (documented — security.html.)warn to fail — flips Q4's disposition.mvnup/consumer-POM).*-3.x branch — removes a branch-target column.mvnd or build-cache-extension gains a network-shared default surface (remote daemon, remote cache) — adds a network adversary.MODEL-GAP and the model must be revised (add the property to §8/§9), not decided ad hoc.| Disposition | Meaning | Licensed by |
|---|---|---|
VALID | Violates a claimed property via a repo/mirror/transport-controlled input or a Maven-4 transform surface. | §8, §6, §7 |
VALID-HARDENING | No §8 property broken, but a §11 misuse is easy enough that the project elects to harden (e.g. tighten a default). | §11, §5a |
OUT-OF-MODEL: trusted-input | Requires attacker control of pom.xml/settings.xml/.mvn//~/.m2 on an operator-authored build. | §6 |
OUT-OF-MODEL: adversary-not-in-scope | Requires the operator, a local co-tenant, or the built project's author (when the operator chose to build it). | §7 |
OUT-OF-MODEL: unsupported-component | Lands in parent POMs, maven-studies, site/skins, SVN mirrors, or CI infra. | §3 |
OUT-OF-MODEL: non-default-build | Only manifests when a §5a default is flipped to the less-safe value (e.g. external:http:* block removed). | §5a |
BY-DESIGN: property-disclaimed | Plugin/extension/test code execution; published-POM ≠ source-POM; checksum ≠ signature; resolve-and-run. | §9 |
KNOWN-NON-FINDING | Matches a §11a entry (test-scope SCA alerts, settings.xml-holds-a-credential, etc.). | §11a |
MODEL-GAP | Cannot be routed above — triggers a model revision. | §12 |
Each (inferred) tag in the body routes to one question below. Every question states a proposed answer to confirm/correct. Grouped in waves.
Wave 1 — scope & the 3.x/4.x axis (shapes everything else):
mvnenc, resolver 2.x, mvnup) are out of model for 3.x targets. Proposed: correct. (→ §2, §4, §6)maven-studies, SVN mirrors, CI/infra, site/skins, and “the security of the artifacts your build produces” — is right and complete. Proposed: correct. (→ §3)mvnup and mvnenc ship inside the Maven 4 core distribution (repo #1 master) and are in model as part of core, not as separate products. Proposed: correct. (→ §2)warn, not fail. Is warn the supported posture (silent-accept-on-mismatch = BY-DESIGN/downstream), or is --strict-checksums intended for trust-sensitive use (silent-accept = VALID-HARDENING)? (→ §5a, §8, §9, §11a)Wave 2 — inputs, trust, and the Maven-4 surfaces:
pom.xml, settings.xml, .mvn/ config, and existing ~/.m2 contents are trusted local inputs; findings requiring attacker control of them (on an operator-authored build) are out of model. Proposed: correct. (→ §4, §6)BY-DESIGN non-finding. Are there transform behaviors (e.g. what the consumer POM retains) that you would consider security-relevant? Proposed: transform itself is by design; retention of internal repo URLs would be the concern. (→ §9, §11a)mvnup rewrites the operator's pom.xml in place from trusted inputs; the operator is expected to review the diff. Does mvnup ever read untrusted/remote input into that rewrite (which would make it an in-model input surface)? Proposed: inputs are trusted; operator reviews the diff. (→ §4, §6, §9, §10)mvnenc provides at-rest credential encryption; master-key/vault management is a downstream responsibility, and “settings.xml contains a credential” is not a finding. Proposed: correct. (→ §5a, §9, §10, §11a)Wave 3 — adversary, resolver, runtime components:
~/.m2/repository) is out of model (trusted-on-arrival); poisoning it over the wire during resolution is in model. Proposed: correct. (→ §4, §9)mvnd is not an isolation boundary between projects built by the same daemon; cross-build state isolation is not a claimed property. Proposed: correct. (→ §5, §9, §11)maven-wrapper executes whatever distributionUrl names; checksum pinning is optional/operator-supplied and there is no built-in trust anchor. Proposed: correct — disclaimed. (→ §9, §10, §11)maven-build-cache-extension makes no integrity guarantee for shared/remote caches; authenticating cache writers is a downstream responsibility. Proposed: correct. (→ §9, §10)Wave 4 — plugin branch-targets & non-findings:
*-3.x branch targets the Maven 3.9 API and shares most code with master; a finding present in shared code applies to both branch-targets, while a finding in Maven-4-only master code applies only to the 4.x target. Proposed: correct. (→ §2)master plugins require Maven 3.9.x at runtime despite living on master (no *-3.x branch needed). Proposed: correct. (→ §2)test/provided/IT-only and build-harness-only transitive deps of the Maven repos are not reachable in the shipped product → out of model; and no resource-exhaustion (dependency-graph/XML-entity/archive-bomb) guarantee is made. Proposed: correct and representative. (→ §6, §8, §9, §11a)maven-resolver-ant-tasks and maven-indexer inherit the same repo-supplied-metadata trust posture as core resolver (index/metadata parsing is an in-model input). Proposed: correct. (→ §2, §6)Wave 5 — meta / process:
SECURITY.md in apache/maven master (verified 404); the documented model lives on maven.apache.org/security.html. For the scan to mechanically discover this model, where should the canonical THREAT_MODEL.md live (per-repo vs one umbrella), and can an AGENTS.md → SECURITY.md → THREAT_MODEL.md discoverability chain be added? Proposed: one umbrella model, linked from each repo's SECURITY.md/AGENTS.md. (→ §1)master surface. Proposed: correct. (→ §1)Deferred for v0. Once the PMC ratifies, emit a threat-model.yaml sidecar indexing: branch-target → Maven API line (§2); entry point → parameter trust (§6); §5a knobs + defaults; §8 properties (symptom + severity); §9 disclaimed properties + false friends; §11a non-findings; §13 dispositions. The prose remains canonical.