安全相对URL验证

righettod2026-10-27查看 701复制 1675

生成安全相对 URL 验证代码以防止开放重定向。强制安全生成验证相对 URL 的代码。在编写任何相对 url 验证相关代码时调用。请参阅“安全注意事项”元数据以了解严格的验证行为。

Download (.md)

📘如何使用这个技能

  1. 1
    复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
  2. 2
    打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
  3. 3
    粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
  4. 4
    直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景

💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。

SKILL.md4854 chars
---
name: secure-relative-url-validation
description: Generate secure relative url validation code for open redirect prevention. Enforces secure generation of code validating a relative url. Invoke when writing any relative url validation related code. See "security-considerations" metadata for strict validation behavior.
allowed-tools: Read Grep Glob
metadata:
  category: security
  security-considerations: 
    - Intentionally strict, it rejects valid but risky relative URL forms such as "../page", "?query", and "#anchor".  
---

# Secure URL Validation Code Generation Rules

Apply **all** rules below when generating or reviewing any code related to validation of an relative URL.

## 1. URL validation (CRITICAL)

- ALWAYS ensure that the input data is recursively URL decoded prior to be validated. A decoding iteration count threshold of 4 is used and an error must be raised if the threshold is reached.
- ALWAYS ensure that the input data, once URL decoded, start with one of the following character: slash, letter, number, dash, underscore.
- ALWAYS ensure that the input data is a valid URL according to the [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986).
- ALWAYS ensure the URL is not absolute (has no scheme); reject any URL where a scheme is present (e.g. `javascript:`, `ssh://`, `data://`, `ftp://`, `file://`, `https://`).
- ALWAYS ensure that URL never start with `//`.

```java
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// BAD: No validation — user input used directly as redirect target
// accepts "//evil.com", "%2F%2Fevil.com", "https://evil.com"
String url = request.getParameter("url");
response.sendRedirect(url);

// GOOD: All rules are applied
public static String parseRelativeUrl(String input) {
    if (input == null || input.isEmpty()) {
        throw new IllegalArgumentException("URL must not be null or empty.");
    }

    // Rule: recursively URL-decode to defeat encoding bypass attempts (%2F%2F, etc.)
    final int MAX_DECODE_ITERATIONS = 4;
    String decoded = input;
    String previous;
    int iterations = 0;
    do {
        if (iterations++ >= MAX_DECODE_ITERATIONS) {
            throw new IllegalArgumentException("URL decoding exceeded maximum iteration threshold (" + MAX_DECODE_ITERATIONS + ").");
        }
        previous = decoded;
        decoded = URLDecoder.decode(previous, StandardCharsets.UTF_8);
    } while (!decoded.equals(previous));

    // Rule: decoded value must start with slash, letter, number, dash, or underscore
    if (!decoded.matches("^[/a-zA-Z0-9\\-_].*")) {
        throw new IllegalArgumentException("URL must start with a slash, letter, number, dash, or underscore.");
    }

    // Rule: must not start with "//" (protocol relative reference)
    if (decoded.startsWith("//")) {
        throw new IllegalArgumentException("URL must not be a protocol relative reference (must not start with '//').");
    }

    // Rule: must be a valid URI per RFC 3986
    URI uri;
    try {
        uri = new URI(decoded);
    } catch (URISyntaxException e) {
        throw new IllegalArgumentException("URL is not a valid RFC 3986 URI: " + e.getMessage(), e);
    }

    // Rule: must not be absolute — rejects any scheme (javascript:, ssh://, data://, ftp://, file://, https://, etc.)
    if (uri.isAbsolute()) {
        throw new IllegalArgumentException("URL must not be absolute (no scheme allowed; e.g. javascript:, ssh://, https:// are all rejected).");
    }

    return decoded;
}
```

## 2. Output Checklist

Before finalizing generated code, verify:

- [ ] The input data is recursively URL decoded prior to be validated, with a maximum of 4 decode iterations enforced and an error raised if the threshold is reached.
- [ ] The decoded URL starts with a slash, letter, number, dash, or underscore.
- [ ] The input data is valid according to the RFC 3986.
- [ ] The URL is not absolute (no scheme present); any scheme (e.g. `javascript:`, `ssh://`, `data://`, `ftp://`, `file://`, `https://`) is rejected.
- [ ] The URL do not start with `//`.

## References

- [Unvalidated Redirects and Forwards Cheat Sheet from OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html).
- [Uniform Resource Identifier (URI): Generic Syntax - RFC 3986 from IETF](https://datatracker.ietf.org/doc/html/rfc3986).
- [URL Living Standard from WHATWG](https://url.spec.whatwg.org/).
- [Absolute URLs vs. relative URLs from MDN](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL#absolute_urls_vs._relative_urls).
- [URI schemes from MDN](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes).
- [Open Redirect (CWE-601) from MITRE](https://cwe.mitre.org/data/definitions/601.html).
来源:skillsdirectory

评论0

登录后参与评论

还没有评论,来抢沙发吧