Api Key Exposure in Spring Boot
How Api Key Exposure Manifests in Spring Boot
Api key exposure in Spring Boot applications typically occurs through several Spring Boot-specific patterns. The most common vulnerability arises from hardcoded API keys in configuration files, often found in application.properties or application.yml. Developers frequently commit these files to version control, exposing production credentials. For example:
# application.yml
api:
key: "sk-1234567890abcdef"
secret: "shhhhh-very-secret"
Another Spring Boot-specific pattern involves the use of @Value annotations to inject configuration properties. When these are hardcoded in controllers or services, they become vulnerable:
@RestController
@RequestMapping("/api")
public class PaymentController {
@Value("${api.key}")
private String apiKey; // Exposed if controller is logged or inspected
@PostMapping("/charge")
public ResponseEntity<ChargeResponse> charge(@RequestBody ChargeRequest request) {
// apiKey now in method scope and potentially exposed
return paymentService.charge(request, apiKey);
}
}
Spring Boot's Actuator endpoints can inadvertently expose API keys through the /env or /configprops endpoints when misconfigured. A common mistake is enabling these endpoints in production without proper authentication:
# application.yml
management:
endpoints:
web:
exposure:
include: "env,configprops,beans"
Spring Boot's default logging configuration can also leak API keys through stack traces or debug logs. When exceptions occur during API calls, the stack trace might include the key in the context:
@Service
public class ExternalApiService {
private final RestTemplate restTemplate;
public ExternalApiService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
public String callExternalApi(String endpoint) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + apiKey);
HttpEntity<String> entity = new HttpEntity<>("body", headers);
try {
return restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class).getBody();
} catch (RestClientException e) {
log.error("API call failed", e); // Stack trace may expose apiKey
throw e;
}
}
}
Spring Boot's configuration binding can also create exposure points when using @ConfigurationProperties without proper validation:
@Component
@ConfigurationProperties(prefix = "api")
@Validated
public class ApiProperties {
private String key; // No validation - could be empty or malformed
private String secret;
// getters and setters
}
Without validation, these properties might be bound to empty or default values that cause fallback to insecure behavior, or worse, expose default test keys that were never meant for production.
Spring Boot-Specific Detection
Detecting API key exposure in Spring Boot requires examining both the codebase and runtime configuration. Using middleBrick's API security scanner, you can identify these vulnerabilities without credentials or agents. The scanner examines your Spring Boot application's unauthenticated attack surface in 5-15 seconds.
For Spring Boot applications, middleBrick specifically looks for:
- Exposed Actuator endpoints that reveal configuration properties
- Hardcoded API keys in configuration files and source code
- Improper use of
@Valueannotations that inject secrets - Missing validation on
@ConfigurationPropertiesclasses - Debug logging that may expose keys in stack traces
Here's how to scan a Spring Boot API with middleBrick:
npm install -g middlebrick
middlebrick scan https://yourapi.com
The scanner will test for BOLA (Broken Object Level Authorization) vulnerabilities that might allow enumeration of API keys, and check if your Actuator endpoints are properly secured. For Spring Boot applications specifically, it examines:
{
"spring_boot_actuator_exposure": {
"status": "vulnerable",
"severity": "high",
"remediation": "Disable or secure Actuator endpoints in production. Use 'management.endpoints.web.exposure.include' to whitelist only necessary endpoints."
},
"configuration_properties_validation": {
"status": "missing",
"severity": "medium",
"remediation": "Add @Validated to @ConfigurationProperties classes and use @NotBlank, @Pattern for API keys."
}
}
For local development and CI/CD integration, you can use the middleBrick CLI to scan your Spring Boot application before deployment:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
run: |
npm install -g middlebrick
middlebrick scan https://staging.yourapp.com
middleBrick's LLM/AI security checks are particularly relevant for Spring Boot applications that integrate with AI services, as they can detect if your API keys for services like OpenAI or Anthropic are exposed through system prompt leakage or improper error handling.
Spring Boot-Specific Remediation
Remediating API key exposure in Spring Boot requires a multi-layered approach using Spring Boot's native security features. The most critical step is implementing proper configuration management with Spring Cloud Config or external secret management.
First, move all API keys out of application.yml and use environment variables or external secret stores:
# application.yml - no secrets here
api:
key: ${API_KEY:fallback-test-key}
secret: ${API_SECRET}
Then secure your Actuator endpoints to prevent configuration exposure:
# application.yml
management:
endpoints:
web:
exposure:
include: "health,info"
endpoint:
health:
show-details: "when-authorized"
env:
enabled: false
configprops:
enabled: false
spring:
security:
user:
name: "actuator"
password: "${ACTUATOR_PASSWORD:change-me}" # Never hardcode in production
For @ConfigurationProperties classes, add validation to prevent binding to empty or malformed keys:
@Component
@ConfigurationProperties(prefix = "api")
@Validated
public class ApiProperties {
@NotBlank(message = "API key must not be blank")
@Pattern(regexp = "^[a-zA-Z0-9\-_]{20,}$", message = "API key format invalid")
private String key;
@NotBlank(message = "API secret must not be blank")
private String secret;
// getters and setters
}
Implement proper logging configuration to prevent key leakage:
<!-- logback-spring.xml -->
<configuration>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<logger name="org.springframework.web" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
</configuration>
Use Spring Boot's built-in support for externalized configuration with Docker secrets or Kubernetes secrets:
# Dockerfile
FROM openjdk:17-jdk-slim
# Create non-root user
RUN addgroup --system appgroup && adduser --system --group appgroup appuser
WORKDIR /app
# Copy application JAR
COPY target/*.jar app.jar
# Switch to non-root user
USER appuser
# Run with environment variables from Docker secrets
CMD ["java", "-jar", "app.jar"]
For comprehensive protection, integrate middleBrick's continuous monitoring into your Spring Boot deployment pipeline. The Pro plan ($499/month) includes CI/CD gates that can automatically fail builds if API key exposure risks are detected:
# middlebrick.yml (for Pro plan continuous monitoring)
apis:
- name: "Payment API"
url: "https://api.yourservice.com"
scan_schedule: "every_6_hours"
fail_threshold: 70
alerts:
slack: "#security-alerts"
email: ["dev-security@company.com"]
This configuration ensures your Spring Boot APIs are continuously scanned for API key exposure and other security vulnerabilities, with immediate alerts when issues are detected.