Skip to content

fix: remove hardcoded JWT secret key and add startup validation (CWE-798)#63

Open
saaa99999999 wants to merge 1 commit into
Genc:masterfrom
saaa99999999:fix/hardcoded-jwt-secret
Open

fix: remove hardcoded JWT secret key and add startup validation (CWE-798)#63
saaa99999999 wants to merge 1 commit into
Genc:masterfrom
saaa99999999:fix/hardcoded-jwt-secret

Conversation

@saaa99999999
Copy link
Copy Markdown

Summary

application.yml:51 defines a hardcoded JWT signing secret secretKey: secret. This key is used to sign and verify all JWT tokens via HMAC-SHA256. Anyone who reads the public repository can forge valid authentication tokens for any user, achieving complete authentication bypass.

Data Flow

  1. src/main/resources/application.yml:51secretKey: secret — hardcoded signing key
  2. JwtProperties.java:17-18@ConfigurationProperties(prefix = "jwt") binds jwt.secretKey to the field
  3. JwtTokenManager.java:37 — Token signing:
    .sign(Algorithm.HMAC256(jwtProperties.getSecretKey().getBytes()));
  4. JwtTokenManager.java:73 — Token verification uses the same key:
    final JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(jwtProperties.getSecretKey().getBytes())).build();
  5. JwtAuthenticationFilter.java:50 — Filter extracts username from token
  6. JwtAuthenticationFilter.java:69 — Filter validates token against extracted username

The java-jwt library (com.auth0:java-jwt) uses HMAC-SHA256, meaning the same key signs and verifies tokens. With a known key "secret", forged tokens pass verification.

Fix

1. application.yml:48-58 — Remove hardcoded secret

Before:

## FIXME : Customize JWT token and Swagger information for your application
jwt:
  secretKey: secret
  issuer: www.farukgenc.com
  expirationMinute: 10

After:

## JWT Configuration
## Generate a strong secret key (at least 256 bits):
##   openssl rand -base64 32
## Set via environment variable: JWT_SECRETKEY=<your-generated-secret>
## Or replace the empty value below (NOT recommended -- prefer env vars)

jwt:
  secretKey:
  issuer: www.farukgenc.com
  expirationMinute: 10

The secretKey: with no value defaults to empty, causing startup failure unless the developer explicitly configures the key. Spring Boot's @ConfigurationProperties also supports environment variable override: JWT_SECRETKEY=<key>.

2. JwtProperties.java — Add startup validation

Before:

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
    private String issuer;
    private String secretKey;
    private long expirationMinute;
}

After:

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
    private String issuer;
    private String secretKey;
    private long expirationMinute;

    @PostConstruct
    public void validate() {
        if (secretKey == null || secretKey.isBlank()) {
            throw new IllegalStateException(
                "JWT secretKey is not configured. Set JWT_SECRETKEY environment variable or jwt.secretKey in application.yml. "
                + "Generate a strong key with: openssl rand -base64 32"
            );
        }
        if (secretKey.length() < 32) {
            throw new IllegalStateException(
                "JWT secretKey must be at least 32 characters for adequate security. Current length: " + secretKey.length()
            );
        }
    }
}

The @PostConstruct validation:

  • Rejects empty or blank secretKey (application exits with clear error at startup)
  • Enforces minimum 32-character key length
  • Guides the developer to generate a secure key via openssl rand -base64 32
  • Notes the environment variable name JWT_SECRETKEY for configuration

Impact

  • CWE-798: Use of Hard-coded Credentials
  • CVSS 3.1: 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)
  • The string secret is a single dictionary word and one of the most commonly used passwords. This is not a forgotten FIXME — it is an actively exploitable default.

…798)

Replace the hardcoded "secret" signing key with an empty placeholder and
add @PostConstruct validation that rejects empty, blank, or short secrets
at startup, requiring developers to explicitly configure a strong key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

@saaa99999999
Copy link
Copy Markdown
Author

CVE Request — Action Needed from Maintainer

This PR fixes security vulnerabilities. To assign a CVE number:

GitHub only issues CVEs from the official upstream repository, not from forks.

Please:

  1. Go to this repo → SecurityAdvisoriesNew draft security advisory
  2. Add @saaa99999999 as a collaborator
  3. I will populate the full vulnerability details (CVSS, CWE, data flow, PoC) and submit the CVE request

If you prefer, I can submit the CVE via MITRE (cveform.mitre.org) instead — just let me know.

Thank you for reviewing this PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant