Summary
The OpenAPI specification served at /api/openapi.json declares "security": [] globally with no securitySchemes defined in components. This documents all 689 endpoints as requiring no authentication, even though the server code enforces auth on the vast majority of them.
Steps to Reproduce
curl https://demo.dotcms.com/api/openapi.json | jq '.security, (.components.securitySchemes // "MISSING")'
- Observe: global
security is [], securitySchemes is absent
- Run any automated security scanner (OWASP ZAP, 42Crunch) against the spec — all endpoints flagged as unauthenticated
Impact
- Attacker reconnaissance: The full 689-endpoint attack surface appears open — reducing enumeration effort to zero
- Developer misuse: Consumers of the spec may omit auth headers assuming endpoints are intentionally public
- Security audit failures: Automated scanners generate false positives on every endpoint, burying real issues
- Spec ≠ reality divergence: Erodes trust in API documentation as a security contract
Code Verification
All of the following resources properly enforce rejectWhenNoUser(true) in WebResource.InitBuilder — but the spec doesn't reflect this:
| Resource |
Code Enforcement |
In Spec |
MaintenanceResource |
rejectWhenNoUser(true) + admin + MAINTENANCE portlet |
No auth declared |
RedisResource |
rejectWhenNoUser(true) + MAINTENANCE portlet |
No auth declared |
SystemTableResource |
rejectWhenNoUser(true) + CMS_ADMINISTRATOR_ROLE |
No auth declared |
ApiTokenResource |
rejectWhenNoUser(true) + users portlet |
No auth declared |
UserResource |
rejectWhenNoUser(true) |
No auth declared |
LicenseResource |
rejectWhenNoUser(true) + CONFIGURATION portlet |
No auth declared |
OSGIResource |
rejectWhenNoUser(true) + DYNAMIC_PLUGINS portlet |
No auth declared |
LoggerResource |
rejectWhenNoUser(true) + isAdmin() |
No auth declared |
AppsResource |
rejectWhenNoUser(true) |
No auth declared |
PermissionResource |
rejectWhenNoUser(true) + admin checks |
No auth declared |
Root Cause
The openapi.json generator does not emit a securitySchemes block and JAX-RS resource methods lack @SecurityRequirement annotations.
Proposed Fix
- Add
securitySchemes to components:
"securitySchemes": {
"Bearer": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" },
"BasicAuth": { "type": "http", "scheme": "basic" }
}
- Set a global default requiring auth:
"security": [{ "Bearer": [] }]
-
Override with "security": [] at the operation level only for genuinely public endpoints (health checks, SAML metadata, login).
-
Annotate JAX-RS resource methods with @SecurityRequirement so the spec stays accurate as new endpoints are added.
Acceptance Criteria
Summary
The OpenAPI specification served at
/api/openapi.jsondeclares"security": []globally with nosecuritySchemesdefined incomponents. This documents all 689 endpoints as requiring no authentication, even though the server code enforces auth on the vast majority of them.Steps to Reproduce
curl https://demo.dotcms.com/api/openapi.json | jq '.security, (.components.securitySchemes // "MISSING")'securityis[],securitySchemesis absentImpact
Code Verification
All of the following resources properly enforce
rejectWhenNoUser(true)inWebResource.InitBuilder— but the spec doesn't reflect this:MaintenanceResourcerejectWhenNoUser(true)+ admin + MAINTENANCE portletRedisResourcerejectWhenNoUser(true)+ MAINTENANCE portletSystemTableResourcerejectWhenNoUser(true)+ CMS_ADMINISTRATOR_ROLEApiTokenResourcerejectWhenNoUser(true)+ users portletUserResourcerejectWhenNoUser(true)LicenseResourcerejectWhenNoUser(true)+ CONFIGURATION portletOSGIResourcerejectWhenNoUser(true)+ DYNAMIC_PLUGINS portletLoggerResourcerejectWhenNoUser(true)+isAdmin()AppsResourcerejectWhenNoUser(true)PermissionResourcerejectWhenNoUser(true)+ admin checksRoot Cause
The
openapi.jsongenerator does not emit asecuritySchemesblock and JAX-RS resource methods lack@SecurityRequirementannotations.Proposed Fix
securitySchemestocomponents:Override with
"security": []at the operation level only for genuinely public endpoints (health checks, SAML metadata, login).Annotate JAX-RS resource methods with
@SecurityRequirementso the spec stays accurate as new endpoints are added.Acceptance Criteria
securitySchemesblock present incomponentswith Bearer JWT and BasicAuth schemessecuritydefaults to[{ "Bearer": [] }]security: []@SecurityRequirementannotations added to all JAX-RS resource classes