When developing with Jsoup, developers must assume that all inputs, including HTML, XML, URLs, CSS selectors, and HTTP responses, are untrusted and potentially malicious. The library protects against standard parsing anomalies and provides robust safelist-based sanitization and request handling, but it does not protect against logic flaws, injection vulnerabilities, or resource exhaustion unless explicit safety rules and limits are enforced. Security-sensitive surfaces include dynamic query construction, connection parameter configuration, schema validation, and session management, where failures should always fail closed.
Essential implementation rules
Use correct attribute and selector API signatures
When setting attributes programmatically, use Attributes#put(key, value) rather than Attributes#add(key, value) to overwrite existing attributes and prevent duplicate attribute names that could cause parser discrepancies or security control bypasses. Choose standard constructors like new Attribute(key, value) for raw unencoded strings, and restrict Attribute.createFromEncoded(key, encodedValue) exclusively to cases where the attribute value is already HTML entity-encoded.
Authenticate connection sessions securely
Use Jsoup’s RequestAuthenticator interface to manage authentication credentials instead of manual headers. Inspect the challenge context using auth.isServer() and auth.isProxy(), and validate request hosts with auth.url().getHost() before returning credentials. Set authenticators directly on isolated Connection instances for each request execution to prevent cross-tenant credential leakage.
Prevent injection in CSS selectors and regex pseudo-selectors
Wrap dynamic strings in Pattern.quote(...) when building regex-based pseudo-selectors such as :matches(...) or :matchesOwn(...) with user input to prevent regex injection. When querying the DOM using Jsoup CSS selector methods such as select() or expectFirst(), meta-characters must be escaped or direct element access methods like getElementById() should be used.
Validate schemas, HTML fragments, and connection URLs
Validate DOM nodes against expected element schemas using elementIs(normalName, namespace) instead of raw string comparisons on tagName(). Validate untrusted HTML fragments against an explicit Safelist schema using Jsoup.isValid(), and normalize valid inputs using Jsoup.clean(). Verify that input connection strings start with absolute http:// or https:// schemes before calling Jsoup.connect().
Normalize and interpret inputs with appropriate parsers
Ensure XML input is parsed using Parser.xmlParser() rather than standard HTML parsing to prevent tag misinterpretation and structural corruption. Use Node.absUrl() for URL-valued attributes that may be relative to resolve against the base URI securely, and rely on native stream parsing APIs such as Jsoup.parse(InputStream, String, String) for entity-heavy inputs.
Control request methods, redirects, and proxy endpoints
Disable automatic redirect following using followRedirects(false) on sensitive POST or HEAD requests to prevent the automatic re-transmission of sensitive payloads across network boundaries. Enforce outbound traffic control and isolate session requests by configuring proxy parameters on reusable connection sessions using Jsoup.newSession() and invoking proxy().
Escape untrusted strings and serialize output safely
When outputting untrusted strings into HTML or attribute contexts, use Entities.escape(data, outputSettings) or Document.OutputSettings to encode characters such as <, >, &, ", and to prevent Cross-Site Scripting (XSS) and HTML markup injection vulnerabilities.
Enforce explicit resource limits on connections and parsers
Configure explicit response body limits using maxBodySize(int bytes) and timeout limits using timeout(int) when fetching content from untrusted network endpoints to prevent denial of service. When processing untrusted XML or HTML documents, configure explicit stack depth limits on the Parser instance using Parser#setMaxDepth(int) to prevent resource exhaustion from deeply nested tags.
Maintain thread safety and isolation for Safelists and sessions
Fully initialize Safelist instances prior to sharing or passing them to cleaner components, and use deep copy constructors to isolate concurrent modifications. Use Jsoup.newSession() when executing multi-step HTTP interactions to maintain path-scoped cookie contexts and state isolation.
jsoup: All Security Cards
Approximately 3,188 tokens
On this card
Category: api contract misuse
Use correct attribute and selector API signatures and prevent duplicate attributes
Use when
When programmatically setting attributes, querying text nodes, or instantiating attributes using Jsoup.
Secure rules
Rule 1: Use Attributes#put() instead of Attributes#add() to set attributes.
When setting attributes programmatically, use Attributes#put(key, value) rather than Attributes#add(key, value) to overwrite existing attributes and prevent duplicate attribute names that could cause parser discrepancies or security control bypasses.
element.attributes().put("href", sanitizedUrl);
Rule 2: Use Element#selectNodes() instead of the deprecated matchText selector.
Avoid using the deprecated :matchText pseudo-selector when querying text nodes since it mutates the underlying DOM tree. Instead, use Element#selectNodes() with node pseudo-selectors like ::text or ::textnode to query text nodes safely without unexpected side-effects.
Rule 3: Choose the correct Attribute constructor based on encoding state.
Use standard constructors like new Attribute(key, value) for raw unencoded strings, and restrict Attribute.createFromEncoded(key, encodedValue) exclusively to cases where the attribute value is already HTML entity-encoded to prevent unexpected unescaping.
Authenticate Requests Securely Using Jsoup Request Authenticators
Use when
When configuring HTTP or proxy authentication for Jsoup connection sessions and requests to verify identity and supply credentials.
Secure rules
Rule 1: Supply authentication credentials safely using RequestAuthenticator and validate request hosts to prevent credential leakage.
Use Jsoup’s RequestAuthenticator interface to manage authentication credentials instead of manual headers. Inspect the challenge context using auth.isServer() and auth.isProxy(), and validate request hosts with auth.url().getHost() before returning credentials.
Prevent Injection When Constructing Dynamic CSS Selectors and Query Parsers
Use when
Building dynamic CSS selector queries or regex pseudo-selectors using untrusted user input.
Secure rules
Rule 1: Escape special meta-characters or wrap dynamic strings using Pattern.quote when building regex-based pseudo-selectors.
Wrap dynamic strings in Pattern.quote(...) when building regex-based pseudo-selectors such as :matches(...) or :matchesOwn(...) with user input to prevent regex injection, parser crashes, or unexpected query alterations.
Rule 2: Avoid concatenating untrusted input into CSS selector queries and escape special meta-characters.
When querying the DOM using Jsoup CSS selector methods such as select() or expectFirst(), meta-characters including dots, hashes, slashes, and backslashes must be escaped using backslashes to prevent CSS selector injection.
String safeId = untrustedId.replaceAll("([.#/\\\\])", "\\\\$1");Element el = doc.expectFirst("#" + safeId);// Or use direct element access without CSS parser syntaxElement directEl = doc.getElementById(untrustedId);
Category: input contract definition
Validate Element Schemas and HTML Structure Against Defined Allowlist Contracts
Use when
When validating untrusted DOM nodes or HTML fragments against expected structure, namespaces, and safelist rules before processing or rendering.
Secure rules
Rule 1: Validate DOM element names and namespaces using elementIs instead of raw string comparisons.
When validating DOM nodes against expected element schemas or structural contracts, use elementIs(normalName, namespace) instead of checking element tag names using raw string comparisons on tagName(). This ensures that both normalized element tag names and explicit document namespaces are strictly validated according to the schema rules.
if (element.elementIs("a", Parser.NamespaceHtml)) { String href = element.attr("href");} else { throw new IllegalArgumentException("Unexpected element or namespace schema violation");}
Rule 2: Validate untrusted HTML fragments against an explicit Safelist schema before processing.
Use Jsoup.isValid(bodyHtml, safelist) to validate whether untrusted HTML fragments conform to the schema rules defined by a Safelist allowance structure. Ensure that input validated with isValid is still normalized using Jsoup.clean() prior to storage or rendering to enforce attributes and parse normalization.
Safelist schema = Safelist.relaxed();if (!Jsoup.isValid(userInput, schema)) { throw new IllegalArgumentException("Input HTML does not match the required schema rules.");}String safeHtml = Jsoup.clean(userInput, "https://example.com/", schema);
Validate connection URLs are absolute and use allowed schemes
Use when
When accepting external URL strings from users before passing them into Jsoup.connect().
Secure rules
Rule 1: Enforce absolute URLs with explicit http or https schemes before connection processing.
Verify that input strings start with the required scheme prefix before calling Jsoup.connect() to prevent malformed inputs or missing protocols from causing runtime exceptions or unexpected application failures.
Normalize and Interpret Untrusted Input via Jsoup Parsers and URL Resolution
Use when
When parsing untrusted HTML/XML streams, resolving relative URLs, or processing input attributes and character entities.
Secure rules
Rule 1: Ensure XML input is parsed using Parser.xmlParser() rather than standard HTML parsing.
Developers must ensure that XML input is parsed using Parser.xmlParser() rather than standard HTML parsing to prevent misinterpretation of tags, namespaces, or attribute names, avoiding silent mutations or structural corruption.
Use Node.absUrl() for URL-valued attributes that may be relative. It resolves the attribute against the node’s base URI, removes ASCII control characters during resolution, and returns an empty string when an absolute URL cannot be produced. Do not call StringUtil.resolve() directly because StringUtil is an internal API whose behavior may change without notice.
Document document = Jsoup.parse( "<a href=\"../resource\">Resource</a>", "https://example.com/path/");String absoluteUrl = document.selectFirst("a").absUrl("href");if (!absoluteUrl.isEmpty()) { // Process the resolved URL.}
Rule 3: Rely on Jsoup native stream parsing APIs for multibyte and entity-heavy inputs.
When parsing HTML streams that contain numerous HTML entity references across large inputs, rely directly on Jsoup’s native stream parsing APIs such as Jsoup.parse(InputStream, String, String) rather than manually pre-chunking or slicing input buffers.
Control Request Method Retention and Redirect Behavior
Use when
Making HTTP POST or HEAD requests where redirect semantics must be explicitly controlled to prevent automatic re-transmission of sensitive payloads across network boundaries.
Secure rules
Rule 1: Disable automatic redirect following when executing sensitive requests that should not re-transmit payloads to redirect locations.
Be aware of HTTP redirect semantics when making POST or HEAD requests. Jsoup converts POST to GET during 301 and 302 redirects, but strictly preserves POST for 307 and 308 redirects. Disable redirect following on sensitive requests using followRedirects(false) if request payloads should not be automatically re-transmitted to redirect locations.
Connection con = Jsoup.connect("https://example.com/login") .method(Connection.Method.POST) .requestBody("sensitive_data") .followRedirects(false);Connection.Response res = con.execute();
Category: network boundary
Route session traffic through configured proxy endpoints
Use when
Configuring outbound HTTP/HTTPS connections and sessions to route traffic through authorized proxy endpoints.
Secure rules
Rule 1: Enforce outbound traffic control by configuring proxy parameters on reusable Jsoup connection sessions.
Use Jsoup.newSession() and invoke the proxy() method with the appropriate hostname and port to ensure all session requests are routed through the designated proxy gateway.
Escape untrusted strings and serialize documents using safe output settings
Use when
When outputting untrusted data into HTML or attribute contexts or serializing documents to string representations.
Secure rules
Rule 1: Use Entities.escape with appropriate OutputSettings to encode characters for target contexts.
When outputting untrusted strings into HTML or attribute contexts, use Entities.escape(data, outputSettings) or Document.OutputSettings to encode characters such as <, >, &, ", and to prevent Cross-Site Scripting (XSS) or HTML markup injection vulnerabilities.
Enforce Resource Limits on Connections and Parsers
Use when
fetching and parsing remote content, network connections, or untrusted HTML and XML inputs.
Secure rules
Rule 1: Configure explicit response body limits and connection timeouts.
Always configure explicit response body limits using maxBodySize(int bytes) and timeout limits using timeout(int) when fetching content from untrusted network endpoints. Avoid disabling timeouts or limits with a value of 0 to prevent memory exhaustion and denial of service from slow or massive payloads.
Rule 2: Configure explicit stack depth limits on parser instances for untrusted markup.
When processing untrusted XML or HTML documents, configure explicit stack depth limits on the Parser instance using Parser#setMaxDepth(int). This prevents resource exhaustion and unbounded DOM stack growth caused by deeply nested tags.
Isolate authentication contexts and handle credentials securely in connection requests
Use when
Configuring request authenticators and handling sensitive headers or session tokens during connection requests across different origins or persistent thread pools.
Secure rules
Rule 1: Set authenticators directly on isolated Connection instances for each request execution to prevent cross-tenant credential leakage.
Avoid sharing authentication contexts across persistent thread pools where ThreadLocal states might retain sensitive data. Instead, configure authenticators directly on isolated Connection instances for each distinct request execution.
Rule 2: Rely on automatic credential stripping on cross-origin redirects to prevent sensitive token leakage.
Allow Jsoup connection handling to automatically sanitize sensitive headers like Authorization, Cookie, and Cookie2 when following redirects across different origins while retaining them for same-origin redirects.
Configure Safelist instances completely before sharing across concurrent threads
Use when
When configuring and sharing Safelist and Cleaner instances across multiple concurrent threads in jsoup applications.
Secure rules
Rule 1: Fully initialize Safelist instances prior to sharing or passing them to cleaner components, and use deep copies to isolate concurrent modifications.
Safelist objects in jsoup are mutable. To ensure security control integrity across threads, applications must finish configuring a Safelist prior to sharing it or passing it to Cleaner instances, and must never mutate it while active. To derive a custom variant safely from a shared safelist, always use the deep copy constructor.
Safelist baseSafelist = Safelist.relaxed();Safelist threadSafelist = new Safelist(baseSafelist) .addAttributes("div", "class");Cleaner cleaner = new Cleaner(threadSafelist);
Category: session management
Maintain Isolated Session Contexts and Cookies
Use when
Managing multi-step HTTP interactions and session state in Jsoup connections to preserve isolated path-scoped cookie contexts.
Use Jsoup.newSession() when executing multi-step HTTP interactions to ensure path-scoped cookie handling and state isolation. Do not share session objects across unrelated user operations or global contexts.
Use correct attribute and selector API signatures and prevent duplicate attributes
Approximately 369 tokens
Use when
When programmatically setting attributes, querying text nodes, or instantiating attributes using Jsoup.
Secure rules
Rule 1: Use Attributes#put() instead of Attributes#add() to set attributes.
When setting attributes programmatically, use Attributes#put(key, value) rather than Attributes#add(key, value) to overwrite existing attributes and prevent duplicate attribute names that could cause parser discrepancies or security control bypasses.
element.attributes().put("href", sanitizedUrl);
Rule 2: Use Element#selectNodes() instead of the deprecated matchText selector.
Avoid using the deprecated :matchText pseudo-selector when querying text nodes since it mutates the underlying DOM tree. Instead, use Element#selectNodes() with node pseudo-selectors like ::text or ::textnode to query text nodes safely without unexpected side-effects.
Rule 3: Choose the correct Attribute constructor based on encoding state.
Use standard constructors like new Attribute(key, value) for raw unencoded strings, and restrict Attribute.createFromEncoded(key, encodedValue) exclusively to cases where the attribute value is already HTML entity-encoded to prevent unexpected unescaping.
Authenticate Requests Securely Using Jsoup Request Authenticators
Approximately 236 tokens
Use when
When configuring HTTP or proxy authentication for Jsoup connection sessions and requests to verify identity and supply credentials.
Secure rules
Rule 1: Supply authentication credentials safely using RequestAuthenticator and validate request hosts to prevent credential leakage.
Use Jsoup’s RequestAuthenticator interface to manage authentication credentials instead of manual headers. Inspect the challenge context using auth.isServer() and auth.isProxy(), and validate request hosts with auth.url().getHost() before returning credentials.
Prevent Injection When Constructing Dynamic CSS Selectors and Query Parsers
Approximately 305 tokens
Use when
Building dynamic CSS selector queries or regex pseudo-selectors using untrusted user input.
Secure rules
Rule 1: Escape special meta-characters or wrap dynamic strings using Pattern.quote when building regex-based pseudo-selectors.
Wrap dynamic strings in Pattern.quote(...) when building regex-based pseudo-selectors such as :matches(...) or :matchesOwn(...) with user input to prevent regex injection, parser crashes, or unexpected query alterations.
Rule 2: Avoid concatenating untrusted input into CSS selector queries and escape special meta-characters.
When querying the DOM using Jsoup CSS selector methods such as select() or expectFirst(), meta-characters including dots, hashes, slashes, and backslashes must be escaped using backslashes to prevent CSS selector injection.
String safeId = untrustedId.replaceAll("([.#/\\\\])", "\\\\$1");Element el = doc.expectFirst("#" + safeId);// Or use direct element access without CSS parser syntaxElement directEl = doc.getElementById(untrustedId);
Validate Element Schemas and HTML Structure Against Defined Allowlist Contracts
Approximately 489 tokens
Use when
When validating untrusted DOM nodes or HTML fragments against expected structure, namespaces, and safelist rules before processing or rendering.
Secure rules
Rule 1: Validate DOM element names and namespaces using elementIs instead of raw string comparisons.
When validating DOM nodes against expected element schemas or structural contracts, use elementIs(normalName, namespace) instead of checking element tag names using raw string comparisons on tagName(). This ensures that both normalized element tag names and explicit document namespaces are strictly validated according to the schema rules.
if (element.elementIs("a", Parser.NamespaceHtml)) { String href = element.attr("href");} else { throw new IllegalArgumentException("Unexpected element or namespace schema violation");}
Rule 2: Validate untrusted HTML fragments against an explicit Safelist schema before processing.
Use Jsoup.isValid(bodyHtml, safelist) to validate whether untrusted HTML fragments conform to the schema rules defined by a Safelist allowance structure. Ensure that input validated with isValid is still normalized using Jsoup.clean() prior to storage or rendering to enforce attributes and parse normalization.
Safelist schema = Safelist.relaxed();if (!Jsoup.isValid(userInput, schema)) { throw new IllegalArgumentException("Input HTML does not match the required schema rules.");}String safeHtml = Jsoup.clean(userInput, "https://example.com/", schema);
Validate connection URLs are absolute and use allowed schemes
Use when
When accepting external URL strings from users before passing them into Jsoup.connect().
Secure rules
Rule 1: Enforce absolute URLs with explicit http or https schemes before connection processing.
Verify that input strings start with the required scheme prefix before calling Jsoup.connect() to prevent malformed inputs or missing protocols from causing runtime exceptions or unexpected application failures.
Normalize and Interpret Untrusted Input via Jsoup Parsers and URL Resolution
Approximately 475 tokens
Use when
When parsing untrusted HTML/XML streams, resolving relative URLs, or processing input attributes and character entities.
Secure rules
Rule 1: Ensure XML input is parsed using Parser.xmlParser() rather than standard HTML parsing.
Developers must ensure that XML input is parsed using Parser.xmlParser() rather than standard HTML parsing to prevent misinterpretation of tags, namespaces, or attribute names, avoiding silent mutations or structural corruption.
Use Node.absUrl() for URL-valued attributes that may be relative. It resolves the attribute against the node’s base URI, removes ASCII control characters during resolution, and returns an empty string when an absolute URL cannot be produced. Do not call StringUtil.resolve() directly because StringUtil is an internal API whose behavior may change without notice.
Document document = Jsoup.parse( "<a href=\"../resource\">Resource</a>", "https://example.com/path/");String absoluteUrl = document.selectFirst("a").absUrl("href");if (!absoluteUrl.isEmpty()) { // Process the resolved URL.}
Rule 3: Rely on Jsoup native stream parsing APIs for multibyte and entity-heavy inputs.
When parsing HTML streams that contain numerous HTML entity references across large inputs, rely directly on Jsoup’s native stream parsing APIs such as Jsoup.parse(InputStream, String, String) rather than manually pre-chunking or slicing input buffers.
Control Request Method Retention and Redirect Behavior
Approximately 234 tokens
Use when
Making HTTP POST or HEAD requests where redirect semantics must be explicitly controlled to prevent automatic re-transmission of sensitive payloads across network boundaries.
Secure rules
Rule 1: Disable automatic redirect following when executing sensitive requests that should not re-transmit payloads to redirect locations.
Be aware of HTTP redirect semantics when making POST or HEAD requests. Jsoup converts POST to GET during 301 and 302 redirects, but strictly preserves POST for 307 and 308 redirects. Disable redirect following on sensitive requests using followRedirects(false) if request payloads should not be automatically re-transmitted to redirect locations.
Connection con = Jsoup.connect("https://example.com/login") .method(Connection.Method.POST) .requestBody("sensitive_data") .followRedirects(false);Connection.Response res = con.execute();
Route session traffic through configured proxy endpoints
Approximately 186 tokens
Use when
Configuring outbound HTTP/HTTPS connections and sessions to route traffic through authorized proxy endpoints.
Secure rules
Rule 1: Enforce outbound traffic control by configuring proxy parameters on reusable Jsoup connection sessions.
Use Jsoup.newSession() and invoke the proxy() method with the appropriate hostname and port to ensure all session requests are routed through the designated proxy gateway.
Escape untrusted strings and serialize documents using safe output settings
Approximately 206 tokens
Use when
When outputting untrusted data into HTML or attribute contexts or serializing documents to string representations.
Secure rules
Rule 1: Use Entities.escape with appropriate OutputSettings to encode characters for target contexts.
When outputting untrusted strings into HTML or attribute contexts, use Entities.escape(data, outputSettings) or Document.OutputSettings to encode characters such as <, >, &, ", and to prevent Cross-Site Scripting (XSS) or HTML markup injection vulnerabilities.
Enforce Resource Limits on Connections and Parsers
Approximately 288 tokens
Use when
fetching and parsing remote content, network connections, or untrusted HTML and XML inputs.
Secure rules
Rule 1: Configure explicit response body limits and connection timeouts.
Always configure explicit response body limits using maxBodySize(int bytes) and timeout limits using timeout(int) when fetching content from untrusted network endpoints. Avoid disabling timeouts or limits with a value of 0 to prevent memory exhaustion and denial of service from slow or massive payloads.
Rule 2: Configure explicit stack depth limits on parser instances for untrusted markup.
When processing untrusted XML or HTML documents, configure explicit stack depth limits on the Parser instance using Parser#setMaxDepth(int). This prevents resource exhaustion and unbounded DOM stack growth caused by deeply nested tags.
Isolate authentication contexts and handle credentials securely in connection requests
Approximately 284 tokens
Use when
Configuring request authenticators and handling sensitive headers or session tokens during connection requests across different origins or persistent thread pools.
Secure rules
Rule 1: Set authenticators directly on isolated Connection instances for each request execution to prevent cross-tenant credential leakage.
Avoid sharing authentication contexts across persistent thread pools where ThreadLocal states might retain sensitive data. Instead, configure authenticators directly on isolated Connection instances for each distinct request execution.
Rule 2: Rely on automatic credential stripping on cross-origin redirects to prevent sensitive token leakage.
Allow Jsoup connection handling to automatically sanitize sensitive headers like Authorization, Cookie, and Cookie2 when following redirects across different origins while retaining them for same-origin redirects.
Configure Safelist instances completely before sharing across concurrent threads
Approximately 218 tokens
Use when
When configuring and sharing Safelist and Cleaner instances across multiple concurrent threads in jsoup applications.
Secure rules
Rule 1: Fully initialize Safelist instances prior to sharing or passing them to cleaner components, and use deep copies to isolate concurrent modifications.
Safelist objects in jsoup are mutable. To ensure security control integrity across threads, applications must finish configuring a Safelist prior to sharing it or passing it to Cleaner instances, and must never mutate it while active. To derive a custom variant safely from a shared safelist, always use the deep copy constructor.
Safelist baseSafelist = Safelist.relaxed();Safelist threadSafelist = new Safelist(baseSafelist) .addAttributes("div", "class");Cleaner cleaner = new Cleaner(threadSafelist);
Maintain Isolated Session Contexts and Cookies
Approximately 213 tokens
Use when
Managing multi-step HTTP interactions and session state in Jsoup connections to preserve isolated path-scoped cookie contexts.
Use Jsoup.newSession() when executing multi-step HTTP interactions to ensure path-scoped cookie handling and state isolation. Do not share session objects across unrelated user operations or global contexts.