new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

OWASP Cheat Sheets · all subjects

abuse_cases/validation

149 notes in this subject, read out of this brain and free to use. This is page 1 of 3.

Abuse case effectiveness tracking with automated tests

Adding automated tests allows teams to track the effectiveness of countermeasures against abuse cases and determine if the countermeasures are still in place during maintenance or bug fixing phases, preventing accidental removal or disabling. This is also useful for Continuous Delivery approaches to ensure all abuse case protections are in place before opening access to the application.

Abuse case validation during implementation

Put in place automated or manual validations to ensure all selected abuse cases are handled and correctly/completely handled. Automated validations can include custom audit rules in SAST/DAST tools and dedicated security-oriented tests. Manual validations can include security code reviews and pentester validation during intrusion testing.

Compute shipping cost server-side from rate table

Accept the shipping selection from the client, but compute the shipping cost server-side from the application's own rate table. Do not accept a shipping cost field from the request.

Apply per-feature rate limits beyond global edge limits

A global rate limit at the network edge is not sufficient. The signup-bonus endpoint, the referral endpoint, and the promo-redemption endpoint each need their own per-feature rate limits. Value-dispensing features are abuse magnets and require dedicated controls.

Determine tax-exempt status from account state

Determine tax-exempt flag status from the account's server-side state, not from a client-supplied exemption field in the request.

Per-action caps, per-account caps, per-source caps for defense in depth

Apply a per-action cap such as one bonus per account, a per-account cap such as total lifetime promo value, and a per-source cap such as per payment method or per device. This layered approach gives defense in depth against value-dispensing abuse.

Make claiming rewards asymmetrically harder than earning them

Actions that give value should be harder than actions that do not. Making someone wait 30 seconds or complete a CAPTCHA to claim a reward is fine. The legitimate user clicks once and moves on; the automated abuser suffers a per-request cost and abandons the attempt.

Never accept price from client; compute from database

Never accept a price, subtotal, tax, or total from the client request. Accept only product identifiers and quantities, then compute prices and totals server-side from your own database. The same rule applies to discounts: accept a coupon code, validate it server-side, and apply the discount server-side. Do not accept a discount amount field from the request.

Anti-bot decision logging fields

For each request to a sensitive endpoint, capture: timestamp, request ID, route, HTTP status code, client IP, ASN, country, TLS fingerprint (JA3/JA4), HTTP/2 fingerprint, User-Agent (raw and parsed family/version), authenticated identity or session ID hash, decision (allow/challenge/tarpit/block), and signals (e.g., bot_score, triggering rule). Mask credentials and PII in logs per the Logging Cheat Sheet. Record a request ID to correlate with session logs.

Anti-bot monitoring and anomaly dashboards

Build dashboards for: requests-per-second by endpoint, 4xx/5xx rate, fail rate by route, signup-to-purchase funnel, login success rate. Sudden shifts (more than 3-sigma) on these metrics are bot signals. Bot incidents are detected post-hoc almost as often as in real time; log enough to investigate.

Server-side and client-side encoding coordination

The correct approach is to server-side encode for the output context where data is introduced into the application, then client-side encode for the individual subcontext (DOM methods) which untrusted data is passed to. This avoids issues with string comparisons on multiply-encoded data.

Never use eval() with untrusted data

It is always a bad idea to use user-controlled input in dangerous sources such as eval. Using eval() with untrusted data is 99% of the time an indication of bad or lazy programming practice. Do not try to sanitize input passed to eval; instead avoid using eval entirely.

Use textContent for safe DOM population

The most fundamental safe way to populate the DOM with untrusted data is to use the textContent property, which does not execute code. Example: element.textContent = untrustedData. Alternatively use innerText for text-only content, but note that innerText can execute code when applied to script tags.

N-levels of encoding needed for chained eval contexts

If untrusted data passes through multiple levels of implicit eval(), apply N-levels of JavaScript encoding corresponding to the number of eval layers. For example, if data goes through setTimeout's eval followed by a function call, double JavaScript encode. If that function also passes to eval, triple encode. The number of encoding passes must match the number of eval contexts the data traverses.

JavaScript encode and delimit untrusted data as quoted strings on entry

Always JavaScript encode and delimit untrusted data as quoted strings when entering the application when building templated JavaScript. Example: var x = "<%= Encode.forJavaScript(untrustedData) %>"

Treat untrusted data only as displayable text

Avoid treating untrusted data as code or markup within JavaScript code. Untrusted data should only be treated as displayable text.

Use closures to avoid double JavaScript encoding with setTimeout

To avoid double JavaScript encoding issues with methods like setTimeout, use a closure to wrap the untrusted data. Example: setTimeout((function(param) { return function() { customFunction(param); } })(encodeForJavascript(untrustedData)), y)

URL escape then JavaScript escape for href and URL attributes

When setting URL attributes like href in an execution context using setAttribute or direct assignment, apply URL encoding first, then JavaScript encoding. Example: element.setAttribute("href", ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForURL(userRelativePath))). Note that fully qualified URLs with protocols will have the colon encoded, breaking links.

setAttribute with event handlers implicitly coerces value to code

The setAttribute(name_string, value_string) method is dangerous for event handlers because it implicitly coerces the value_string into the DOM attribute datatype of name_string. For event handler attributes, this means the value is converted to JavaScript code and evaluated, even if JavaScript encoded.

URL escape then JavaScript escape for CSS url() context

When inserting untrusted data into the CSS url() method within an execution context, apply URL encoding first, then JavaScript encoding. Example: document.body.style.backgroundImage = "url(" + ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForURL(companyName)) + ")" . Note that CSS expression() method has been disabled in execution contexts.

Complex context example: javascript: protocol in href

Complex contexts occur when data starts in one rendering context then changes to another. Example: untrusted data in an href attribute starts in the rendering URL context, then enters a JavaScript execution context via the javascript: protocol handler, which passes data to an execution URL subcontext. For this case, server-side encoding should be: ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForURL(untrustedData))

Prefer innerText or textContent over innerHTML to fix DOM XSS

The best way to fix DOM based XSS is to use the right output method (sink). If using user input to write to a div tag, use innerText or textContent instead of innerHTML. This eliminates the vulnerability and is the proper remediation for DOM based XSS.

Run JavaScript in ECMAScript 5 sandbox to prevent API compromise

Run JavaScript in an ECMAScript 5 canopy or sandbox to make it harder for the JavaScript API to be compromised. Sandbox/sanitizer libraries include js-xss, sanitize-html, DOMPurify, and the MDN HTML Sanitizer API.

Avoid innerHTML, outerHTML, document.write, document.writeln with untrusted data

Avoid populating the following methods with untrusted data: element.innerHTML, element.outerHTML, document.write, document.writeln. These render untrusted input as HTML which can lead to XSS.

Avoid untrusted data in event handlers and JavaScript code contexts

The primary recommendation is to avoid including untrusted data in event handler and JavaScript code subcontexts entirely. JavaScript encoding does not reliably prevent execution in these contexts. Methods that implicitly evaluate code (setTimeout, setInterval, new Function, setAttribute for event handlers) will execute encoded strings. Use setAttribute with event handler attributes only to set references to functions, not code strings.

innerText can execute code in script tags

Although innerText is sometimes advocated as a safe alternative to innerHTML, it can execute code when applied to script tag elements. Example vulnerability: var tag = document.createElement("script"); tag.innerText = untrustedData; // executes code

Avoid implicit eval methods: setTimeout, setInterval, new Function

Avoid passing untrusted data to methods which implicitly eval() data, such as setTimeout, setInterval, and new Function. If untrusted data must be passed to these methods, ensure it is delimited with string delimiters, enclosed within a closure or N-levels of JavaScript encoded, or wrapped in a custom function.

JavaScript escape only for HTML non-event attributes via setAttribute

When setting HTML attributes that do not execute code (non-event, non-CSS, non-URL attributes) using element.setAttribute(), only JavaScript encode the value. Do not also HTML attribute encode, as this causes double-encoding and breaks display. Example safe attributes: align, alink, alt, bgcolor, border, cellpadding, cellspacing, class, color, cols, colspan, coords, dir, face, height, hspace, ismap, lang, marginheight, marginwidth, multiple, nohref, noresize, noshade, nowrap, ref, rel, rev, rows, rowspan, scrolling, shape, span, summary, tabindex, title, usemap, valign, value, vlink, vspace, width.

JSON.stringify() output requires encoding before HTML embedding

JSON.stringify() is not an output-encoding function. Its output is valid JSON but is not safe to embed directly in HTML, HTML-attribute, or inline script contexts. Characters like <, >, &, ", ', backtick can break out of the surrounding context and enable XSS. Either deliver it as a separate JSON response parsed client-side, or HTML-encode (or JavaScript-string-encode) the serialized string before injecting it.

Untrusted data on right side of expressions only

Use untrusted data only on the right side of expressions, especially data that looks like code (e.g., data passed to location or eval()). Avoid: window[userDataOnLeftSide] = value. Prefer: window["safeKey"] = userDataOnRightSide. Using untrusted user data on the left side allows attackers to subvert internal and external attributes of the window object.

HTML escape then JavaScript escape for innerHTML, outerHTML, document.write

When inserting untrusted data into the HTML subcontext within the execution context using innerHTML, outerHTML, document.write, or document.writeln, apply HTML encoding first, then JavaScript encoding. Example: element.innerHTML = ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(untrustedData))

Use JSON.parse() instead of eval() for JSON deserialization

Use the built-in JSON.parse() to deserialize JSON into JavaScript values, not eval(). JSON.parse() rejects anything that is not valid JSON and cannot execute attacker-supplied code the way eval() can. Use JSON.stringify() to serialize JavaScript values into JSON.

Limit object property access with untrusted keys

Limit access to object properties when using object[x] accessors with untrusted input. Add a level of indirection between untrusted input and specified object properties. Instead of myMapType[untrustedData] = value, use validation: if (untrustedData === 'location') { myMapType.location = value }

Character set issues in URL encoding within DOM

When URL encoding in DOM, be aware of character set issues as the character set in JavaScript DOM is not clearly defined. This can affect how encoded characters are interpreted.

Use safe DOM methods: createElement, setAttribute, appendChild

document.createElement(), element.setAttribute(), element.appendChild() and similar are safe ways to build dynamic interfaces. Note that element.setAttribute is only safe for non-command-execution attributes. Dangerous attributes are any command execution contexts such as onclick or onblur.

HTML encoding is lost when retrieving DOM element values

HTML encodings are lost when retrieving values using the value attribute of a DOM element. If untrustedData is HTML encoded in an input value attribute, when retrieved via document.form.element.value the encoding is reversed, making any code now executable.

HTML encoding does not work in XHTML content type

If pages are returned with content type text/xhtml or file extension .xhtml, HTML encoding may not prevent XSS. For example, <script>&#x61;lert(1);</script> is still executable in XHTML because the HTML-encoded value is still recognized.

JavaScript encoding accepted as valid executable code in many contexts

JavaScript encoding enables support for international characters and alternate string representations in JavaScript constructs. However, JavaScript-encoded values are still executable in many contexts, such as variable declarations, for loops, function calls via window[encodedString], and eval. This makes JavaScript encoding less effective than HTML encoding which castrates HTML tags.

Recommended encoding libraries: ESAPI, Java Encoder, js-xss, sanitize-html, DOMPurify

OWASP ESAPI and OWASP Java Encoder are active projects providing support for HTML, CSS, and JavaScript encoding. ESAPI encodes all non-alphanumeric characters on an allowlist basis. For JavaScript-based projects, libraries include js-xss, sanitize-html, DOMPurify, and the MDN HTML Sanitizer API.

Encoding library inconsistencies: allowlist vs denylist

Different encoding libraries have inconsistencies. Some work on a denylist while others ignore important characters like < and >. ESAPI is one of the few which works on an allowlist and encodes all non-alphanumeric characters. It is important to use an encoding library that understands which characters can be used to exploit vulnerabilities in their respective contexts.

Disposable email abuse controls

Maintain a list of known disposable email domains if appropriate to prevent bypass of controls. Prefer risk-based controls over strict blocking. Monitor for suspicious patterns of account creation using temporary email services.

Anti-enumeration controls for email flows

Attackers should not be able to determine whether an email is registered in the system. Use consistent responses for login and reset flows regardless of whether the email exists. Avoid timing discrepancies between valid and invalid cases. Implement rate limiting and monitoring to detect enumeration attempts.

GraphQL DoS prevention: rate limiting

Enforce rate limiting on incoming requests per IP or user (or both) to prevent basic DoS attacks. Ideally this can be done with a WAF, API gateway, or web server (Nginx, Apache, HTTPD) to reduce the effort of adding rate limiting. Rate limiting can also be implemented in application code but is non-trivial.

GraphQL DoS prevention: infrastructure timeouts

Add timeouts on HTTP servers (Apache/httpd, nginx), reverse proxies, or load balancers as an alternative to application-level timeouts. Infrastructure timeouts are often inaccurate and can be bypassed more easily than application-level ones.

GraphQL query timeout implementation: Java with Instrumentation

In Java using Instrumentation, implement GraphQL query timeout by extending SimpleInstrumentation and instrumenting DataFetcher to use Observable.fromCallable() with subscribeOn(Schedulers.computation()) and timeout(10, TimeUnit.SECONDS).blockingFirst(). This provides a timeout of 10 seconds for resolver execution.

GraphQL query timeout implementation: JavaScript

In JavaScript, implement GraphQL query timeout by tracking elapsed time during request processing and throwing an error when the timeout is exceeded. Example: if runTime exceeds 10000 milliseconds (10 seconds), throw an error such as 'Query execution has timeout. Field resolution aborted'.

GraphQL DoS prevention: pagination

Add pagination to GraphQL queries to limit the amount of data that can be returned in a single response and help prevent DoS attacks.

GraphQL DoS prevention: amount limiting

Add amount limiting to incoming GraphQL queries to prevent DoS attacks. In GraphQL each object requested in a query can have an amount specified. By default amount can be unlimited which may lead to DoS. For JavaScript APIs, use graphql-input-number to implement amount limiting. Prevent queries requesting excessive amounts of objects, such as requesting 99999999 of an object.

GraphQL DoS prevention: depth limiting

Add depth limiting to incoming GraphQL queries to prevent DoS attacks. In GraphQL each query has a depth such as nested objects. By default depth can be unlimited which may lead to DoS. For graphql-java APIs, utilize the built-in MaxQueryDepthInstrumentation for depth limiting. For JavaScript APIs, use graphql-depth-limit to implement depth limiting. Depth is counted starting at 0 for the query, then incrementing by 1 for each nested level.

GraphQL: prevent user-controlled HTTP requests (SSRF)

When using user input, even if sanitized or validated, it should not be used for certain purposes that would give a user control over data flow. Do not make an HTTP or resource request to a host that the user supplies unless there is an absolute business need.

GraphQL injection prevention: use safe APIs

When handling input meant to be passed to another interpreter (SQL/NoSQL/ORM, OS, LDAP, XML), always choose libraries or modules offering safe APIs such as parameterized statements. Follow the documentation to properly use the tool. Using ORMs and ODMs are good options but must be used properly to avoid flaws such as ORM injection. If safe tools are not available, always escape or encode input data according to the target interpreter's best practices using a well-documented and actively maintained escaping or encoding library.

GraphQL input validation: handle unicode properly

To properly handle unicode input in GraphQL, use a single internal character encoding for all incoming data.

GraphQL input validation: use allowlist not denylist

Validate all incoming data to only allow valid values using an allowlist approach. Use specific GraphQL data types such as scalars or enums, write custom GraphQL validators for complex validations, and consider custom scalars. Define schemas for mutations input. List allowed characters and do not use a denylist. The stricter the list of allowed characters the better; a good starting point is allowing only alphanumeric, non-unicode characters to disallow many attacks.

GraphQL DoS prevention: application timeouts

Add timeouts at the application layer for GraphQL queries and resolver functions to limit how many resources any single request can consume. GraphQL does not natively support query timeouts so custom code is required. Application-level timeouts are usually more effective since the query or resolution can be stopped once the timeout is reached. A reasonable timeout for query execution is 10 seconds.

GraphQL batching attack mitigation: object rate limiting

To mitigate GraphQL batching attacks, create a code-level rate limit on how many objects that callers can request. The backend would track how many different object instances the caller has requested, so they will be blocked after requesting too many objects even if they batch the object requests in a single network call. This replicates a network-level rate limit that a WAF or other tool would do.

GraphQL error handling: do not return excessive errors

GraphQL APIs in production should not return stack traces or be in debug mode. Using middleware is one popular way to have better control over errors the server returns. To disable excessive errors with Apollo Server, either pass debug: false to the Apollo Server constructor or set the NODE_ENV environment variable to 'production' or 'test'.

GraphQL DoS prevention: server-side batching and caching

To increase efficiency of a GraphQL API and reduce its resource consumption, implement the batching and caching technique to prevent making duplicate requests for pieces of data within a small time frame. Facebook's DataLoader tool is one way to implement this.

GraphQL DoS prevention: query cost analysis

Consider performing query cost analysis and enforcing a maximum allowed cost per query to prevent DoS. Query cost analysis involves assigning costs to the resolution of fields or types in incoming queries so that the server can reject queries that cost too much to run or will consume too many resources. This is not easy to implement and may not always be necessary. For graphql-java APIs, utilize the built-in MaxQueryComplexityInstrumentation to enforce max query complexity. For JavaScript APIs, use graphql-cost-analysis or graphql-validation-complexity to enforce max query cost.

GraphQL error handling: mask and log errors

To log the stack trace internally without returning it to the user, mask and log errors so they are available to the developers but not to callers of the API.

GraphQL batching attack mitigation: prevent batching for sensitive objects

To mitigate GraphQL batching attacks, prevent batching for sensitive objects that you don't want to be brute forced, such as usernames, emails, passwords, OTPs, session tokens, etc. This way an attacker is forced to attack the API like a REST API and make a different network call per object instance. This is not supported natively so it will require a custom solution. Once this control is put in place other standard controls will function normally to help prevent any brute forcing.

Give your agent this brain