{"record":{"id":"1ac663ecc5426363","repo":"apache/hadoop","slug":"null-or-empty-string-to-sign","errorCode":null,"errorMessage":"NULL or empty string to sign","messagePattern":"NULL or empty string to sign","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/Signer.java","lineNumber":56,"sourceCode":"   * @param secretProvider The SignerSecretProvider to use\n   */\n  public Signer(SignerSecretProvider secretProvider) {\n    if (secretProvider == null) {\n      throw new IllegalArgumentException(\"secretProvider cannot be NULL\");\n    }\n    this.secretProvider = secretProvider;\n  }\n\n  /**\n   * Returns a signed string.\n   *\n   * @param str string to sign.\n   *\n   * @return the signed string.\n   */\n  public synchronized String sign(String str) {\n    if (str == null || str.length() == 0) {\n      throw new IllegalArgumentException(\"NULL or empty string to sign\");\n    }\n    byte[] secret = secretProvider.getCurrentSecret();\n    String signature = computeSignature(secret, str);\n    return str + SIGNATURE + signature;\n  }\n\n  /**\n   * Verifies a signed string and extracts the original string.\n   *\n   * @param signedStr the signed string to verify and extract.\n   *\n   * @return the extracted original string.\n   *\n   * @throws SignerException thrown if the given string is not a signed string or if the signature is invalid.\n   */\n  public String verifyAndExtract(String signedStr) throws SignerException {\n    int index = signedStr.lastIndexOf(SIGNATURE);\n    if (index == -1) {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/Signer.java#L38-L74","documentation":"Signer.sign() appends an HMAC-SHA256 signature to a string (typically the authentication token destined for a cookie). An empty signature input is meaningless and hides bugs, so null or zero-length input throws IllegalArgumentException('NULL or empty string to sign') before any crypto runs.","triggerScenarios":"Calling signer.sign(str) where str is null or '' — e.g. building an authentication cookie before the token's toString() produced content, or passing an unset principal.","commonSituations":"Filter code signing a token whose fields were never populated; refactors that reorder token construction and signing; NPE-avoidance 'null passed through' chains ending at sign().","solutions":["Populate the AuthToken/AuthenticationToken (user, principal, type, expiry) before signing its string form","Add a guard at the call site for null/empty and treat it as a programming error","Review the code path that produced the empty string (usually an upstream setter was skipped)"],"exampleFix":"// before\ncookie.setValue(signer.sign(token.toString())); // token.toString() may be empty\n\n// after\nString raw = token.toString();\nif (raw == null || raw.isEmpty()) {\n  throw new IllegalStateException(\"token serialized to empty string\");\n}\ncookie.setValue(signer.sign(raw));","handlingStrategy":"validation","validationCode":"if (str == null || str.isEmpty()) throw new IllegalArgumentException(\"nothing to sign: check upstream token construction\");","typeGuard":null,"tryCatchPattern":"fail fast is intended — catch only to convert into a clearer application-specific error at the filter boundary","preventionTips":["Assert the payload is non-empty before signing","Build tokens fully (user/principal/type/expiry) before toString/sign","Treat empty signing input as a bug, not a runtime condition to handle"],"tags":["hadoop-auth","signing","validation"],"backgroundTag":"empty-input-validation","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}