BootUI
Try it
Setup
Features
Properties
AI agents
Ecosystem
GitHub
Try it
Setup
Features
Properties
AI agents
Ecosystem
GitHub
  • Get started

    • Try the sample app
    • Setup
    • Spring WebFlux
    • Quarkus
    • Activation and safety
    • Non-standard runtimes
    • Troubleshooting
  • Features

    • All features
    • Overview
    • Advisors
    • Runtime
    • Configuration
    • Database
    • Security
    • Services
    • Diagnostics
    • Developer tools
  • Reference

    • Properties
    • Framework support
    • AI agents
    • Command line
    • BootUI family
  • Diagnostic checks

    • Architecture
    • REST API
    • Spring
    • Hibernate
    • Database
    • Security
    • Vulnerabilities
    • Memory
    • Pentesting
    • GraalVM readiness
    • CRaC readiness
    • Quarkus
    • Quarkus security
  • Contributing

    • Repository
    • Specification
    • Implementation plan
    • Quarkus design notes
    • WebFlux design notes
  • Privacy

Quarkus checks

The Quarkus application advisor is the Quarkus flavor of the shared Spring panel: the panel ID remains spring, the endpoint remains /bootui/api/spring, and the shared SpringReport JSON and dismissal contract are unchanged. It is separate from the Quarkus Security advisor.

The advisor has 14 active rules. It inspects application-owned build metadata and selected configuration only when the user requests a scan. It never invokes application beans, constructs REST clients, executes scheduled work, reads JDBC data, intercepts traffic, or changes configuration. Findings are review prompts, not proof of a race, measured performance failure, or the configuration of an unseen deployment.

Reading more than the preview

The application advisor keeps its twenty-entry sampleViolations preview and full violationCount. View violations and GET <api>/spring/rules/{id}/violations?scanId=...&offset=0&limit=100 read bounded, sanitized details retained by the same scan without invoking application beans. Retention truncation is separate from evidence coverage; see snapshot, retention, and MCP/CLI retrieval.

Evidence and availability

Inspecting application metadata alone does not establish a passing check. Usable known-findings scores retain unrelated evidence gaps under the shared score eligibility policy.

CDI evidence comes from Arc's resolved application class beans, including effective scope and injection points, rather than counts of directly declared scope annotations. Application metadata is captured in non-production launch modes; the existing NORMAL production exclusion remains unchanged. Missing or unreadable metadata is unknown, not an empty, clean application.

Configuration analysis distinguishes active effective settings, framework defaults, and visible production declarations. Development mode builds with the development profile and never drains HTTP requests, so the compression and request-draining rules prefer a visible literal %prod. declaration over the active value and, like the other production rules, report incomplete coverage unless prod is the sole active profile. The native configuration machinery resolves active values and registered REST-client aliases. An inactive production profile is inspected only through already-loaded production declarations: BootUI does not load another profile's files, invent external environment values, resolve a production expression through development values, or switch the application's profiles. Multiple active profiles are not treated as proof of a future production deployment.

Production declarations can produce useful findings while coverage remains incomplete. PARTIAL reports retain those findings and explain unavailable evidence in analysisErrors; ERROR means no applicable evidence could be inspected. Skipped/unknown checks are not counted as successfully evaluated. Dismissing a finding does not remove coverage errors or turn an incomplete scan into a complete one. Retired rule IDs are never reused, and existing dismissals of surviving IDs still apply.

Bounds

  • Configuration name discovery considers at most 4,096 source names, plus an overflow sentinel, across at most 128 existing sources. Original profile prefixes are preserved.
  • Production declaration projection reuses those sources and retains at most 4,096 declarations; it discovers no new sources.
  • Build metadata considers at most 10,000 application classes/beans and 100,000 members.
  • At most 256 registered REST clients are inspected.
  • Each rule shows at most 20 deterministic samples; occurrence totals are independent of the display limit.

A reached bound or failed conversion is reported explicitly. Unrelated collected findings remain available. These are cardinality bounds, not a guarantee that arbitrary third-party configuration-source code can be interrupted. Raw URLs, credentials, unrecognized configuration values, and exception messages are not exposed.

