{"record":{"id":"9deb12341f94d5fa","repo":"pinpoint-apm/pinpoint","slug":"webhook-url-fragment-is-not-allowed","errorCode":null,"errorMessage":"Webhook URL fragment is not allowed","messagePattern":"Webhook URL fragment is not allowed","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"commons-server/src/main/java/com/navercorp/pinpoint/common/server/webhook/WebhookUrlValidator.java","lineNumber":129,"sourceCode":"\n        String normalizedScheme = scheme.toLowerCase(Locale.ROOT);\n        if (!\"http\".equals(normalizedScheme) && !\"https\".equals(normalizedScheme)) {\n            throw new IllegalArgumentException(\"Webhook URL scheme must be http or https\");\n        }\n    }\n\n    private static void validateAuthority(URI uri) {\n        if (uri.getHost() == null || uri.getHost().isBlank()) {\n            throw new IllegalArgumentException(\"Webhook URL host is required\");\n        }\n        if (isBlockedHostLiteral(uri.getHost())) {\n            throw new IllegalArgumentException(\"Webhook URL host is not allowed\");\n        }\n        if (uri.getRawUserInfo() != null) {\n            throw new IllegalArgumentException(\"Webhook URL user info is not allowed\");\n        }\n        if (uri.getRawFragment() != null) {\n            throw new IllegalArgumentException(\"Webhook URL fragment is not allowed\");\n        }\n        int port = uri.getPort();\n        if (port == -1 && hasExplicitPort(uri)) {\n            throw new IllegalArgumentException(\"Webhook URL port is not valid\");\n        }\n        if (port == 0 || port > MAX_PORT) {\n            throw new IllegalArgumentException(\"Webhook URL port is not allowed\");\n        }\n    }\n\n    private static boolean hasExplicitPort(URI uri) {\n        String rawAuthority = uri.getRawAuthority();\n        if (rawAuthority == null || rawAuthority.isEmpty()) {\n            return false;\n        }\n\n        int hostStartIndex = rawAuthority.lastIndexOf('@') + 1;\n        if (rawAuthority.charAt(hostStartIndex) == '[') {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/commons-server/src/main/java/com/navercorp/pinpoint/common/server/webhook/WebhookUrlValidator.java#L111-L147","documentation":"WebhookUrlValidator.validateAuthority throws IllegalArgumentException when the URL contains a fragment (rawFragment != null, the '#...' part). Fragments are client-side only and never sent to the server, so they are meaningless — and potentially misleading — in a webhook target URL.","triggerScenarios":"URLs like 'https://example.com/hook#section' or copied URLs that carried an anchor, passed to validateSyntax/uri.","commonSituations":"Copying a URL from a browser address bar or docs page that included an anchor link; templating mistakes appending '#...' placeholders.","solutions":["Strip the '#fragment' portion from the URL before validating/saving","If the fragment encoded meaningful routing info, move it into the path or query string"],"exampleFix":"// before\nvalidator.validateSyntax(\"https://example.com/webhook#setup\");\n// after\nvalidator.validateSyntax(\"https://example.com/webhook\");","handlingStrategy":"validation","validationCode":"int hash = url.indexOf('#'); if (hash >= 0) url = url.substring(0, hash);","typeGuard":"boolean hasNoFragment(java.net.URI uri) { return uri.getRawFragment() == null; }","tryCatchPattern":"try { WebhookUrlValidator.validateSyntax(url); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"fragment\")) { strip '#...' and retry; } }","preventionTips":["Strip anchors when copying URLs from browsers/docs","Don't encode routing metadata in fragments — use path or query params","Trim pasted URLs before saving"],"tags":["java","webhook","url","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}