attackmap-analyzer-java-spring 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ Metadata-Version: 2.4
2
+ Name: attackmap-analyzer-java-spring
3
+ Version: 0.2.0
4
+ Summary: Java/Kotlin Spring Boot ecosystem analyzer plugin for AttackMap (Spring MVC routing, JAX-RS, Ktor; Spring Data JPA / Mongo / Redis; Spring Security; jjwt; RestTemplate / WebClient / OkHttp).
5
+ Author: AttackMap Contributors
6
+ Author-email: Matthew Davis <mlaify@mlaify.io>
7
+ Maintainer-email: Matthew Davis <mlaify@mlaify.io>
8
+ License-Expression: MIT
9
+ Project-URL: Homepage, https://github.com/mlaify/attackmap-analyzer-java-spring
10
+ Project-URL: Repository, https://github.com/mlaify/attackmap-analyzer-java-spring
11
+ Project-URL: Issues, https://github.com/mlaify/attackmap-analyzer-java-spring/issues
12
+ Project-URL: Changelog, https://github.com/mlaify/attackmap-analyzer-java-spring/blob/main/CHANGELOG.md
13
+ Project-URL: AttackMap core, https://github.com/mlaify/AttackMap
14
+ Keywords: security,static-analysis,appsec,defensive-security,attackmap,attackmap-plugin
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Information Technology
18
+ Classifier: Intended Audience :: System Administrators
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Topic :: Security
26
+ Classifier: Topic :: Software Development :: Quality Assurance
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.11
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: pydantic>=2.7.0
32
+ Provides-Extra: core
33
+ Requires-Dist: attackmap>=0.6.0; extra == "core"
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
36
+ Requires-Dist: build>=1.2.0; extra == "dev"
37
+ Requires-Dist: attackmap>=0.6.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # attackmap-analyzer-java-spring
41
+
42
+ > [!IMPORTANT]
43
+ > **Active development, slow pace.** AttackMap is under active development, but
44
+ > progress may be slow until more contributors or co-maintainers join. Help is
45
+ > very welcome with the core engine, an analyzer, the macOS app, or the docs —
46
+ > see [CONTRIBUTING.md](CONTRIBUTING.md) or open an issue on
47
+ > [mlaify/AttackMap](https://github.com/mlaify/AttackMap/issues) to say hello.
48
+ > Security reports are still welcome at [security@mlaify.io](mailto:security@mlaify.io).
49
+
50
+ Java and Kotlin Spring Boot ecosystem analyzer for [AttackMap](https://github.com/mlaify/AttackMap).
51
+
52
+ This analyzer extracts structured signals from Maven and Gradle projects:
53
+
54
+ - **Web frameworks** — Spring MVC / Spring Boot (annotation routing with class-level `@RequestMapping` prefix joining), Spring WebFlux / WebMvc.fn functional endpoints (`RouterFunctions`, the `route()` builder, Kotlin `router {}` / `coRouter {}`), JAX-RS / Jersey / Quarkus (`@Path` + `@GET`/`@POST`), Ktor (Kotlin DSL), Javalin, Micronaut
55
+ - **Route auth** — Spring Security `authorizeHttpRequests` / `authorizeRequests` / `authorizeExchange` rules and method security (`@PreAuthorize`, `@Secured`, `@RolesAllowed`) resolved per route into `Route.auth` / `guards` / `guard_evidence`
56
+ - **Databases** — Spring Data JPA (`@Entity`, `JpaRepository`), Spring Data MongoDB (`@Document`, `MongoRepository`), Spring Data Redis (`RedisTemplate`), JDBC (`DriverManager.getConnection` with driver-aware kind inference), Hibernate, jOOQ, AWS SDK (S3, DynamoDB)
57
+ - **Auth packages** — Spring Security (`@PreAuthorize`, `@Secured`, `SecurityFilterChain`, `@EnableWebSecurity`), jjwt / nimbus-jose-jwt, BCrypt / Argon2 / SCrypt password encoders, OAuth2 (`oauth2Login`, `OAuth2AuthenticationToken`)
58
+ - **HTTP clients (external calls)** — RestTemplate, WebClient, java.net.http.HttpClient, OkHttpClient, `@FeignClient`, Apache HttpClient
59
+ - **Secrets** — `System.getenv`, `@Value("${...}")`, `Environment.getProperty(...)`
60
+ - **Service hints** — `<artifactId>` from `pom.xml`, `rootProject.name` from Gradle settings, `spring.application.name` from `application.properties`/`application.yml`
61
+
62
+ All emissions populate AttackMap's Signal v2 fields (line numbers, evidence snippets, confidence scores) so downstream insights can cite `path/to/file.java:NN`.
63
+
64
+ ## Install
65
+
66
+ ```bash
67
+ uv tool install attackmap --with attackmap-analyzer-java-spring \
68
+ --index mlaify=https://pkg.mlaify.io/pypi/simple/ --index-strategy first-index
69
+ # or from source:
70
+ pip install git+https://github.com/mlaify/attackmap-analyzer-java-spring.git
71
+ ```
72
+
73
+ The analyzer is auto-discovered by AttackMap via the `attackmap.analyzers` entry-point group.
74
+
75
+ ## Usage with AttackMap
76
+
77
+ ```bash
78
+ # Auto-discovered when installed:
79
+ attackmap analyze /path/to/spring/repo
80
+
81
+ # Or invoke explicitly:
82
+ attackmap analyze /path/to/spring/repo --module java-spring
83
+ ```
84
+
85
+ ## Detection
86
+
87
+ `detect()` returns true when any of the following are present, ignoring `target/`, `build/`, `.gradle/`, `.mvn/`, `.idea/`, `.git/`, `out/`, `bin/`, and `node_modules/`:
88
+
89
+ - `pom.xml`, `build.gradle`, `build.gradle.kts`, `settings.gradle`, or `settings.gradle.kts` at the root
90
+ - `.java`, `.kt`, or `.kts` files anywhere in the tree
91
+
92
+ ## Coverage notes
93
+
94
+ - **Class-level `@RequestMapping` prefix joining**: a class annotated with `@RequestMapping("/api/users")` causes its method-level `@GetMapping("/{id}")` to emit as `/api/users/{id}`. Multiple classes in one file are tracked correctly — the prefix in effect is whichever class declaration most recently preceded the method annotation.
95
+ - **`@PostMapping` with no value** (e.g. `@PostMapping public Object create()`) is **not currently extracted** — the regex requires a string argument. Workaround: write `@PostMapping("")` or `@PostMapping("/")`. Roadmap.
96
+ - **JAX-RS class + method `@Path` joining**: each class's own `@Path` is the prefix for the methods in its body, and a verb (`@GET`, `@POST`, etc.) pairs only with the `@Path` among the annotations on the same method, so a neighbouring method's path is never borrowed.
97
+ - **Functional endpoints**: `GET("/x")`-style predicates and builder calls are read only in files that use `org.springframework.web.reactive.function.server`, `org.springframework.web.servlet.function`, `RouterFunctions` or `RequestPredicates`. `nest(path("/api"), ...)`, `.andNest(...)`, builder `.path("/api", b -> ...)` / `.nest(path(...), b -> ...)` and Kotlin `"/api".nest {}` / `path("/api").nest {}` add their prefix. A path that isn't a string literal (a constant, a Kotlin `$template`), and every route inside a nest whose prefix can't be read, is skipped rather than reported under a wrong path. `GET(handler)` with no path and `route(path("/x").and(method(...)), h)` are not read.
98
+ - **Spring Security rules → route auth**: the matchers of `authorizeHttpRequests` / `authorizeRequests` / `authorizeExchange` (lambda, pre-lambda `.and()` chain and Kotlin `authorize(...)` DSL; `requestMatchers` / `antMatchers` / `mvcMatchers` / `pathMatchers` with an optional `HttpMethod`, `anyRequest()` / `anyExchange()`, `web.ignoring()`) are applied to Spring, JAX-RS and functional routes in first-match order with Ant/PathPattern matching (`/**`, `/*`, `?`, `{var}`, `{*var}`). `permitAll()` / `anonymous()` give `auth = "anonymous"`; `authenticated()`, `hasRole(..)`, `hasAuthority(..)`, `denyAll()` and readable `access(..)` give `"required"` with the rule as the guard. A matcher that can't be read (a constant, `regexMatchers`, a loop over configured URLs) before the deciding rule leaves the route `"unknown"` unless it agrees. Several chains must agree unless a `securityMatcher` or the config's package picks one; a chain applies only to routes in its own Maven/Gradle module (or, for a module without its own chain, a route-less shared security module); configs under `test/` directories are ignored. The filter chain runs first, so method security can turn a `permitAll()` route into `"required"` but never opens a route the chain protects. `csrf().disable()` is reported by AttackMap core's web-hardening pass, not by this plugin.
99
+ - **When a route is never `required`** (the dangerous direction, since core then skips it):
100
+ - a multi-segment route wildcard (`/files/**`, `{*rest}`) is only fully covered by a pattern `**`;
101
+ - a pattern without a leading `/` is unreadable (Ant never matches it), and `/admin/` doesn't cover `/admin`;
102
+ - **trailing slash**: Spring MVC 5 / Boot 2 routes `POST /admin/` to `/admin`, and an exact Ant pattern (`antMatchers`, `requestMatchers`, the Kotlin DSL, `antMatcher(..)`) doesn't match it. A `required` route must stay `required` for that form too, or it becomes `unknown`. This is skipped only when the module is on Spring Boot 3+ (build file) or imports `jakarta.servlet`, and `setUseTrailingSlashMatch(true)` isn't set. `mvcMatchers`, `mvc.pattern(..)` and WebFlux `pathMatchers` cover the trailing slash. JAX-RS routes always get the check;
103
+ - **HEAD**: a `GET` route must also be `required` for `HEAD`, because Spring MVC runs the GET handler for HEAD and a `HttpMethod.GET` rule doesn't cover it;
104
+ - the guiding rule: when an input the decision depends on can't be read with confidence, the answer is `unknown`;
105
+ - `hasRole` / `hasAnyRole` / `hasAuthority` need string-literal arguments. Same-repo string constants resolve (#11): `static final String NAME = "...";` and Kotlin `const val`, referenced as `Class.NAME` (or fully qualified), also inside `+` concatenations such as `"hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")"`. Every member declaration of every class, interface (fields implicitly static final), enum, record and Kotlin object or companion object is recorded. A key resolves only when all its declarations in the repo are String constants with the same plain-literal value. Any other declaration poisons it: non-final or non-String, no literal initializer, a text block or raw string, an enum constant, a `val`/`var`, or a same-named class elsewhere declaring it differently. Hitting a size cap makes every lookup fail. Unqualified names and constants declared only under `test/` stay unresolved. All of these give `unknown`. An `ANONYMOUS` authority gives `anonymous`. SpEL is read only as plain terms (`hasRole('A')`, `isAuthenticated()`, `permitAll`) joined by `and` / `or`, and `or` gives `required` only if every branch does. `==`, `eq`, `!`, `not`, ternaries, `#param`, `@bean` and grouping give `unknown`. The same applies to `@PreAuthorize` (one string literal, not a concatenation), `@Secured` and `@RolesAllowed`;
106
+ - a `securityMatchers(m -> ...)` lambda that names a method is an unreadable scope. Each request form (plain, trailing slash, HEAD) re-selects its chain by `securityMatcher`;
107
+ - the nearest build file that declares a Spring Boot version decides Boot 2 vs 3, so a module's own Boot 2 wins over the root's Boot 3. Without one, a main-source `import jakarta.servlet...` line counts as Spring 6. Spring 6.2's `UrlHandlerFilter` re-enables the trailing-slash check, like `setUseTrailingSlashMatch(true)`;
108
+ - `spring.mvc.servlet.path` below `/`, in application properties or YAML (nested keys followed by indentation) or as an unreadable `${..}` value, makes the module's Spring and functional routes `unknown`: Ant matchers then see the servlet path in front of the route. The same applies in code: `addPathPrefix(..)` with a non-root or unreadable prefix (predicates aren't read, so it covers the whole module), or the DispatcherServlet registered on a sub-path (`DispatcherServletRegistrationBean`, or a `ServletRegistrationBean` of the dispatcher servlet; other servlets such as an H2 console don't count). A non-root Jersey `@ApplicationPath` or `spring.jersey.application-path` does the same for JAX-RS routes. `server.servlet.context-path` is harmless, because matchers and routes both exclude it;
109
+ - method security counts only when switched on in the route's module or a shared route-less module. `@PreAuthorize` needs `@EnableMethodSecurity` / `@EnableReactiveMethodSecurity` / `@EnableGlobalMethodSecurity(prePostEnabled = true)`. `@Secured` needs `securedEnabled = true`. `@RolesAllowed` / `@DenyAll` / `@PermitAll` need `jsr250Enabled = true`, or, for JAX-RS, Jersey's `RolesAllowedDynamicFeature` / Quarkus security. `@PostAuthorize` runs after the handler and is never a guard, and `@Secured("ROLE_ANONYMOUS")` / `@PreAuthorize("isAnonymous() or ...")` aren't guards either;
110
+ - several handlers on one route key (`params=` / `headers=` variants) count as the least restrictive of them.
111
+ - **Cost**: per-file parsing is linear and capped (rules, chains, calls, pattern size). Applying rules to routes costs routes × chains × rules × entries, so it shares a per-repo budget of 5,000,000 cost units. Each matcher entry costs 20, each path match the size of its segment table, and each glob comparison pattern × text characters. A pattern segment with more than 8 wildcards is unreadable. Routes left when it runs out keep their chain answer `unknown`. Not covered: Spring < 5.3 suffix-pattern matching (`/admin.json`) and `@Order` between chains.
112
+ - **Kotlin Ktor**: `routing { get("/x") { ... } }` extraction only fires when the file contains an `io.ktor` import or `ktor.server.routing` reference, to avoid mis-attributing `get(...)` calls on Maps and other types.
113
+ - **Javalin** and **Micronaut** are similarly framework-gated.
114
+ - **OkHttp / java.net.http.HttpClient**: literal-URL builder patterns (`new Request.Builder().url("https://...")`, `HttpRequest.newBuilder(URI.create("https://..."))`) are picked up. Calls where the URL is built by string concatenation are not.
115
+
116
+ ## License
117
+
118
+ MIT
@@ -0,0 +1,12 @@
1
+ attackmap_analyzer_java_spring/__init__.py,sha256=KJSALbhfbFgJgkYbbL-zz3W4PSzUjP-s-NT7j88F8nY,75
2
+ attackmap_analyzer_java_spring/analyzer.py,sha256=prMgMA2iPDjpD8fD8VdcU1L3aE2CbiOjLKVd7Zjzyr0,55327
3
+ attackmap_analyzer_java_spring/annotations.py,sha256=D9XnsTFd_R7i-G39ORA7qvLPXJpSbZiR6mAhD-aJylo,15491
4
+ attackmap_analyzer_java_spring/constants.py,sha256=7l5nRaukw2e2VnUx-BY4EIqXCNuWoTV0MmyiMOaleXw,11389
5
+ attackmap_analyzer_java_spring/functional.py,sha256=MAvZ9SL37jVLvpr5tY93Uzc43spn5Ojg-dz2XbDDlDM,6306
6
+ attackmap_analyzer_java_spring/security_dsl.py,sha256=bmV8Spvi0li0i2oo0e7Psm-GMAokVsYU0Rstbnn9SgQ,43904
7
+ attackmap_analyzer_java_spring-0.2.0.dist-info/licenses/LICENSE,sha256=vtPQVGUyxq359j0JmD3_eJaXyHmaHyjzaMOtaLwJc88,1097
8
+ attackmap_analyzer_java_spring-0.2.0.dist-info/METADATA,sha256=o9C3747EBJcxNAwdEYNxyN0famRLS0ibpWTGwj1o234,13633
9
+ attackmap_analyzer_java_spring-0.2.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
10
+ attackmap_analyzer_java_spring-0.2.0.dist-info/entry_points.txt,sha256=VZO4542hocH02OvgISydT4zRunx6lkBv5d6LYwlCVqU,86
11
+ attackmap_analyzer_java_spring-0.2.0.dist-info/top_level.txt,sha256=JEj3pI66-dq9VrWTz0ESh7uwuOyHt92AyMwQdaQ6NoI,31
12
+ attackmap_analyzer_java_spring-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [attackmap.analyzers]
2
+ java_spring = attackmap_analyzer_java_spring:JavaSpringAnalyzer
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthew Davis and AttackMap Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ attackmap_analyzer_java_spring