Filter the list, then jump to a check — the detail below narrows to match.

    CDI

    QA-CDI-004 - Public field on a normal-scoped bean

    MEDIUM. A resolved application class bean whose effective scope is a normal scope — @ApplicationScoped, @RequestScoped, @SessionScoped or a custom normal scope, including scopes assigned by stereotypes and Quarkus REST's automatic @RequestScoped for resources with REST parameter fields — declares or inherits a non-static public field that is not an injection point or a REST parameter/@Context field.

    CDI 4.1 §3.1 makes such a field a definition error; ArC's default mode does not enforce it. Every injection point of a normal-scoped bean receives one shared client proxy, a generated subclass with its own copy of every field, and the proxy delegates methods only. Reading or writing the field through an injected reference therefore works on the proxy, not on the current contextual instance; for request or session scope, a value written that way can be seen by other requests. The Quarkus CDI guide states this directly: never read or write a field of a normal-scoped bean. The finding is conditional: field accesses are not observed, and this.field inside the bean reaches the contextual instance.

    Make the field private and access the state through methods. Package-private visibility still permits direct proxy field access from the same package. Final atomics and concurrent collections are not exempt here, because the proxy holds a second object. To limit noise, final primitives and immutable value types (String, boxed numbers, java.time, BigDecimal, UUID) remain excluded, although a constructor-assigned value can still differ on the proxy.

    QA-CDI-002 - Public state on a singleton REST resource

    MEDIUM. An actual application REST resource resolved as @Singleton — the Quarkus REST default — exposes a public, potentially mutable instance field that is not injected. Singletons have no client proxy, so the field is shared by concurrent requests. Final immutable values, atomics and concurrent collections are excluded; REST parameter and @Context fields are excluded. Normal-scoped resources are reported once under QA-CDI-004 instead, and the resource-specific rule does not also charge the same field under QA-CDI-003.

    Keep request-specific data in method-local variables or parameters, and expose shared state only as an immutable value or an encapsulated operation. This is not a claim that concurrent mutation was observed.

    QA-CDI-003 - Public mutable state on a singleton bean

    LOW. A resolved @Singleton application class bean, including a scope assigned by the framework, exposes a public, potentially mutable instance field that is not an injection point. CDI allows public fields on this pseudo-scope. Public final immutable values, atomics and concurrent collections are excluded. Scope annotations on a producer class do not establish the scope of the object returned by a producer.

    Review whether the field should expose an immutable value or an encapsulated operation. final does not make an object deeply immutable. Do not move the field to a normal scope such as request scope: that turns it into a QA-CDI-004 client-proxy defect.

    CDI sources: Jakarta CDI 4.1 managed beans, Quarkus client proxies, ArC client proxy generation, ArC maintainer on proxy field access, Arc effective scope resolution, implicit qualifier-field injection, and Quarkus REST scope handling.

    Configuration and production declarations

    QA-CFG-002 - Production SQL logging

    MEDIUM. Observed production configuration enables Hibernate SQL logging on a default or named persistence unit. Review production log volume and the sensitivity of SQL text. SQL logging does not automatically enable bind-parameter logging, which has separate settings; SQL literals may nevertheless contain application data.

    QA-CFG-003 - Verbose production root logging

    MEDIUM. The observed production root log level is DEBUG, TRACE, or ALL. Review whether that verbosity is intended for the deployment; INFO or WARN is often a more appropriate baseline. BootUI does not infer a measured slowdown or an actual secret disclosure from the level alone.

    QA-CFG-004 - Deprecated Hibernate schema property

    LOW. A configured default/named/profile variant of the quarkus.hibernate-orm.database.generation group, deprecated for removal since Quarkus 3.22, is declared: database.generation, database.generation.create-schemas or database.generation.halt-on-error. One finding is reported per persistence unit and profile prefix, however many legacy keys it declares. Migrate each key to its replacement — schema-management.strategy, schema-management.create-schemas and schema-management.halt-on-error — preserving the intended value. A property name merely supplied by framework defaults or an empty value is not enough to trigger this rule.

    On Quarkus 3.33.3.1, an explicitly configured legacy property takes precedence over the new property. Remove or migrate the old declaration rather than assuming a new schema-management.strategy=none has overridden it.

    QA-CFG-005 - Production bind-parameter logging

    HIGH. Hibernate ORM is present and the production view of quarkus.hibernate-orm.log.bind-parameters or its deprecated alias quarkus.hibernate-orm.log.bind-param is true. Quarkus ORs both global flags and forces the org.hibernate.orm.jdbc.bind logger to TRACE, so every bound value — personal data, credentials or tokens — can be written to the logs. There is no per-persistence-unit key; a quoted unit variant is ignored.

    The setting is fixed at build time, so the production view is built from declarations a production build packages: a visible %prod. declaration, or an unqualified declaration in a base application.properties/application.yaml file, resolved with Quarkus' own profile and source-ordinal precedence. Profile-aware files such as application-dev.properties, system properties and environment variables of the development run are not production evidence. When prod is the sole active profile, the rule defers to the Hibernate advisor's HIB-CONFIG-018, which reads the effective logger, so one setting is not charged twice. Build-time overrides of a future packaging step are not observed, so the rule always reports incomplete coverage in development mode.

    Remove the production declaration and enable bind logging only temporarily outside production.

    QA-PROD-002 - Production schema creation, alteration or dropping

    CRITICAL for drop or drop-and-create; HIGH for create or update. The rule distinguishes the actual schema actions and includes named persistence units.

    Quarkus sends this value through the Jakarta schema-action setting. Its create means create-only, not Hibernate's legacy hibernate.hbm2ddl.auto=create, which drops before recreating. create and update can still perform unreviewed production DDL, but are not described as guaranteed deletion of existing data. none and validate do not trigger this rule. Unknown spellings are not silently normalized into a destructive action.

    Prefer reviewed migrations or the deployment's existing schema-management process. The advisor does not require that migration tooling run inside the application.

    QA-PROD-003 - Observed in-memory production datasource

    MEDIUM. A supported JDBC URL explicitly selects in-memory storage. H2, HSQLDB or Derby database kind alone is not evidence of volatile storage: file-backed and server-backed databases are valid. URL matching uses storage-mode forms, not an incidental mem substring elsewhere in the URL.

    Confirm that the data is intentionally transient, or select durable storage. An in-memory database exposed by a database server can be shared across application instances; its durability follows that database process, not necessarily the application process. The raw JDBC URL is never included in the report.

    Sources: profile and source precedence, Quarkus schema-action wiring and legacy precedence, Hibernate create-only distinction, separate bind logging, H2 storage modes, deprecated database.generation group, and build-time bind-parameter logging.

    HTTP and clients

    QA-WEB-001 - Application HTTP compression disabled

    INFO. Compression is disabled by the framework default. An explicit quarkus.http.enable-compression=false records a deliberate decision, for example edge compression, and suppresses this prompt, as SPRING-WEB-001 does on Spring. The setting is fixed at build time, so in development mode a visible %prod. declaration is preferred and labelled as such. Enabling compression may help suitable payloads, but is not universally necessary. Upstream compression, client negotiation, response media types and workload are not inspected.

    QA-WEB-002 - Explicit zero shutdown timeout

    LOW. quarkus.shutdown.timeout=0 disables HTTP request-draining grace; zero does not mean waiting without limit. Set a positive duration, for example 10s, if requests should be allowed to finish. Removing the override is not equivalent: the framework default also leaves draining disabled, which is why the behaviourally identical default is only the INFO prompt QA-WEB-004. This does not promise completion of every scheduled or messaging operation.

    QA-WEB-003 - Managed REST-client timer disabled

    MEDIUM. A registered client's effective connect or read timer is zero. The native Quarkus configuration interceptors resolve quoted FQCN, configKey, MicroProfile /mp-rest/ aliases, profiles and configuration-source priority. Client-specific values override the global fallback as the framework specifies; properties for unrelated/unregistered clients do not trigger findings.

    The standard defaults are 15s connect / 30s read. A positive finite timeout, including one above five minutes, is not automatically unsafe. Zero disables the corresponding standard-transport timer, not necessarily every other deadline. In particular, a read timer is not a universal total-operation deadline. Review whether that disabled timer is intentional, or configure an appropriate positive duration in milliseconds. Arbitrary programmatic/custom client settings are not inferred. Quarkus REST Client registrations are supported; an installed Classic REST client extension produces incomplete coverage, not a claim that no clients exist.

    QA-WEB-004 - HTTP request draining not configured

    INFO. The shutdown timeout is known to be absent. Quarkus request-draining grace is opt-in, so configure a positive quarkus.shutdown.timeout if required. Development mode never drains, even with a positive timeout, so a visible %prod.quarkus.shutdown.timeout declaration is preferred over the active value for both shutdown rules, and both report incomplete production coverage unless prod is the sole active profile. This rule is mutually exclusive with QA-WEB-002. An unreadable duration is an analysis error, not an absent value.

    Sources: compression default, shutdown default, client defaults, native aliases and priority handling, and zero connect-timer semantics.

    Virtual threads

    QA-PERF-002 - Potential synchronized virtual-thread pinning

    LOW. On the running JDK 21-23, an identified Quarkus REST virtual-thread entry implementation is also declared synchronized. The native-resolved implementation, not a superclass/interface declaration supplying REST annotations, determines this flag. Review blocking work performed while holding the monitor; declaration metadata alone does not establish that blocking occurs.

    The rule does not treat every helper in an annotated class as a virtual-thread entry point and does not double-count a method annotated at both class and method level. Method-body synchronized blocks and unmodeled scheduler/messaging invocation paths are outside its evidence. JEP 491 removes synchronized-related pinning from JDK 24 onward, so this rule does not fire there. The build JDK is not used as a substitute for the running JDK.

    Sources: Quarkus dispatch decisions, framework-interpreted annotation contract, and Quarkus virtual-thread guide.

    Complete audit disposition

    All 19 original IDs are accounted for. The table records the first audit; see the second audit below. Retired IDs remain reserved so stored dismissals cannot later target an unrelated rule.

    RuleDispositionReason
    QA-CDI-001UpdatedResolved application scope/injection; public-state-only LOW review, no private-field race claim.
    QA-CDI-002UpdatedActual shared REST resources and injection/scope handling; no duplicate general-CDI charge.
    QA-CDI-003UpdatedResolved singleton scope; same narrowed public-state policy.
    QA-CFG-001RetiredConfigMapping is recommended, not mandatory; no custom configuration and programmatic access are valid.
    QA-CFG-002UpdatedProduction/named-unit evidence; SQL text and bind logging distinguished.
    QA-CFG-003UpdatedProduction provenance and unavailable coverage made explicit.
    QA-CFG-004RetainedValid deprecation advice; actual declarations and legacy precedence handled correctly.
    QA-RX-001RetiredJDBC capability plus reactive signatures does not prove an event-loop call; Mutiny offloading is legitimate.
    QA-SCH-001RetiredLocal/per-replica jobs are legitimate; no topology or once-per-cluster intent is observed.
    QA-PROD-001RetiredRUN can use profile prod with Dev Services; the declaration need not be useless.
    QA-PROD-002UpdatedQuarkus create-only semantics, legacy precedence, named units and explicit coverage.
    QA-PROD-003UpdatedRequire observed in-memory URL mode, not database vendor.
    QA-PROF-001RetiredMissing %prod keys do not establish missing production configuration.
    QA-DB-001RetiredThe finite default maximum is 50; workload/database sizing cannot be inferred from omission.
    QA-WEB-001UpdatedDistinguish disabled/default/unknown; compression remains a conditional optimization.
    QA-WEB-002UpdatedPositive-duration remediation; removing zero does not enable draining.
    QA-WEB-003UpdatedEffective registered-client timers; zero only, no arbitrary finite ceiling.
    QA-WEB-004RetainedValid opt-in default information, only when absence is known.
    QA-PERF-002UpdatedActual REST entry points and running JDK; conditional LOW risk, not observed HIGH pinning.

    Retirement sources: supported configuration APIs, Mutiny offloading, local versus composite scheduling, launch modes, and Agroal default maximum.

    Second audit disposition

    A second audit re-checked every surviving rule against Quarkus 3.33.3.x sources and CDI 4.1. Twenty-one IDs are now accounted for: 14 active and 7 retired. Each added rule and severity change was reviewed independently by three models before implementation.

    RuleDispositionReason
    QA-CDI-001RetiredFramed as a concurrency review prompt, but the real defect on a normal scope is client-proxy field access. Replaced by QA-CDI-004 under a new ID so earlier dismissals of the LOW prompt do not hide the MEDIUM definition error.
    QA-CDI-002UpdatedNow singleton resources only; application- or request-scoped resources move to QA-CDI-004.
    QA-CDI-003UpdatedRecommendation no longer suggests request scope, which would create a QA-CDI-004 defect.
    QA-CDI-004AddedPublic fields on every normal scope, including request and session scope; atomics and concurrent collections are not exempt behind a proxy.
    QA-CFG-004UpdatedAlso detects the deprecated create-schemas and halt-on-error keys, names each replacement and reports once per unit.
    QA-CFG-005AddedBuild-time bind-parameter logging in the production view; complements HIB-CONFIG-018, which reads only an active production profile.
    QA-WEB-001UpdatedExplicit false suppresses the prompt; a visible %prod. declaration is preferred in development mode.
    QA-WEB-002UpdatedMEDIUM to LOW: an explicit zero behaves like the INFO default; visible %prod. declaration preferred.
    QA-WEB-004UpdatedFalse positive fixed: %prod.quarkus.shutdown.timeout was invisible to the development profile.
    OthersRetainedQA-CFG-002, QA-CFG-003, QA-PROD-002, QA-PROD-003, QA-WEB-003 and QA-PERF-002 were re-verified.

    Not added: a REST client without a URL (Quarkus already fails with a precise message on first use), a log category below quarkus.log.min-level and @RunOnVirtualThread on JDK 17 (Quarkus warns at startup), scheduled-job overlap (the default PROCEED policy is legitimate), and unqualified base-file declarations for the runtime production rules (development-only sources, Dev Services and launch overrides cannot be told apart reliably at runtime).

    The source audit targets Quarkus 3.33.3.1. Pinned supporting JDK, Hibernate, SmallRye and database references explain specific semantics; they do not claim every application uses the same dependency patch. Floating guides are reading aids, not stronger evidence than the version-pinned implementation.

Prev
CRaC readiness
Next
Quarkus security