From 603d1133e015493f922f61147693f2751479ef17 Mon Sep 17 00:00:00 2001 From: Leah Restad Date: Sun, 3 May 2026 17:51:09 -0700 Subject: [PATCH 1/7] rename and contrbutor docs --- .github/ISSUE_TEMPLATE/bug_report_dotnet.yml | 80 ++++++++++++ .github/ISSUE_TEMPLATE/bug_report_nodejs.yml | 81 +++++++----- .github/ISSUE_TEMPLATE/feature_request.yml | 60 +++++++++ CONTRIBUTING.md | 99 ++++++++------- README.md | 74 +++++++---- SUPPORT.md | 27 ++-- .../antissrfhandler.md | 0 .../antissrfpolicy/constructor.md | 0 .../antissrfpolicy/index.md | 0 .../methods/addallowedaddresses.md | 0 .../methods/adddeniedaddresses.md | 0 .../methods/adddeniedheaders.md | 0 .../methods/addrequiredheaders.md | 0 .../antissrfpolicy/methods/gethandler.md | 0 .../antissrfpolicy/methods/index.md | 0 .../antissrfpolicy/properties/addxffheader.md | 0 .../properties/allowedaddresses.md | 0 .../properties/allowplaintexthttp.md | 0 .../properties/deniedaddresses.md | 0 .../properties/deniedheaders.md | 0 .../properties/denyallunspecifiedips.md | 0 .../antissrfpolicy/properties/index.md | 0 .../properties/requiredheaders.md | 0 docs/{csharp-api => dotnet-api}/changelog.md | 0 docs/{csharp-api => dotnet-api}/index.md | 2 +- .../urivalidator/inazurekeyvaultdomain.md | 0 .../urivalidator/inazurestoragedomain.md | 0 .../urivalidator/index.md | 0 .../urivalidator/indomain.md | 0 docs/faq.md | 40 +++++- docs/getting-started.md | 115 +++++++++++++++++- docs/ipaddressranges.md | 9 ++ docs/nodejs-api/index.md | 4 +- docs/support.md | 23 ++++ dotnet/src/README.md | 51 ++++++-- nodejs/README.md | 58 ++++++++- 36 files changed, 587 insertions(+), 136 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report_dotnet.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml rename docs/{csharp-api => dotnet-api}/antissrfhandler.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/constructor.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/index.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/addallowedaddresses.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/adddeniedaddresses.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/adddeniedheaders.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/addrequiredheaders.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/gethandler.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/methods/index.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/addxffheader.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/allowedaddresses.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/allowplaintexthttp.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/deniedaddresses.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/deniedheaders.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/denyallunspecifiedips.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/index.md (100%) rename docs/{csharp-api => dotnet-api}/antissrfpolicy/properties/requiredheaders.md (100%) rename docs/{csharp-api => dotnet-api}/changelog.md (100%) rename docs/{csharp-api => dotnet-api}/index.md (99%) rename docs/{csharp-api => dotnet-api}/urivalidator/inazurekeyvaultdomain.md (100%) rename docs/{csharp-api => dotnet-api}/urivalidator/inazurestoragedomain.md (100%) rename docs/{csharp-api => dotnet-api}/urivalidator/index.md (100%) rename docs/{csharp-api => dotnet-api}/urivalidator/indomain.md (100%) create mode 100644 docs/support.md diff --git a/.github/ISSUE_TEMPLATE/bug_report_dotnet.yml b/.github/ISSUE_TEMPLATE/bug_report_dotnet.yml new file mode 100644 index 0000000..b5d2ed8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_dotnet.yml @@ -0,0 +1,80 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Bug Report - .NET +description: File a bug report for the .NET version of the AntiSSRF library +title: "[Bug][.NET]: " +labels: ["bug", "dotnet"] +type: bug +body: + + - type: textarea + attributes: + label: Bug Behavior + description: Describe the current behavior you are experiencing. Include any error messages, unexpected responses, or other issues. + validations: + required: false + + - type: textarea + attributes: + label: Expected Behavior + description: Describe what you expected to happen instead of the current behavior. + validations: + required: false + + - type: textarea + attributes: + label: Steps To Reproduce + description: Provide clear steps to reproduce this issue, including code samples if applicable. + placeholder: | + 1. Create policy: `var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest);` + 2. Get handler: `using var handler = policy.GetHandler();` + 3. Create HttpClient: `using var client = new HttpClient(handler);` + 4. Make request: `var response = await client.GetAsync("https://example.com");` + 5. Observe unexpected behavior: [describe what happens] + validations: + required: false + + - type: input + attributes: + label: Version + description: Specify the version of the AntiSSRF .NET library where you encountered this issue. + placeholder: "e.g., 1.0.0" + validations: + required: true + + - type: input + attributes: + label: Operating System + description: Specify your operating system and version. + placeholder: "e.g., Ubuntu 22.04, Windows 11, macOS 15.0" + validations: + required: true + + - type: input + attributes: + label: .NET Version + description: Specify the .NET version you are using. + placeholder: "e.g., 8.0.100" + validations: + required: true + + - type: textarea + attributes: + label: Additional Context + description: | + Provide any additional context, links to documentation, stack traces, or other relevant information that may help us understand and resolve this issue. + validations: + required: false + + - type: checkboxes + attributes: + label: Verification + description: Please confirm before submitting your bug report. + options: + - label: I have searched existing issues and confirmed this bug has not already been reported + required: true + + - type: markdown + attributes: + value: "Thank you for helping us improve the AntiSSRF library!" diff --git a/.github/ISSUE_TEMPLATE/bug_report_nodejs.yml b/.github/ISSUE_TEMPLATE/bug_report_nodejs.yml index aa26727..3a9dc37 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_nodejs.yml +++ b/.github/ISSUE_TEMPLATE/bug_report_nodejs.yml @@ -1,59 +1,80 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -name: Bug - Node.js -description: File a bug report for the NodeJS version of the AntiSSRF library. -title: "[Bug][Nodejs]: <title>" +name: Bug Report - Node.js +description: File a bug report for the Node.js version of the AntiSSRF library +title: "[Bug][Node.js]: <title>" labels: ["bug", "nodejs"] -assignees: - - leah-restad type: bug body: + - type: textarea attributes: label: Bug Behavior - description: A concise description of what you're experiencing. + description: Describe the current behavior you are experiencing. Include any error messages, unexpected responses, or other issues. validations: required: false + - type: textarea attributes: label: Expected Behavior - description: A concise description of what you expected to happen. + description: Describe what you expected to happen instead of the current behavior. validations: required: false + - type: textarea attributes: label: Steps To Reproduce - description: Steps to reproduce the behavior. + description: Provide clear steps to reproduce this issue, including code samples if applicable. placeholder: | - 1. In this environment... - 1. With this config... - 1. Run '...' - 1. See error... + 1. Import the library: `import { AntiSSRFPolicy, PolicyConfigOptions } from "@microsoft/antissrf";` + 2. Create policy: `const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest);` + 3. Get agent: `const agent = policy.getHttpsAgent();` + 4. Make request: `https.get("https://example.com", { agent }, (res) => { ... });` + 5. Observe unexpected behavior: [describe what happens] validations: required: false - - type: textarea + + - type: input attributes: - label: Environment - description: | - examples: - - **OS**: Ubuntu 20.04 - - **Node**: 13.14.0 - - **npm**: 7.6.3 - value: | - - OS: - - Node: - - npm: - render: markdown + label: Version + description: Specify the version of the AntiSSRF Node.js library where you encountered this issue. + placeholder: "e.g., 1.0.0" validations: - required: false + required: true + + - type: input + attributes: + label: Operating System + description: Specify your operating system and version. + placeholder: "e.g., Ubuntu 22.04, Windows 11, macOS 15.0" + validations: + required: true + + - type: input + attributes: + label: Node.js Version + description: Specify the Node.js version you are using. + placeholder: "e.g., 22.1.0" + validations: + required: true + - type: textarea attributes: - label: Anything else? + label: Additional Context description: | - Links? References? Anything that will give us more context about the issue you are encountering! - - Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. + Provide any additional context, links to documentation, stack traces, or other relevant information that may help us understand and resolve this issue. validations: required: false - \ No newline at end of file + + - type: checkboxes + attributes: + label: Verification + description: Please confirm before submitting your bug report. + options: + - label: I have searched existing issues and confirmed this bug has not already been reported + required: true + + - type: markdown + attributes: + value: "Thank you for helping us improve the AntiSSRF library!" diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..bbafeab --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,60 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Feature Request +description: Request a new feature or enhancement for the AntiSSRF library +title: "[Feature]: <title>" +labels: ["enhancement"] +type: feature +body: + + - type: textarea + attributes: + label: Feature Description + description: Describe the feature you would like to see added to AntiSSRF. + validations: + required: true + + - type: textarea + attributes: + label: Problem Statement + description: Describe the problem this feature would solve or the use case it would enable. + validations: + required: true + + - type: textarea + attributes: + label: Proposed Solution + description: Describe how you envision this feature working. Include any API design ideas or implementation approaches. + validations: + required: false + + - type: textarea + attributes: + label: Alternative Solutions + description: Describe any alternative solutions or workarounds you have considered. + validations: + required: false + + - type: textarea + attributes: + label: Additional Context + description: Provide any additional context, examples, links to documentation, or other relevant information that supports this feature request. + validations: + required: false + + - type: dropdown + attributes: + label: Applicable Libraries + description: Select which AntiSSRF library or libraries this feature request applies to. + options: + - .NET Library + - Node.js Library + - Both Libraries + - None or N/A + validations: + required: true + + - type: markdown + attributes: + value: "Thank you for helping us improve the AntiSSRF library!" \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ec1d01..c51c239 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,68 +1,79 @@ # Contributing to AntiSSRF -Thank you for your interest in contributing to the AntiSSRF project! This guide will help you get started. +Thank you for your interest in contributing to Microsoft AntiSSRF! This guide will help you get started with contributing to our security library. ## Development Setup -### C# AntiSSRF Library - -From the `./csharp` directory: +### AntiSSRF .NET Library **Prerequisites:** -- .NET 8.0 SDK or later - -**Commands:** -- **Build:** `dotnet build Microsoft.Security.AntiSSRF.sln` -- **Unit tests:** `dotnet test` +- .NET 8.0 SDK +- Make sure you are in the `/dotnet` folder -### Node.js (TypeScript) +**Useful Commands:** +- Restore dependencies: `dotnet restore` +- Build solution: `dotnet build` +- Run all tests: `dotnet test` -From the `./nodejs` directory: +### AntiSSRF Node.js Library **Prerequisites:** -- Node.js 20+ +- Node.js 20.0 or later +- Make sure you are in the `/nodejs` folder -**Commands:** -- **Install dependencies:** `npm install` -- **Build TypeScript:** `npm run build` -- **Unit tests:** `npm test` -- **Lint code:** `npm run lint` -- **Format code:** `npm run format` +**Useful Commands:** +- Install dependencies: `npm install` +- Build TypeScript: `npm run build` +- Run all tests: `npm test` +- Lint code: `npm run lint` +- Format code: `npm run format` -## Updating IP Address Ranges or Domains +### Documentation -The IP address ranges are maintained in [`config/IPAddressRanges.json`](config/IPAddressRanges.json) and automatically generated into language-specific files. +**Prerequisites:** +- Jekyll (for GitHub Pages) +- Ruby 3.4 or later +- Bundler (`gem install bundler`) +- Make sure you are in the `/docs` folder -The Azure SDK domains are maintained in [`config/Domains.json`](config/Domains.json) and automatically generated into language-specific files. +**Useful Commands:** +- Install dependencies: `bundle install` +- Test locally: `bundle exec jekyll serve` -**Prerequisites:** -- `jq`: `brew install jq` (macOS) or `sudo apt-get install jq` (Linux) +## Submitting Issues -**Commands:** -- **Regenerate IP Address Ranges:** -```bash -./scripts/build-ip-ranges-cs.sh -./scripts/build-ip-ranges-nodejs.sh -``` -- **Regenerate Domains:** -```bash -./scripts/build-domains-cs.sh -./scripts/build-domains-nodejs.sh -``` +We welcome bug reports and feature requests! Please use our issue templates to provide the information we need: -**Important**: The GitHub Actions workflow will fail if generated files don't match the source JSON. +### Bug Reports +- Report in our [GitHub Issues](https://github.com/microsoft/AntiSSRF/issues) +- Please search existing issues first to avoid duplicates +- Provide clear reproduction steps and expected behavior +- Include relevant version information and environment details -## Editing Documentation +### Feature Requests +- Report in our [GitHub Issues](https://github.com/microsoft/AntiSSRF/issues) +- Clearly describe the problem your feature would solve +- Explain your proposed solution and any alternatives considered +- Specify which library (or both) the feature applies to -The project documentation is built with Jekyll and uses the Just the Docs theme. +## Contributing Code -From the `./docs` directory: +We welcome pull requests for bug fixes, features, and documentation improvements: -**Prerequisites:** -- Ruby 2.7+ and Bundler +### Before Submitting +- Verify that all existing tests pass without failures +- Add appropriate test coverage for your changes +- Ensure there are no breaking changes (in rare cases where unavoidable, discuss with maintainers in an issue first) +- Documentation updates are optional but very appreciated + +### When Discussion is Required + +Before submitting a PR, you must create an issue and discuss with maintainers if your changes involve: -**Commands:** -- **Install dependencies:** `bundle install` -- **Test locally:** `bundle exec jekyll serve` +- Breaking changes - Any modification that could break existing functionality. All other possibilities must be considered before introducing a breaking change. +- New API additions - Adding new public methods, classes, or interfaces. +- Configuration file changes - Modifications to IP address ranges or domains configuration files. These changes will almost always be rejected unless there is an exceptional reason. -The documentation will be available at `http://localhost:4000` when running the local server. +### Pull Request Process +- Be detailed in your description and reproduction steps +- Reference any related issues, bugs, or feature requests diff --git a/README.md b/README.md index ad2e7be..a93318b 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,61 @@ -# Project +# Microsoft AntiSSRF -> This repo has been populated by an initial template to help get you started. Please -> make sure to update the content to build a great experience for community-building. +The Microsoft AntiSSRF library is a security-developed, exhaustively-tested secure code library that provides robust URL validation to mitigate the risk of Server-Side Request Forgery (SSRF) vulnerabilities. It is an easy-to-use drop-in library with minimal adoption effort for developers, available for both .NET and Node.js applications. -As the maintainer of this project, please make a few updates: +## What is Server-Side Request Forgery (SSRF)? -- Improving this README.MD file to provide a great experience -- Updating SUPPORT.MD with content about this project's support experience -- Understanding the security reporting process in SECURITY.MD -- Remove this section from the README +Server-Side Request Forgery (also known as SSRF) is a critical web security vulnerability in which an attacker can manipulate the server-side application to make network requests to an arbitrary endpoint. Through this vulnerability, the attacker manipulates the target web server to connect to internal, sensitive networks or exfiltrate sensitive data to an untrusted endpoint on the Internet. + +SSRF can lead (but is not limited) to: +- Exposure of internal services +- Leakage of sensitive data +- Service disruption +- Remote code execution + +## How the Microsoft AntiSSRF Library Helps + +A common scenario in many online services is handling requests from customers containing customer-supplied strings that are, or are used to construct a URL. These strings are often not validated properly, leading to vulnerabilities such as Server-Side Request Forgery which can result in token theft. + +AntiSSRF helps mitigate these risks by: +- Automatically validating URLs and network connections and rejecting/refusing unsafe input +- Providing an agent that ensures HTTP requests cannot reach internal or sensitive IP addresses + +## Getting Started + +### .NET Framework and .NET Core + +- πŸ“¦ **NuGet Package**: [Microsoft.Security.AntiSSRF](https://www.nuget.org/packages/Microsoft.Security.AntiSSRF/) +- πŸ“– **Documentation**: [AntiSSRF C# API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) +- πŸš€ **Quick Start**: [Getting Started Guide](https://microsoft.github.io/AntiSSRF/getting-started) +- πŸ“‹ **Library README**: [.NET README](dotnet/README.md) + +### JavaScript/TypeScript (Node.js) + +- πŸ“¦ **npm Package**: [@microsoft/antissrf](https://www.npmjs.com/package/@microsoft/antissrf) +- πŸ“– **Documentation**: [AntiSSRF JavaScript API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) +- πŸš€ **Quick Start**: [Getting Started Guide](https://microsoft.github.io/AntiSSRF/getting-started) +- πŸ“‹ **Library README**: [Node.js README](nodejs/README.md) ## Contributing -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit [Contributor License Agreements](https://cla.opensource.microsoft.com). +We welcome contributions! Please see our contribution resources: + +- 🀝 **Contributing Guide**: [CONTRIBUTING.md](CONTRIBUTING.md) +- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) +- οΏ½ **License**: [LICENSE](LICENSE) +- πŸ”’ **Security Policy**: [SECURITY.md](SECURITY.md) +- πŸ“‹ **Code of Conduct**: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) +- πŸ†˜ **Support**: [SUPPORT.md](SUPPORT.md) + +## More Resources -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. +### Learning About SSRF -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +- πŸ“– **AntiSSRF Documentation**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) +- **OWASP SSRF Guide**: [Server-Side Request Forgery Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html) +- **PortSwigger Web Security Academy**: [Server-side request forgery (SSRF)](https://portswigger.net/web-security/ssrf) +- **CWE-918**: [Server-Side Request Forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html) -## Trademarks +### Testing Tools -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft -trademarks or logos is subject to and must follow -[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/legal/intellectualproperty/trademarks/usage/general). -Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. -Any use of third-party trademarks or logos are subject to those third-party's policies. +- πŸ§ͺ **Dusseldorf**: [Dynamic SSRF Testing Tool](https://github.com/Microsoft/Dusseldorf) - Microsoft's open-source tool for dynamic SSRF testing and validation \ No newline at end of file diff --git a/SUPPORT.md b/SUPPORT.md index 291d4d4..a51f299 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,25 +1,14 @@ -# TODO: The maintainer of this repo has not yet edited this file - -**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? - -- **No CSS support:** Fill out this template with information about how to file issues and get help. -- **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. -- **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. - -*Then remove this first heading from this SUPPORT.MD file before publishing your repo.* - # Support -## How to file issues and get help +This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new issue. -This project uses GitHub Issues to track bugs and feature requests. Please search the existing -issues before filing new issues to avoid duplicates. For new issues, file your bug or -feature request as a new Issue. +For help and questions about using this project, please: -For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE -FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER -CHANNEL. WHERE WILL YOU HELP PEOPLE?**. +- **Check the documentation**: Visit our [documentation site](https://microsoft.github.io/AntiSSRF/) for comprehensive guides and API references +- **Search existing issues**: Browse [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) to see if your question has already been answered +- **File a new issue**: Create a [new issue](https://github.com/Microsoft/AntiSSRF/issues/new/choose) using our issue templates for bug reports or feature requests +- **Contact us directly**: Email us at **antissrf-oss@microsoft.com** for questions about usage, integration, or other inquiries -## Microsoft Support Policy +## Microsoft Support Policy -Support for this **PROJECT or PRODUCT** is limited to the resources listed above. +Support for Microsoft AntiSSRF is limited to the resources listed above. This is an open source project maintained by Microsoft, and support is provided on a best-effort basis through the community channels listed above. diff --git a/docs/csharp-api/antissrfhandler.md b/docs/dotnet-api/antissrfhandler.md similarity index 100% rename from docs/csharp-api/antissrfhandler.md rename to docs/dotnet-api/antissrfhandler.md diff --git a/docs/csharp-api/antissrfpolicy/constructor.md b/docs/dotnet-api/antissrfpolicy/constructor.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/constructor.md rename to docs/dotnet-api/antissrfpolicy/constructor.md diff --git a/docs/csharp-api/antissrfpolicy/index.md b/docs/dotnet-api/antissrfpolicy/index.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/index.md rename to docs/dotnet-api/antissrfpolicy/index.md diff --git a/docs/csharp-api/antissrfpolicy/methods/addallowedaddresses.md b/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/addallowedaddresses.md rename to docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md diff --git a/docs/csharp-api/antissrfpolicy/methods/adddeniedaddresses.md b/docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/adddeniedaddresses.md rename to docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md diff --git a/docs/csharp-api/antissrfpolicy/methods/adddeniedheaders.md b/docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/adddeniedheaders.md rename to docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md diff --git a/docs/csharp-api/antissrfpolicy/methods/addrequiredheaders.md b/docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/addrequiredheaders.md rename to docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md diff --git a/docs/csharp-api/antissrfpolicy/methods/gethandler.md b/docs/dotnet-api/antissrfpolicy/methods/gethandler.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/gethandler.md rename to docs/dotnet-api/antissrfpolicy/methods/gethandler.md diff --git a/docs/csharp-api/antissrfpolicy/methods/index.md b/docs/dotnet-api/antissrfpolicy/methods/index.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/methods/index.md rename to docs/dotnet-api/antissrfpolicy/methods/index.md diff --git a/docs/csharp-api/antissrfpolicy/properties/addxffheader.md b/docs/dotnet-api/antissrfpolicy/properties/addxffheader.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/addxffheader.md rename to docs/dotnet-api/antissrfpolicy/properties/addxffheader.md diff --git a/docs/csharp-api/antissrfpolicy/properties/allowedaddresses.md b/docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/allowedaddresses.md rename to docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md diff --git a/docs/csharp-api/antissrfpolicy/properties/allowplaintexthttp.md b/docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/allowplaintexthttp.md rename to docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md diff --git a/docs/csharp-api/antissrfpolicy/properties/deniedaddresses.md b/docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/deniedaddresses.md rename to docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md diff --git a/docs/csharp-api/antissrfpolicy/properties/deniedheaders.md b/docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/deniedheaders.md rename to docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md diff --git a/docs/csharp-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/denyallunspecifiedips.md rename to docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md diff --git a/docs/csharp-api/antissrfpolicy/properties/index.md b/docs/dotnet-api/antissrfpolicy/properties/index.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/index.md rename to docs/dotnet-api/antissrfpolicy/properties/index.md diff --git a/docs/csharp-api/antissrfpolicy/properties/requiredheaders.md b/docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md similarity index 100% rename from docs/csharp-api/antissrfpolicy/properties/requiredheaders.md rename to docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md diff --git a/docs/csharp-api/changelog.md b/docs/dotnet-api/changelog.md similarity index 100% rename from docs/csharp-api/changelog.md rename to docs/dotnet-api/changelog.md diff --git a/docs/csharp-api/index.md b/docs/dotnet-api/index.md similarity index 99% rename from docs/csharp-api/index.md rename to docs/dotnet-api/index.md index 8af2c33..b863071 100644 --- a/docs/csharp-api/index.md +++ b/docs/dotnet-api/index.md @@ -1,7 +1,7 @@ --- layout: default title: C# API Reference -nav_order: 4 +nav_order: 3 description: "Complete API documentation for the AntiSSRF C# library" has_children: true has_toc: false diff --git a/docs/csharp-api/urivalidator/inazurekeyvaultdomain.md b/docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md similarity index 100% rename from docs/csharp-api/urivalidator/inazurekeyvaultdomain.md rename to docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md diff --git a/docs/csharp-api/urivalidator/inazurestoragedomain.md b/docs/dotnet-api/urivalidator/inazurestoragedomain.md similarity index 100% rename from docs/csharp-api/urivalidator/inazurestoragedomain.md rename to docs/dotnet-api/urivalidator/inazurestoragedomain.md diff --git a/docs/csharp-api/urivalidator/index.md b/docs/dotnet-api/urivalidator/index.md similarity index 100% rename from docs/csharp-api/urivalidator/index.md rename to docs/dotnet-api/urivalidator/index.md diff --git a/docs/csharp-api/urivalidator/indomain.md b/docs/dotnet-api/urivalidator/indomain.md similarity index 100% rename from docs/csharp-api/urivalidator/indomain.md rename to docs/dotnet-api/urivalidator/indomain.md diff --git a/docs/faq.md b/docs/faq.md index f0f683a..891dd92 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,10 +1,46 @@ --- layout: default title: FAQ -nav_order: 4 +nav_order: 5 description: "Frequently asked questions about AntiSSRF" --- # Frequently Asked Questions -TODO +## What IP addresses or subnets should my service block? + +It is important to separate HTTP clients intented for internal vs. external requests. + +Ideally, for internal requests or if the range of possible IP addresses is known, use the configuration [`PolicyConfigOptions.InternalOnly`](../dotnet-api/antissrfpolicy/constructor#policyconfigoptionsinternalonly) and ONLY allow the expected ranges. + +For external requests, your service should AT LEAST block the internal and special-use IP addresses, included to the configuration [`IPAddressRanges.recommendedLatest`](../ipaddressranges#recommended-ranges-latest). + +## Does the AntiSSRF library support IPv6 functionality? + +Yes, the AntiSSRF Library supports IPv6 functionality. + +## My outgoing requests are being dropped at the destination because of an invalid X-Forwarded-For header. What should I do? + +By default, the external-only configurations of AntiSSRF automatically add an `X-Forwarded-For: "true"` header to outgoing requests that don't already have this header. This is an important security feature that helps protect against access to sensitive, internal endpoints like IMDS which safely drop all requests with the `X-Forwarded-For` header. + +However, some destination services may reject requests with this dummy value. If your destination service is rejecting requests because of the `X-Forwarded-For: "true"` header, you can disable this behavior: + +```cs +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalLatest); +policy.addXFFHeader = false; // Disables automatic X-Forwarded-For header addition +``` + +**Important:** Only disable this feature if you are absolutely certain that: +* Your destination service drops ALL requests with the `X-Forwarded-For` header. For example, you are intentionally accessing IMDS while blocking all external IP addresses. +* **OR** another component in your service stack reliably adds the `X-Forwarded-For` header to all outgoing requests. That way, the policy does not need to add the invalid dummy value to include the header. + +For more information, see the [X-Forwarded-For header documentation](../dotnet-api/antissrfpolicy/properties/addxffheader#security-notes) and [`addXFFHeader` property](../dotnet-api/antissrfpolicy/properties/addxffheader). + +## What languages and frameworks are supported? + +| Language / Framework | Documentation | Notes | +| --- | --- | --- | +| C# / .NET Framework and Core | [AntiSSRF .NET Library](../dotnet-api/) | For web clients using `HttpClient` objects | +| Node.js / JavaScript/TypeScript | [AntiSSRF Node.js Library](../nodejs-api/) | For requests using NodeJS HTTP(S) Agents | + +Broader platform support is under development. diff --git a/docs/getting-started.md b/docs/getting-started.md index 9c9ed7e..c0de575 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -5,4 +5,117 @@ nav_order: 2 description: "Learn how to install and configure AntiSSRF in your application" --- -TODO +# Getting Started with Microsoft AntiSSRF + +The Microsoft AntiSSRF library helps protect your applications from Server-Side Request Forgery (SSRF) vulnerabilities by providing robust URL validation and secure HTTP client configurations. + +## Installation + +### .NET Framework and .NET Core (C#) + +Install the NuGet package: + +```bash +dotnet add package Microsoft.Security.AntiSSRF +``` + +Or using Package Manager Console: + +```powershell +Install-Package Microsoft.Security.AntiSSRF +``` + +### Node.js (JavaScript/TypeScript) + +Install the npm package: + +```bash +npm install @microsoft/antissrf +``` + +## Quick Start Examples + +### .NET Usage + +```csharp +using Microsoft.Security.AntiSSRF; +using System.Net.Http; + +// Create a policy for external-only requests +var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Get a secure HttpMessageHandler +using var handler = policy.GetHandler(); + +// Use with HttpClient +using var client = new HttpClient(handler); + +// Make secure requests - internal IPs will be blocked +var response = await client.GetAsync("https://api.example.com/data"); +``` + +### Node.js Usage + +```javascript +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Create a policy for external-only requests +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Get a secure HTTPS agent +const httpsAgent = policy.getHttpsAgent({ keepAlive: true }); + +// Use with standard Node.js requests +const options = { + hostname: 'api.example.com', + path: '/data', + agent: httpsAgent +}; + +https.get(options, (res) => { + // Handle response +}); +``` + +## How to Use + +The AntiSSRF library provides validation for different scenarios based on your trust requirements: + +| Use Case | Description | Documentation Link | +|----------|-------------|-------------------| +| **Any Domain** | Validate untrusted URLs belonging to any domain | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) | +| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurestoragedomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurestoragedomain/) | +| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurekeyvaultdomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurekeyvaultdomain/) | +| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/indomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/indomain/) | + +## Best Practices + +1. Use Separate Handlers for External vs. Internal Requests + + Always create separate HTTP clients for external and internal requests so that you can use the stricted security policy possible on each. + This approach ensures that external API calls cannot accidentally reach internal services, and internal calls are restricted to only the networks you explicitly trust. When using the `AntiSSRFPolicy`, you can choose different built-in configuration options intended for each use-case. + +2. Only Use `InDomain` for Owned and Trusted Domains + + A domain should only be considered trusted if you fully control both the domain itself and all subdomains. You should trust the DNS responses for these domains and should be sure that no subdomain is configurable by a third party. + +3. Add X-Forwarded-For Header whenever possible + + The `X-Forwarded-For` header can be an important defense-in-depth strategy against SSRF vulnerabilities. Some services, including IMDS, will drop all incoming requests with the `X-Forwarded-For` present. By ensuring that the header is added to all outgoing requests, your service can be sure that it will never have an SSRF vulnerability that leaks data from IMDS. + +4. Stay up-to-date + + Keep the library updated to receive the latest security changes. Instead of using `PolicyConfigOptions.ExternalV1`, consider using `PolicyConfigOptions.ExternalOnlyLatest`. + +## Next Steps + +### Learn More + +- πŸ“– **API Documentation**: [.NET API](../dotnet-api/) | [Node.js API](../nodejs-api/) +- ❓ **Common Questions**: [FAQ](../faq/) + +### Get Support + +- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) +- πŸ“§ **Contact**: antissrf-oss@microsoft.com diff --git a/docs/ipaddressranges.md b/docs/ipaddressranges.md index 80adece..fef2140 100644 --- a/docs/ipaddressranges.md +++ b/docs/ipaddressranges.md @@ -13,6 +13,15 @@ Provides predefined IP address ranges for internal and special-purpose addresses This list is consistent and shared across all the languages and frameworks. +## Example + +To block all address ranges except for the IPv4 Private-Use ranges: + +```cs +const policy = new AntiSSRFPolicy(PolicyConfigOptions.InternalOnly); +policy.addAllowedAddresses(IPAddressRanges.privateUse); +``` + ## Special-Purpose Ranges | Special Purpose | Variable Name | IP Address Ranges | diff --git a/docs/nodejs-api/index.md b/docs/nodejs-api/index.md index 57faa65..d6a297e 100755 --- a/docs/nodejs-api/index.md +++ b/docs/nodejs-api/index.md @@ -1,7 +1,7 @@ --- layout: default title: Node.js API Reference -nav_order: 3 +nav_order: 4 description: "Complete API documentation for the AntiSSRF Node.js library" has_children: true has_toc: false @@ -11,7 +11,7 @@ has_toc: false ## AntiSSRF JavaScript Library -The **AntiSSRF NodeJS Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as a NodeJS HTTP(S) Agent and URL validator, depending on use case. +The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as a Node.js HTTP(S) Agent and URL validator, depending on use-case. ## Usage Instructions diff --git a/docs/support.md b/docs/support.md new file mode 100644 index 0000000..c77f560 --- /dev/null +++ b/docs/support.md @@ -0,0 +1,23 @@ +--- +layout: default +title: Support +nav_order: 6 +description: "How to get help and support for Microsoft AntiSSRF" +--- + +# Support + +## How to file issues and get help + +This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. + +For help and questions about using this project, please: + +- **Check the documentation**: Visit our [documentation site](https://microsoft.github.io/AntiSSRF/) for comprehensive guides and API references +- **Search existing issues**: Browse [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) to see if your question has already been answered +- **File a new issue**: Create a [new issue](https://github.com/Microsoft/AntiSSRF/issues/new/choose) using our issue templates for bug reports or feature requests +- **Contact us directly**: Email us at **antissrf-oss@microsoft.com** for questions about usage, integration, or other inquiries + +## Microsoft Support Policy + +Support for Microsoft AntiSSRF is limited to the resources listed above. This is an open source project maintained by Microsoft, and support is provided on a best-effort basis through the community channels listed above. \ No newline at end of file diff --git a/dotnet/src/README.md b/dotnet/src/README.md index bef0d41..b6551dd 100644 --- a/dotnet/src/README.md +++ b/dotnet/src/README.md @@ -1,32 +1,57 @@ -## About +## Microsoft AntiSSRF for .NET -<!-- A description of the package and where one can find more documentation --> +The Microsoft AntiSSRF library for .NET is a security-developed, exhaustively-tested library that provides robust URL validation to protect .NET applications from Server-Side Request Forgery (SSRF) vulnerabilities. Designed specifically for .NET Framework and .NET Core applications, it integrates seamlessly with `HttpClient` through the `AntiSSRFHandler` class, allowing developers to secure outbound HTTP requests with minimal code changes. ## How to Use -<!-- A compelling example on how to use this package with code --> +The AntiSSRF library provides validation for different scenarios based on your trust requirements: + +| Use Case | Description | Documentation Link | +|----------|-------------|-------------------| +| **Any Domain** | Validate untrusted URLs belonging to any domain | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) | +| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [InAzureStorageDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurestoragedomain/) | +| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [InAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurekeyvaultdomain/) | +| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [InDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/indomain/) | ## Key Features -<!-- The key features of this package --> +πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts + +🚫 **Private Network Protection** - - Separate built-in configuration options for internal vs. external address HTTP clients + +πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks -## Main Types +πŸ”„ **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts -<!-- The main types provided in this library --> +🌐 **Protocol Validation** - Ensures only safe protocols are used -## Addtional Documentation +βš™οΈ **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies -<!--Provide links to more resources: List links such as detailed documentation, tutorial videos, blog posts, or any other relevant documentation to help users get the most out of your package--> +## Additional Documentation -## Related Packages +Explore our comprehensive documentation to get the most out of Microsoft AntiSSRF: -<!-- The related packages associated with this package --> +### Getting Started +- πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) +- πŸš€ **Quick Start Guide**: [Getting Started with .NET](https://microsoft.github.io/AntiSSRF/getting-started/) +- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started/#best-practices) +- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq/) +- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/dotnet-api/changelog/) + +### API Documentation +- πŸ”§ **C# API Reference**: [Complete .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/) +- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfhandler/) +- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) +- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/) ## Feedback & Contributing -<!-- How to provide feedback on this package and contribute to it --> -<!-- Links to a GitHub repository where could open issues, Twitter, a Discord channel, bug tracker, or other platforms where a package consumer can connect with the package author --> +We welcome feedback and contributions from the community! Here's how you can get involved: + +- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features +- 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project +- πŸ“§ **Contact**: antissrf-oss@microsoft.com - Direct email for questions and feedback ## Support Policy -<!-- The support policy associated with this package --> \ No newline at end of file +For support inquiries, contact antissrf-oss@microsoft.com. \ No newline at end of file diff --git a/nodejs/README.md b/nodejs/README.md index 30404ce..a8447a5 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -1 +1,57 @@ -TODO \ No newline at end of file +## Microsoft AntiSSRF for Node.js + +The Microsoft AntiSSRF library for Node.js is a security-developed, exhaustively-tested library that provides robust URL validation to protect Node.js applications from Server-Side Request Forgery (SSRF) vulnerabilities. It integrates seamlessly with Node.js HTTP/HTTPS agents, allowing developers to secure outbound HTTP requests with minimal code changes. + +## How to Use + +The AntiSSRF library provides validation for different scenarios based on your trust requirements: + +| Use Case | Description | Documentation Link | +|----------|-------------|-------------------| +| **Any Domain** | Validate untrusted URLs belonging to any domain | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) | +| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [inAzureStorageDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurestoragedomain/) | +| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [inAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurekeyvaultdomain/) | +| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [inDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/indomain/) | + +## Key Features + +πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts + +🚫 **Private Network Protection** - - Separate built-in configuration options for internal vs. external address HTTP clients + +πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks + +πŸ”„ **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts + +🌐 **Protocol Validation** - Ensures only safe protocols are used + +βš™οΈ **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies + +## Additional Documentation + +Explore our comprehensive documentation to get the most out of Microsoft AntiSSRF: + +### Getting Started +- πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) +- πŸš€ **Quick Start Guide**: [Getting Started with Node.js](https://microsoft.github.io/AntiSSRF/getting-started/) +- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started/#best-practices) +- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq/) +- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/nodejs-api/changelog/) + +### API Documentation +- πŸ”§ **JavaScript API Reference**: [Complete Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) +- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfhandler/) +- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) +- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/) + +## Feedback & Contributing + +We welcome feedback and contributions from the community! Here's how you can get involved: + +- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features +- 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project +- πŸ“§ **Contact**: antissrf-oss@microsoft.com - Direct email for questions and feedback + +## Support Policy + +For support inquiries, contact antissrf-oss@microsoft.com. \ No newline at end of file From 14c45508a48af2a4c097f00fe6eac03dc24597a9 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Sun, 3 May 2026 23:27:49 -0700 Subject: [PATCH 2/7] nodejs docs --- docs/faq.md | 6 +- docs/index.md | 6 +- docs/nodejs-api/antissrfpolicy/constructor.md | 56 ++++------------ docs/nodejs-api/antissrfpolicy/index.md | 42 ++++++------ .../methods/addallowedaddresses.md | 39 +++++++++-- .../methods/adddeniedaddresses.md | 40 ++++++++++-- .../methods/adddeniedheaders.md | 51 +++++++++++++-- .../methods/addrequiredheaders.md | 52 +++++++++++++-- .../antissrfpolicy/methods/gethttpagent.md | 51 +++++++++++++-- .../antissrfpolicy/methods/gethttpsagent.md | 47 ++++++++++++-- .../antissrfpolicy/methods/index.md | 18 ++++++ .../antissrfpolicy/properties/addxffheader.md | 10 +-- .../properties/allowedaddresses.md | 8 +-- .../properties/allowplaintexthttp.md | 6 +- .../properties/deniedaddresses.md | 10 +-- .../properties/deniedheaders.md | 6 +- .../properties/denyallunspecifiedips.md | 8 ++- .../antissrfpolicy/properties/index.md | 13 ++++ .../properties/requiredheaders.md | 6 +- docs/nodejs-api/changelog.md | 4 +- docs/nodejs-api/index.md | 26 ++++---- .../urivalidator/inazurekeyvaultdomain.md | 25 ++++++-- .../urivalidator/inazurestoragedomain.md | 25 ++++++-- docs/nodejs-api/urivalidator/index.md | 16 +++-- docs/nodejs-api/urivalidator/indomain.md | 64 +++++++++++-------- 25 files changed, 445 insertions(+), 190 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 891dd92..1fe0530 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -38,9 +38,9 @@ For more information, see the [X-Forwarded-For header documentation](../dotnet-a ## What languages and frameworks are supported? -| Language / Framework | Documentation | Notes | +| Language | Documentation | Notes | | --- | --- | --- | -| C# / .NET Framework and Core | [AntiSSRF .NET Library](../dotnet-api/) | For web clients using `HttpClient` objects | -| Node.js / JavaScript/TypeScript | [AntiSSRF Node.js Library](../nodejs-api/) | For requests using NodeJS HTTP(S) Agents | +| C# | [AntiSSRF .NET Library](dotnet-api/) | For web clients using `HttpClient` objects | +| JavaScript/TypeScript | [AntiSSRF Node.js Library](nodejs-api/) | For requests using NodeJS HTTP(S) Agents | Broader platform support is under development. diff --git a/docs/index.md b/docs/index.md index f60cd94..50a9225 100644 --- a/docs/index.md +++ b/docs/index.md @@ -42,10 +42,10 @@ A common scenario in many online services is handling requests from customers co ## Supported Languages and Frameworks -| Language / Framework | Documentation | Notes | +| Language | Documentation | Notes | | --- | --- | --- | -| .NET Framework and Core | [AntiSSRF C# Library](csharp-api/) | For web clients using `HttpClient` objects | -| JavaScript/TypeScript | [AntiSSRF JavaScript Library](nodejs-api/) | For requests using NodeJS HTTP(S) Agents | +| C# | [AntiSSRF .NET Library](dotnet-api/) | For web clients using `HttpClient` objects | +| JavaScript/TypeScript | [AntiSSRF Node.js Library](nodejs-api/) | For requests using NodeJS HTTP(S) Agents | {: .note } > Broader platform support is under development. diff --git a/docs/nodejs-api/antissrfpolicy/constructor.md b/docs/nodejs-api/antissrfpolicy/constructor.md index e4a2c2c..2e51d6b 100644 --- a/docs/nodejs-api/antissrfpolicy/constructor.md +++ b/docs/nodejs-api/antissrfpolicy/constructor.md @@ -12,7 +12,7 @@ uid: constructor ## Definition -Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. +Creates a new [AntiSSRFPolicy](../) instance with a predefined security configuration. ```js AntiSSRFPolicy(config: PolicyConfigOptions) @@ -22,54 +22,26 @@ AntiSSRFPolicy(config: PolicyConfigOptions) `config`: `PolicyConfigOptions` -* `PolicyConfigOptions.InternalOnly` -* `PolicyConfigOptions.ExternalOnlyV1` -* `PolicyConfigOptions.ExternalOnlyLatest` -* `PolicyConfigOptions.None` +Choose from the following predefined policy configurations: -### PolicyConfigOptions.InternalOnly +### PolicyConfigOptions -Recommended when: -* The policy should enforce requests only reach internal addresses, blocking all requests to external addresses. -* **OR** the policy should enforce requests only reach addresses specified by `addAllowedAddresses`. - -Configuration: -* Blocks all requests to all IP addresses by default, only allowing requests to IP addresses that have been explicitly specified by `addAllowedAddresses`. - -### PolicyConfigOptions.ExternalOnlyV1 - -Recommended when: -* The policy should enforce that requests should not reach any internal or special-purpose address, unless otherwise specified by `addAllowedAddresses`. - -Configuration: -* Blocks all requests to internal and special-purpose addresses as specified by `IPAddressRanges.recommendedV1`. This excludes any address ranges that have been explicitly specified by `addAllowedAddresses`. -* Adds the `X-Forwarded-For` header on all outgoing requests that do not already have the header. This can be disabled with `policy.addXFFHeader = false`. - -### PolicyConfigOptions.ExternalOnlyLatest +| Option | Use Case | Behavior | +| --- | --- | --- | +| **InternalOnly** | Making requests to internal addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [addAllowedAddresses](../methods/addallowedaddresses). | +| **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedramgesv1). Automatically adds `X-Forwarded-For` header to requests. | +| **ExternalOnlyLatest** | Currently the same as `ExternalOnlyV1` with automatic security updates | Always stays up to date with the latest `ExternalOnly` version, independent of semantic versioning. | +| **None** | Custom policy configuration | No restrictions applied. Requires manual configuration via policy methods. | {: .important } -> This policy does NOT follow semantic versioning. It will always stay up-to-date with the latest recommended addresses with no code changes required by the user. - -Recommended when: -* Currently the same as `PolicyConfigOptions.ExternalOnlyV1`, if you want your security requirements updated automatically and are okay with changes that are not reflected in the package's semantic version. - -Configuration: -* Currently the same as `PolicyConfigOptions.ExternalOnlyV1`. - -### PolicyConfigOptions.None - -Recommended when: -* You plan to manually configure all policy customizations. - -Configuration: -* Unless customized, this policy will not update any requests and will not block any requests. +> `PolicyConfigOptions.ExternalOnlyLatest` does NOT follow semantic versioning. It will always stay up-to-date with the latest recommended addresses with no code changes required by the user. -### Security Notes +## Security Notes To prevent SSRF vulnerabilities, it is a best practice to ensure that your code can make requests to external endpoints or to internal endpoints, but never both. -If your service needs to make outbound requests to external endpoints, you need to make sure that it can't be used to access internal endpoints as well. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. +If your service needs to make requests to external endpoints, you need to make sure that it can’t be abused to access internal resources. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. -If your service needs to make outbound requests to internal endpoints, you need to make sure that it can't be used to access external endpoints as well. In this case, we recommend using `PolicyConfigOptions.InternalOnly` to block all unspecified addresses, then use `addAllowedAddresses(...)` with the specific internal IP addresses that your service might need to access. +If your service needs to make requests to backend services, you must prevent data exfiltration by ensuring it cannot be used to send data to external endpoints. In this case, we recommend using `PolicyConfigOptions.InternalOnly` to block all unspecified addresses, then use `addAllowedAddresses(...)` with the specific internal IP addresses that your service might need to access. -For more about the `X-Forwarded-For` header, see `addXFFHeader`. +For more about the `X-Forwarded-For` header, see [addXFFHeader](../properties/addxffheader). diff --git a/docs/nodejs-api/antissrfpolicy/index.md b/docs/nodejs-api/antissrfpolicy/index.md index 6e967b7..295d2ae 100644 --- a/docs/nodejs-api/antissrfpolicy/index.md +++ b/docs/nodejs-api/antissrfpolicy/index.md @@ -3,56 +3,58 @@ layout: default title: AntiSSRFPolicy parent: Node.js API Reference description: "Main policy configuration class for SSRF protection" +nav_order: 1 has_children: true +has_toc: false --- # AntiSSRFPolicy Class ## Use Case -You would use this class whenever you are accessesing a URL that can belong to any **any domain** or **some untrusted domain**. +Use this class whenever you are accessing a URL that can belong to **any domain** or **some untrusted domain**. -When you are accessing a URL that was constructed with external input (user input or input from other services), you need to make sure the final construted URL cannot be abused to access unexpected internal endpoints. This class allows you to use built-in configurations or customize your own policy, then provides an `http.Agent` and `https.Agent` that will enforce that policy across all requests and redirects. +This use case addresses two distinct security scenarios. For requests to external endpoints, the policy enforces that IP addresses are not internal or special-use addresses, preventing URLs from being abused to gain access to internal resources. For requests to backend resources, the policy blocks all IP addresses except for specific ranges that you expect to see, ensuring that URLs cannot be used to exfiltrate data to unauthorized destinations. {: .note } -> * If you instead expect the domain to be a **specific, trusted domain**, see [inDomain](../urivalidator/indomain.html). -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [inAzureStorageDomain](../urivalidator/inazurestoragedomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [inAzureKeyVaultDomain](../urivalidator/inazurekeyvaultdomain.html). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [URIValidator.inAzureKeyVaultDomain](../urivalidator/inazurekeyvaultdomain). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [URIValidator.inAzureStorageDomain](../urivalidator/inazurestoragedomain). +> * If you instead expect the domain to be a **specific, trusted domain**, see [URIValidator.inDomain](../urivalidator/indomain). ## Definition -Represents a customizable security policy and provides HTTP(S) agents to ensure all outgoing requests match the security policy. +The `AntiSSRFPolicy` allows you to customize security requirements for headers, IP addresses, and protocols. You can configure the policy using built-in settings or define your own custom rules. The policy then provides Node.js HTTP(S) agents that automatically enforce these security requirements on all outgoing requests made using those agents. ## Constructors | Constructor | Description | | --- | --- | -| `AntiSSRFPolicy(config: PolicyConfigOptions)` | Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. | +| [AntiSSRFPolicy(PolicyConfigOptions)](constructor) | Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. | ## Properties | Property | Description | | --- | --- | -| allowPlainTextHttp | Determines whether HTTPS is required or HTTP is allowed. | -| denyAllUnspecifiedIPs | Determines whether all IP addresses should be blocked by default or only `deniedAddresses` IP addresses should be blocked. | -| addXFFHeader | Determines whether to add the `X-Forwarded-For` header to requests that are missing the header. | -| allowedAddresses | List of IPv4/IPv6 addresses or subnets that are explicitly allowed by the policy. | -| deniedAddresses | List of IPv4/IPv6 addresses or subnets that are explicitly blocked by the policy. | -| requiredHeaders | List of headers that are required to be present in all outgoing requests. | -| deniedHeaders | List of headers that are forbidden from being included in outgoing requests. | +| [addXFFHeader](properties/addxffheader) | Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don't already include it. | +| [allowedAddresses](properties/allowedaddresses) | List of IP networks that are explicitly allowed by the policy. | +| [allowPlainTextHttp](properties/allowplaintexthttp) | Determines whether HTTPS is required or HTTP is allowed. | +| [deniedAddresses](properties/deniedaddresses) | List of IP networks that are explicitly blocked by the policy. | +| [deniedHeaders](properties/deniedheaders) | List of headers that are forbidden from being included in outgoing requests. | +| [denyAllUnspecifiedIPs](properties/denyallunspecifiedips) | Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. | +| [requiredHeaders](properties/requiredheaders) | List of headers that are required to be present in outgoing requests. | ## Policy Customization Methods | Method | Description | | --- | --- | -| addAllowedAddresses(networks: string[]) | Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly allowed by the policy. | -| addDeniedAddresses(networks: string[]) | Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly blocked by the policy. | -| addRequiredHeaders(headers: string[]) | Adds to the list of headers explicitly required by the policy. Outgoing requests that are missing a required header will be blocked. | -| addDeniedHeaders(headers: string[]) | Adds to the list of headers explicitly blocked by the policy. Outgoing requests that include a denied header will be blocked. | +| [addAllowedAddresses(string[])](methods/addallowedaddresses) | Adds IP networks to be explicitly allowed by the policy. | +| [addDeniedAddresses(string[])](methods/adddeniedaddresses) | Adds IP networks to be explicitly blocked by the policy. | +| [addDeniedHeaders(string[])](methods/adddeniedheaders) | Adds headers to be explicitly blocked by the policy. | +| [addRequiredHeaders(string[])](methods/addrequiredheaders) | Adds headers to be explicitly required by the policy. | ## Policy Use Methods | Method | Description | | --- | --- | -| getHttpsAgent(agentOptions?: any): https.Agent | Builds an `http.Agent` that will enforce the policy on all outgoing requests. | -| getHttpAgent(agentOptions?: any): http.Agent | Builds an `https.Agent` that will enforce the policy on all outgoing requests. | +| [getHttpAgent(any)](methods/gethttpagent) | Builds an `http.Agent` that will enforce the policy on all outgoing requests. | +| [getHttpsAgent(any)](methods/gethttpsagent) | Builds an `https.Agent` that will enforce the policy on all outgoing requests. | diff --git a/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md b/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md index 147f9d7..b6a41f6 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md @@ -4,7 +4,6 @@ title: addAllowedAddresses parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "addAllowedAddresses method documentation" --- @@ -12,27 +11,27 @@ description: "addAllowedAddresses method documentation" ## Definition -Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly allowed by the policy. +Adds IP networks to be explicitly allowed by the policy. ```js addAllowedAddresses(networks: string[]): void ``` {: .note } -> `allowedAddresses` takes precedence over `deniedAddresses`, if if an IP address matches both, it will be considered allowed by the policy. +> `allowedAddresses` takes precedence over `deniedAddresses`. If an IP address matches both, it will be considered allowed by the policy. ### Parameters `networks`: `string[]` -The llist of IPv4/IPv6 addresses or subnets to be explicitly allowed by the policy. +The list of IP networks to be explicitly allowed by the policy. Networks can be: * IPv4 addresses in dotted-quad notation * ex. `127.0.0.1` * IPv6 addresses in expanded notation `x:x:x:x:x:x:x:x`, where the `x`s are one to four hexadecimal digits * ex. `ABCD:EF01:2345:6789:ABCD:EF01:2345:6789` -* IPv6 addresses in compressed notation, where one group of consecutive 0s is be represented with `::` +* IPv6 addresses in compressed notation, where one group of consecutive 0s is represented with `::` * ex. `ABCD::`, `::1`, `ABCD:EF01::2345:6789` * IPv6 in mixed notation `x:x:x:x:x:x:d.d.d.d`, where the `x`s are hexadecimal values and the `d`s are decimal * ex. `::FFFF:127.0.0.1` @@ -44,3 +43,33 @@ Networks can be: `AntiSSRFError` * The `networks` argument is `null` or `undefined`. * Some `network` in `networks` is not a valid format. + +## Examples + +```javascript +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.None); +policy.denyAllUnspecifiedIPs = true; +policy.addAllowedAddresses(["1.2.3.4"]); + +const options = { + hostname: '<some_untrusted_hostname>', + path: '/public/data', + agent: policy.getHttpsAgent() +}; + +const req = https.request(options, (res) => { + // If the untrusted hostname directs to 1.2.3.4, + // the request will succeed here +}); + +req.on('error', (err) => { + // If untrusted hostname directs to anything besides 1.2.3.4, + // the request will fail here with an AntiSSRF error +}); + +req.end(); +``` diff --git a/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md b/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md index e58cf8f..bc5aad5 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md @@ -4,7 +4,6 @@ title: addDeniedAddresses parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "addDeniedAddresses method documentation" --- @@ -12,30 +11,30 @@ description: "addDeniedAddresses method documentation" ## Definition -Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly blocked by the policy. +Adds IP networks to be explicitly blocked by the policy. ```js addDeniedAddresses(networks: string[]): void ``` {: .note } -> `allowedAddresses` takes precedence over `deniedAddresses`, if if an IP address matches both, it will be considered allowed by the policy. +> `allowedAddresses` takes precedence over `deniedAddresses`. If an IP address matches both, it will be considered allowed by the policy. {: .note } -> `denyAllUnspecifiedIPs` takes precedence over `deniedAddresses`, if `denyAllUnspecifiedIPs` is `true`, `deniedAddresses` will not be considered when determining if an IP address is allowed or blocked by the policy. +> `denyAllUnspecifiedIPs` takes precedence over `deniedAddresses`. If `denyAllUnspecifiedIPs` is `true`, `deniedAddresses` will not be considered when determining if an IP address is allowed or blocked by the policy. ### Parameters `networks`: `string[]` -The list of IPv4/IPv6 addresses or subnets to be explicitly blocked by the policy. +The list of IP networks to be explicitly blocked by the policy. Networks can be: * IPv4 addresses in dotted-quad notation * ex. `127.0.0.1` * IPv6 addresses in expanded notation `x:x:x:x:x:x:x:x`, where the `x`s are one to four hexadecimal digits * ex. `ABCD:EF01:2345:6789:ABCD:EF01:2345:6789` -* IPv6 addresses in compressed notation, where one group of consecutive 0s is be represented with `::` +* IPv6 addresses in compressed notation, where one group of consecutive 0s is represented with `::` * ex. `ABCD::`, `::1`, `ABCD:EF01::2345:6789` * IPv6 in mixed notation `x:x:x:x:x:x:d.d.d.d`, where the `x`s are hexadecimal values and the `d`s are decimal * ex. `::FFFF:127.0.0.1` @@ -48,3 +47,32 @@ Networks can be: * The `networks` argument is `null` or `undefined`. * Some `network` in `networks` is not a valid format. * `denyAllUnspecifiedIPs` is already set to `true`. + +## Examples + +```js +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.None); +policy.addDeniedAddresses(["1.2.3.4"]); + +const options = { + hostname: '<some_untrusted_hostname>', + path: '/public/data', + agent: policy.getHttpsAgent() +}; + +const req = https.request(options, (res) => { + // If the untrusted hostname directs to anything besides 1.2.3.4, + // the request will succeed here +}); + +req.on('error', (err) => { + // If untrusted hostname directs to 1.2.3.4, + // the request will fail here with an AntiSSRF error +}); + +req.end(); +``` diff --git a/docs/nodejs-api/antissrfpolicy/methods/adddeniedheaders.md b/docs/nodejs-api/antissrfpolicy/methods/adddeniedheaders.md index 56c5139..f669007 100755 --- a/docs/nodejs-api/antissrfpolicy/methods/adddeniedheaders.md +++ b/docs/nodejs-api/antissrfpolicy/methods/adddeniedheaders.md @@ -4,7 +4,6 @@ title: addDeniedHeaders parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "addDeniedHeaders method documentation" --- @@ -12,10 +11,10 @@ description: "addDeniedHeaders method documentation" ## Definition -Adds to the list of headers explicitly blocked by the policy. Outgoing requests that include a denied header will be blocked. +Adds headers to be explicitly blocked by the policy. Requests that include a denied header will be blocked. ```js -addDeniedHeaders(networks: string[]): void +addDeniedHeaders(headers: string[]): void ``` {: .note } @@ -25,10 +24,54 @@ addDeniedHeaders(networks: string[]): void `headers`: `string[]` -* The list of headers for the policy to block. +The list of headers for the policy to block. ### Errors `AntiSSRFError` * The `headers` argument is `null` or `undefined`. * Some `header` in `headers` is `null`, `undefined`, or whitespace. + +## Examples + +```js +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.addDeniedHeaders(['X-Real-IP', 'X-Forwarded-Host']); +const agent = policy.getHttpsAgent(); + +// This request will succeed (no denied headers) +const options = { + hostname: '<some_untrusted_hostname>', + path: '/public/data', + headers: { + 'User-Agent': 'MyApp/1.0', + 'Accept': 'application/json' + }, + agent: agent +}; + +https.get(options, (res) => { + console.log('Request successful - no denied headers present'); +}); + +// This request will be blocked (contains denied header) +const blockedOptions = { + hostname: '<some_untrusted_hostname>', + path: '/admin/endpoint', + headers: { + 'X-Real-IP': '192.168.1.1', // This header is denied + 'Accept': 'application/json' + }, + agent: agent +}; + +https.get(blockedOptions, (res) => { + // This will not execute - request will be blocked +}).on('error', (err) => { + console.log('Request blocked due to denied header:', err.message); +}); +``` diff --git a/docs/nodejs-api/antissrfpolicy/methods/addrequiredheaders.md b/docs/nodejs-api/antissrfpolicy/methods/addrequiredheaders.md index dbfbcfb..4cf8295 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/addrequiredheaders.md +++ b/docs/nodejs-api/antissrfpolicy/methods/addrequiredheaders.md @@ -4,7 +4,6 @@ title: addRequiredHeaders parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "addRequiredHeaders method documentation" --- @@ -12,10 +11,10 @@ description: "addRequiredHeaders method documentation" ## Definition -Adding to the list of headers explicitly required by the policy. Outgoing requests that are missing a required header will be blocked. +Adds headers to be explicitly required by the policy. Requests that are missing a required header will be blocked. ```js -addRequiredHeaders(networks: string[]): void +addRequiredHeaders(headers: string[]): void ``` {: .note } @@ -25,10 +24,55 @@ addRequiredHeaders(networks: string[]): void `headers`: `string[]` -* The list of headers for the policy to require. +The list of headers for the policy to require. ### Errors `AntiSSRFError` * The `headers` argument is `null` or `undefined`. * Some `header` in `headers` is `null`, `undefined`, or whitespace. + +## Examples + +```js +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.addRequiredHeaders(['Authorization', 'X-API-Key']); +const agent = policy.getHttpsAgent(); + +// This request will succeed (all required headers present) +const options = { + hostname: '<some_untrusted_hostname>', + path: '/secure/data', + headers: { + 'Authorization': 'Bearer token123', + 'X-API-Key': 'key456', + 'Accept': 'application/json' + }, + agent: agent +}; + +https.get(options, (res) => { + console.log('Request successful - all required headers present'); +}); + +// This request will be blocked (missing required header) +const blockedOptions = { + hostname: '<some_untrusted_hostname>', + path: '/secure/admin', + headers: { + 'Authorization': 'Bearer token123', + 'Accept': 'application/json' + }, + agent: agent +}; + +https.get(blockedOptions, (res) => { + // This will not execute - request will be blocked +}).on('error', (err) => { + console.log('Request blocked due to missing required header:', err.message); +}); +``` diff --git a/docs/nodejs-api/antissrfpolicy/methods/gethttpagent.md b/docs/nodejs-api/antissrfpolicy/methods/gethttpagent.md index 6323129..79c5977 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/gethttpagent.md +++ b/docs/nodejs-api/antissrfpolicy/methods/gethttpagent.md @@ -4,7 +4,6 @@ title: getHttpAgent parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "getHttpAgent method documentation" --- @@ -14,21 +13,59 @@ description: "getHttpAgent method documentation" Builds an `http.Agent` that will enforce the policy on all outgoing requests. +{: .warning } +> **HTTP is insecure**: HTTP requests send data in plaintext over the network. Using this HTTP agent when your policy does not allow plaintext connections will cause all requests to fail. For secure communications, use [`getHttpsAgent()`](gethttpsagent) instead. + ```js -getHttpAgent(options?: http.AgentOptions): void +getHttpAgent(options?: http.AgentOptions): http.Agent ``` ### Parameters `options`: `http.AgentOptions` -* The optional `http.AgentOptions` to pass to the new agent. +The optional `http.AgentOptions` to pass to the new agent. ### Errors `AntiSSRFError` -* The function `lookup` is included in `options`. -### Security Notes -* The agents utilizes `lookup` function to apply the policy. Attempts to overwrite the `lookup` function will result in errors. -* While not explicitly blocked, any use of proxies, like with `proxyEnv` in `options` or in clients that use the agents, will bypass the protections provided with the AntiSSRF library. +The function `lookup` is included in `options`. + +## Examples + +```js +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const http = require('http'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.allowPlainTextHttp = true; + +// Get HTTP agent with the configured policy +const httpAgent = policy.getHttpAgent(); + +const options = { + hostname: '<some_untrusted_hostname>', + port: 80, + path: '/public/data', + method: 'GET', + agent: httpAgent +}; + +const req = http.request(options, (res) => { + // If the untrusted hostname directs to an external address using HTTP, + // the request will succeed here +}); + +req.on('error', (err) => { + // If untrusted hostname directs to an internal or special-use address, + // the request will fail here with an AntiSSRF error +}); + +req.end(); +``` + +## Security Notes +* The agent utilizes the `lookup` function to apply the policy. Attempts to overwrite the `lookup` function will result in errors. +* While not explicitly blocked, any use of proxies, such as `proxyEnv` in `options` or in clients that use the agent, will bypass the protections provided by the AntiSSRF library. diff --git a/docs/nodejs-api/antissrfpolicy/methods/gethttpsagent.md b/docs/nodejs-api/antissrfpolicy/methods/gethttpsagent.md index f41033a..da31f7b 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/gethttpsagent.md +++ b/docs/nodejs-api/antissrfpolicy/methods/gethttpsagent.md @@ -4,7 +4,6 @@ title: getHttpsAgent parent: Methods grand_parent: AntiSSRFPolicy ancestor: Node.js API Reference -nav_order: 1 description: "getHttpsAgent method documentation" --- @@ -15,20 +14,54 @@ description: "getHttpsAgent method documentation" Builds an `https.Agent` that will enforce the policy on all outgoing requests. ```js -getHttpsAgent(options?: http.AgentOptions): void +getHttpsAgent(options?: https.AgentOptions): https.Agent ``` ### Parameters `options`: `https.AgentOptions` -* The optional `https.AgentOptions` to pass to the new agent. +The optional `https.AgentOptions` to pass to the new agent. ### Errors `AntiSSRFError` -* The function `lookup` is included in `options`. -### Security Notes -* The agents utilizes `lookup` function to apply the policy. Attempts to overwrite the `lookup` function will result in errors. -* While not explicitly blocked, any use of proxies, like with `proxyEnv` in `options` or in clients that use the agents, will bypass the protections provided with the AntiSSRF library. +The function `lookup` is included in `options`. + +## Examples + +```js +const { AntiSSRFPolicy, PolicyConfigOptions } = require('@microsoft/antissrf'); +const https = require('https'); + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Get HTTPS agent with the configured policy +const httpsAgent = policy.getHttpsAgent(); + +const options = { + hostname: '<some_untrusted_hostname>', + port: 443, + path: '/public/data', + method: 'GET', + agent: httpsAgent +}; + +const req = https.request(options, (res) => { + // If the untrusted hostname directs to an external address using HTTPS, + // the request will succeed here +}); + +req.on('error', (err) => { + // If untrusted hostname directs to an internal or special-use address, + // the request will fail here with an AntiSSRF error +}); + +req.end(); +``` + +## Security Notes +* The agent utilizes the `lookup` function to apply the policy. Attempts to overwrite the `lookup` function will result in errors. +* While not explicitly blocked, any use of proxies, such as `proxyEnv` in `options` or in clients that use the agent, will bypass the protections provided by the AntiSSRF library. diff --git a/docs/nodejs-api/antissrfpolicy/methods/index.md b/docs/nodejs-api/antissrfpolicy/methods/index.md index 0f8196f..ca2f349 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/index.md +++ b/docs/nodejs-api/antissrfpolicy/methods/index.md @@ -6,4 +6,22 @@ grand_parent: Node.js API Reference nav_order: 3 description: "AntiSSRFPolicy methods documentation" has_children: true +nav_fold: true +has_toc: false --- + +## Policy Customization Methods + +| Method | Description | +| --- | --- | +| [addAllowedAddresses(string[])](addallowedaddresses) | Adds IP networks to be explicitly allowed by the policy. | +| [addDeniedAddresses(string[])](adddeniedaddresses) | Adds IP networks to be explicitly blocked by the policy. | +| [addDeniedHeaders(string[])](adddeniedheaders) | Adds headers to be explicitly blocked by the policy. | +| [addRequiredHeaders(string[])](addrequiredheaders) | Adds headers to be explicitly required by the policy. | + +## Policy Use Methods + +| Method | Description | +| --- | --- | +| [getHttpAgent(any)](gethttpagent) | Builds an `http.Agent` that will enforce the policy on all outgoing requests. | +| [getHttpsAgent(any)](gethttpsagent) | Builds an `https.Agent` that will enforce the policy on all outgoing requests. | diff --git a/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md b/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md index b00b99e..a772baf 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md +++ b/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md @@ -11,20 +11,20 @@ description: "addXFFHeader property documentation" ## Definition -Determines whether the `X-Forwarded-For` header should be added to all requests where it is missing. +Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don’t already include it. {: .important } > The header is added with the dummy value `"true"`. If your end service requires this header to be a valid IP address, you will have to add the header manually. ```js -boolean addXFFHeader { get; set; } +addXFFHeader: boolean { get; set; } ``` ### Property Value `boolean` -* `true` if the `X-Forwarded-For` header should be added to requests where it is missing. +* `true` if the `X-Forwarded-For` header should be added to requests that don’t already include it. * `false` if the `X-Forwarded-For` header should not be added. ### Errors @@ -32,6 +32,6 @@ boolean addXFFHeader { get; set; } `AntiSSRFException` The value passed cannot be `null` or `undefined`. -### Security Notes +## Security Notes -The `X-Forwarded-For` header can be an important defense-in-depth strategy against SSRF vulnerabilities. Some services, including IMDS, will drop all incoming requests with the `X-Forwarded-For` present. By ensuring that the header is added to all outgoing requests, your service can be sure that it will never have an SSRF vulnerability that leaks data from IMDS. +The `X-Forwarded-For` header can be an important defense-in-depth strategy against SSRF vulnerabilities. Some services, including IMDS, will drop all incoming requests with the `X-Forwarded-For` header present. By ensuring that the header is added to all outgoing requests, your service can be sure that it will never have an SSRF vulnerability that leaks data from IMDS. diff --git a/docs/nodejs-api/antissrfpolicy/properties/allowedaddresses.md b/docs/nodejs-api/antissrfpolicy/properties/allowedaddresses.md index f520e19..bf4ab72 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/allowedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/properties/allowedaddresses.md @@ -11,17 +11,17 @@ description: "allowedAddresses property documentation" ## Definition -The `BlockList` of IP address ranges explicitly allowed by the policy. +The [`BlockList`](https://nodejs.org/api/net.html#class-netblocklist) of IP networks explicitly allowed by the policy. ```js -ReadOnly<BlockList> allowedAddresses { get; } +allowedAddresses: ReadOnly<BlockList> { get; } ``` {: .note } -> `allowedAddresses` takes precedence over `deniedAddresses`, if if an IP address matches both, it will be considered allowed by the policy. +> `allowedAddresses` takes precedence over `deniedAddresses`. If an IP address matches both, it will be considered allowed by the policy. ### Property Value `ReadOnly<BlockList>` -The `ReadOnly` version of the `net.Blocklist` storing the allowed IP addresses. +The `ReadOnly` version of the `net.BlockList` storing the allowed IP networks. diff --git a/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md b/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md index 12ae389..90bf957 100755 --- a/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md +++ b/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md @@ -10,18 +10,18 @@ description: "allowPlainTextHttp property documentation" # AntiSSRFPolicy.allowPlainTextHttp Property {: .warning } -> Changing an `AntiSSRFPolicy` instance to allow plaintext HTTP means you will be able to send HTTP requests without the required TLS encryption. +> Changing an `AntiSSRFPolicy` instance to allow plaintext HTTP means you will be able to send HTTP requests without the recommended TLS encryption. ## Definition Determines whether HTTPS is required or HTTP is allowed. ```js -boolean allowPlainTextHttp { get; set; } +allowPlainTextHttp: boolean { get; set; } ``` {: .note } -> With ALL configuration options, HTTP is disallowed unless `allowPaintextHttp` is explicitly set to `true`. +> With ALL configuration options, HTTP is disallowed unless `allowPlainTextHttp` is explicitly set to `true`. ### Property Value diff --git a/docs/nodejs-api/antissrfpolicy/properties/deniedaddresses.md b/docs/nodejs-api/antissrfpolicy/properties/deniedaddresses.md index d46e62d..5445ebd 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/deniedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/properties/deniedaddresses.md @@ -11,20 +11,20 @@ description: "deniedAddresses property documentation" ## Definition -The `BlockList` of IP address ranges explicitly blocked by the policy. +The [`BlockList`](https://nodejs.org/api/net.html#class-netblocklist) of IP networks explicitly blocked by the policy. ```js -ReadOnly<BlockList> deniedAddresses { get; } +deniedAddresses: ReadOnly<BlockList> { get; } ``` {: .note } -> `allowedAddresses` takes precedence over `deniedAddresses`, if if an IP address matches both, it will be considered allowed by the policy. +> `allowedAddresses` takes precedence over `deniedAddresses`. If an IP address matches both, it will be considered allowed by the policy. {: .note } -> `denyAllUnspecifiedIPs` takes precedence over `deniedAddresses`, if `denyAllUnspecifiedIPs` is `true`, `deniedAddresses` will not be considered when determining if an IP address is allowed or blocked by the policy. +> `denyAllUnspecifiedIPs` takes precedence over `deniedAddresses`. If `denyAllUnspecifiedIPs` is `true`, `deniedAddresses` will not be considered when determining if an IP address is allowed or blocked by the policy. ### Property Value `ReadOnly<BlockList>` -The `ReadOnly` version of the `net.Blocklist` storing the denied IP addresses. +The `ReadOnly` version of the `net.BlockList` storing the denied IP networks. diff --git a/docs/nodejs-api/antissrfpolicy/properties/deniedheaders.md b/docs/nodejs-api/antissrfpolicy/properties/deniedheaders.md index 2cae3d0..c9f011a 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/deniedheaders.md +++ b/docs/nodejs-api/antissrfpolicy/properties/deniedheaders.md @@ -11,10 +11,10 @@ description: "deniedHeaders property documentation" ## Definition -The readonly copy of the list of headers explicitly blocked by the policy. Outgoing requests that include a denied header will be blocked. +A read-only array of headers that are forbidden from being included in outgoing requests. ```js -readonly string[] deniedHeaders { get; } +deniedHeaders: readonly string[] { get; } ``` {: .note } @@ -24,4 +24,4 @@ readonly string[] deniedHeaders { get; } `readonly string[]` -The readonly copy of the list of headers explicitly blocked by the policy. +A read-only array of header names that are blocked by the policy. diff --git a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md index ffda190..5cec6f9 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md +++ b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md @@ -11,11 +11,13 @@ description: "denyAllUnspecifiedIPs property documentation" ## Definition -Determines whether all IP addresses should be blocked by default or only `deniedAddresses` IP addresses should be blocked. -To allow specific addresses, use `addAllowedAddresses`. +Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. + +{: .note } +> To allow specific addresses, use `addAllowedAddresses`. ```js -boolean denyAllUnspecifiedIPs { get; set; } +denyAllUnspecifiedIPs: boolean { get; set; } ``` ### Property Value diff --git a/docs/nodejs-api/antissrfpolicy/properties/index.md b/docs/nodejs-api/antissrfpolicy/properties/index.md index 2a0c94a..e6127c6 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/index.md +++ b/docs/nodejs-api/antissrfpolicy/properties/index.md @@ -7,4 +7,17 @@ nav_order: 2 description: "AntiSSRFPolicy properties documentation" has_children: true nav_fold: true +has_toc: false --- + +# AntiSSRFPolicy Properties + +| Property | Description | +| --- | --- | +| [addXFFHeader](addxffheader) | Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don't already include it. | +| [allowedAddresses](allowedaddresses) | List of IP networks that are explicitly allowed by the policy. | +| [allowPlainTextHttp](allowplaintexthttp) | Determines whether HTTPS is required or HTTP is allowed. | +| [deniedAddresses](deniedaddresses) | List of IP networks that are explicitly blocked by the policy. | +| [deniedHeaders](deniedheaders) | List of headers that are forbidden from being included in outgoing requests. | +| [denyAllUnspecifiedIPs](denyallunspecifiedips) | Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. | +| [requiredHeaders](requiredheaders) | List of headers that are required to be present in outgoing requests. | diff --git a/docs/nodejs-api/antissrfpolicy/properties/requiredheaders.md b/docs/nodejs-api/antissrfpolicy/properties/requiredheaders.md index b410eea..2e9e4de 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/requiredheaders.md +++ b/docs/nodejs-api/antissrfpolicy/properties/requiredheaders.md @@ -11,10 +11,10 @@ description: "requiredHeaders property documentation" ## Definition -The readonly copy of the list of headers explicitly required by the policy. Outgoing requests that are missing a required header will be blocked. +A read-only array of headers that are required to be present in outgoing requests. ```js -readonly string[] requiredHeaders { get; } +requiredHeaders: readonly string[] { get; } ``` {: .note } @@ -24,4 +24,4 @@ readonly string[] requiredHeaders { get; } `readonly string[]` -The readonly copy of the list of headers explicitly required by the policy. +A read-only array of header names that are required by the policy. diff --git a/docs/nodejs-api/changelog.md b/docs/nodejs-api/changelog.md index 9431ccc..aa0cb25 100644 --- a/docs/nodejs-api/changelog.md +++ b/docs/nodejs-api/changelog.md @@ -3,12 +3,12 @@ layout: default title: Changelog parent: Node.js API Reference nav_order: 99 -description: "Release notes and version history for AntiSSRF NodeJS" +description: "Release notes and version history for AntiSSRF Node.js Library" --- # Changelog -All notable changes to the AntiSSRF NodeJS library will be documented in this file. +All notable changes to the AntiSSRF Node.js Library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/docs/nodejs-api/index.md b/docs/nodejs-api/index.md index d6a297e..988cb95 100755 --- a/docs/nodejs-api/index.md +++ b/docs/nodejs-api/index.md @@ -2,32 +2,32 @@ layout: default title: Node.js API Reference nav_order: 4 -description: "Complete API documentation for the AntiSSRF Node.js library" +description: "Complete API documentation for the AntiSSRF Node.js Library" has_children: true has_toc: false --- # API Documentation -## AntiSSRF JavaScript Library +## AntiSSRF Node.js Library -The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as a Node.js HTTP(S) Agent and URL validator, depending on use-case. +The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as [Node.js HTTP(S) agents](https://nodejs.org/api/http.html#class-httpagent) and a URL validator, depending on use case. ## Usage Instructions -There are four different ways to use this library, depending on your specific case. Identify the use case below based on the URLs your code is accessing. +The AntiSSRF library provides validation for different scenarios based on your trust requirements: -| Use Case | Steps | -| --- | --- | -| The URL you are accessing must always belong to a **specific, trsuted domain**. | See URIValidator.inDomain. | -| The URL you are accessing must be an **Azure Storage endpoint**. | See URIValidator.inAzureStorageDomain. | -| The URL you are accessing must be an **Azure Key Vault endpoint**. | See URIValidator.inAzureKeyVaultDomain. | -| The URL you are accessing can belong to **any domain** or an **untrusted domain**, so to prevent SSRF vulnerabilities, you must ensure that it does not resolve to internal and special-purpose IP addresses. | See AntiSSRFPolicy. | +| Use Case | Description | Documentation Link | +| --- | --- | --- | +| **General Case** | The untrusted URL can belong to **any domain** or an **untrusted domain**. | [AntiSSRFPolicy](antissrfpolicy) | +| **Azure Key Vault Domain** | The untrusted URL must be an **Azure Key Vault endpoint**. | [URIValidator.inAzureKeyVaultDomain](urivalidator/inazurekeyvaultdomain) | +| **Azure Storage Domain** | The untrusted URL must be an **Azure Storage endpoint**. | [URIValidator.inAzureStorageDomain](urivalidator/inazurestoragedomain) | +| **Allowlist of Trusted Domains** | The untrusted URL must belong to a **specific, trusted domain**. | [URIValidator.inDomain](urivalidator/indomain) | ## Classes | Class | Description | | --- | --- | -| [AntiSSRFPolicy](antissrfpolicy/) | Represents a customizable security policy and provides HTTP(S) agents to ensure all outgoing requests match the security policy. | -| [IPAddressRanges](../ipaddressranges.html) | Provides predefined IP address ranges for use with AntiSSRF policies. | -| [URIValidator](urivalidator/) | Provides methods for validating the hostname of URLs. | +| [AntiSSRFPolicy](antissrfpolicy) | Represents a customizable security policy and provides HTTP(S) agents to ensure all outgoing requests match the security policy. | +| [IPAddressRanges](../ipaddressranges) | Provides predefined IP address ranges for use with AntiSSRF policies. | +| [URIValidator](urivalidator) | Provides methods for validating the hostname of URLs. | diff --git a/docs/nodejs-api/urivalidator/inazurekeyvaultdomain.md b/docs/nodejs-api/urivalidator/inazurekeyvaultdomain.md index 5f67298..6e1ee0f 100755 --- a/docs/nodejs-api/urivalidator/inazurekeyvaultdomain.md +++ b/docs/nodejs-api/urivalidator/inazurekeyvaultdomain.md @@ -3,7 +3,6 @@ layout: default title: inAzureKeyVaultDomain parent: URIValidator grand_parent: Node.js API Reference -nav_order: 3 description: "Check if a URI belongs to Azure Key Vault domains" --- @@ -13,18 +12,18 @@ description: "Check if a URI belongs to Azure Key Vault domains" The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to an **Azure Key Vault Domain**. +The URL is expected to belong to an [**Azure Key Vault Domain**](#azure-key-vault-domain-names). {: .note } -> * If you instead expect the domain to be another **specific, trusted domain**, see [inDomain](indomain.html). -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [inAzureStorageDomain](inazurestoragedomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [inAzureStorageDomain](inazurestoragedomain). +> * If you instead expect the domain to be another **specific, trusted domain**, see [inDomain](indomain). ## Definition -Validates if `url` is an Azure Key Vault endpoint. +Validates if a URL is an Azure Key Vault endpoint. ```js inAzureKeyVaultDomain(url: URL | string): boolean @@ -41,6 +40,18 @@ The URL to be evaluated. * `true` if `url` belongs to any of the listed Azure Key Vault domains. * `false` if `url` does not belong to any of the listed Azure Key Vault domains, the `url` is not a valid URL, or the protocol is not HTTP/S. +## Examples + +```js +const { URIValidator } = require('@microsoft/antissrf'); + +URIValidator.inAzureKeyVaultDomain('https://myvault.vault.azure.net/secrets/api-key'); +// β†’ true + +URIValidator.inAzureKeyVaultDomain('https://evil.com/secrets'); +// β†’ false +``` + ## Azure Key Vault Domain Names `inAzureKeyVaultDomain` will evaluate whether the given parameter belongs to any of the following domains: diff --git a/docs/nodejs-api/urivalidator/inazurestoragedomain.md b/docs/nodejs-api/urivalidator/inazurestoragedomain.md index c892e68..92f4d57 100755 --- a/docs/nodejs-api/urivalidator/inazurestoragedomain.md +++ b/docs/nodejs-api/urivalidator/inazurestoragedomain.md @@ -3,7 +3,6 @@ layout: default title: inAzureStorageDomain parent: URIValidator grand_parent: Node.js API Reference -nav_order: 2 description: "Check if a URI belongs to Azure Storage domains" --- @@ -13,18 +12,18 @@ description: "Check if a URI belongs to Azure Storage domains" The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to an **Azure Storage Domain**. +The URL is expected to belong to an [**Azure Storage Domain**](#azure-storage-domain-names). {: .note } -> * If you instead expect the domain to be another **specific, trusted domain**, see [inDomain](indomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [inAzureKeyVaultDomain](inazurekeyvaultdomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [inAzureKeyVaultDomain](inazurekeyvaultdomain). +> * If you instead expect the domain to be another **specific, trusted domain**, see [inDomain](indomain). ## Definition -Validates if `url` is an Azure Storage endpoint. +Validates if a URL is an Azure Storage endpoint. ```js inAzureStorageDomain(url: URL | string): boolean @@ -41,6 +40,18 @@ The URL to be evaluated. * `true` if `url` belongs to any of the listed Azure Storage domains. * `false` if `url` does not belong to any of the listed Azure Storage domains, the `url` is not a valid URL, or the protocol is not HTTP/S. +## Examples + +```js +const { URIValidator } = require('@microsoft/antissrf'); + +URIValidator.inAzureStorageDomain('https://mystorageaccount.blob.core.windows.net/container/file.txt'); +// β†’ true + +URIValidator.inAzureStorageDomain('https://evil.com/data'); +// β†’ false +``` + ## Azure Storage Domain Names `inAzureStorageDomain` will evaluate whether the given parameter belongs to any combination of the following domains and services: diff --git a/docs/nodejs-api/urivalidator/index.md b/docs/nodejs-api/urivalidator/index.md index e5cc0c9..9a57c49 100755 --- a/docs/nodejs-api/urivalidator/index.md +++ b/docs/nodejs-api/urivalidator/index.md @@ -3,7 +3,9 @@ layout: default title: URIValidator parent: Node.js API Reference description: "URL validation class for SSRF protection" +nav_order: 2 has_children: true +has_toc: false --- # URIValidator Class @@ -12,12 +14,12 @@ has_children: true The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to a specific set of trusted domains, the Azure Storage domains, or the Azure Key Vault domains. +The URL is expected to belong to a specific set of trusted domains, the [Azure Storage domains](inazurestoragedomain#azure-storage-domain-names), or the [Azure Key Vault domains](inazurekeyvaultdomain#azure-key-vault-domain-names). {: .note } -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see AntiSSRFPolicy. +> If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). ## Definition @@ -27,7 +29,7 @@ Provides methods for validating the hostname and protocol of URLs. | Method | Description | | --- | --- | -| `inDomain(url: URL | string, domain: string)` | Validates if `url` belongs to `domain`. | -| `inDomain(url: URL | string, domains: string[])` | Validates if `url` belongs to any domain in `domains`. | -| `inAzureKeyVaultDomain(url: URL | string)` | Validates if `url` is an Azure Key Vault endpoint. | -| `inAzureStorageDomain(url: URL | string)` | Validates if `url` is an Azure Storage endpoint. | +| [inAzureKeyVaultDomain(URL \| string)](inazurekeyvaultdomain) | Validates if a URL is an Azure Key Vault endpoint. | +| [inAzureStorageDomain(URL \| string)](inazurestoragedomain) | Validates if a URL is an Azure Storage endpoint. | +| [inDomain(URL \| string, string)](indomain) | Validates if a URL belongs to a trusted domain. | +| [inDomain(URL \| string, string[])](indomain) | Validates if a URL belongs to any of a list of trusted domains. | diff --git a/docs/nodejs-api/urivalidator/indomain.md b/docs/nodejs-api/urivalidator/indomain.md index 7504fc6..5d12c7d 100755 --- a/docs/nodejs-api/urivalidator/indomain.md +++ b/docs/nodejs-api/urivalidator/indomain.md @@ -3,82 +3,92 @@ layout: default title: inDomain parent: URIValidator grand_parent: Node.js API Reference -nav_order: 1 description: "Check if a URI belongs to specified domain(s)" --- ---- -uid: indomain ---- - # URIValidator.inDomain Method ## Use Case The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** The URL is expected to belong to a **specific set of trusted domains**. {: .note } -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [inAzureStorageDomain](inazurestoragedomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [inAzureKeyVaultDomain](inazurekeyvaultdomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [inAzureKeyVaultDomain](inazurekeyvaultdomain). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [inAzureStorageDomain](inazurestoragedomain). {: .important } -> If your untrusted URL needs to belong to a specific domain, but you do not fully control all subdomains of the domain, you can use BOTH `inDomain` AND `AntiSSRFPolicy` to be protected. +> If your untrusted URL needs to belong to a specific domain, but you do not fully control all subdomains of the domain, you can use BOTH `inDomain` AND `AntiSSRFPolicy` to be protected. If the untrusted URL belongs to a domain that cannot be fully trusted, at least `AntiSSRFPolicy` is required for full protection. ## Definition -Validates if the given input belongs to any of the specified domains. +Validates if a URL belongs to any of a list of trusted domains. ## Overloads | Method | Description | | --------------- | --------------- | -| `inDomain(url: URL | string, domain: string): boolean` | Validates if `url` belongs to `domain`. | -| `inDomain(url: URL | string, domains: string[]): boolean` | Validates if `url` belongs to any domain in `domains`. | +| [inDomain(URL \| string, string): boolean](#indomainurl-url--string-domain-boolean) | Validates if a URL belongs to a trusted domain. | +| [inDomain(URL \| string, string[]): boolean](#indomainurl-url--string-domains-string-boolean) | Validates if a URL belongs to any of a list of trusted domains. | -## inDomain(url: URL | string, domain): boolean +## inDomain(URL | string, string): boolean ```js -inDomain(url: URL | string, domain: string): boolean +inDomain(untrustedUrl: URL | string, trustedDomain: string): boolean ``` ### Parameters -`url`: `URL | string` +`untrustedUrl`: `URL | string` The URL to be evaluated. -`domain`: `string` +`trustedDomain`: `string` -The domain name that `url` will be compared against. +The domain name that `untrustedUrl` will be compared against. ### Returns -* `true` if `url` belongs to `domain`. -* `false` if `url` does not belong `domain`, if `url` cannot be converted to a valid `URL`, if protocol is not HTTP/S or WS/S, or if either argument is invalid. +* `true` if `untrustedUrl` belongs to `trustedDomain`. +* `false` if `untrustedUrl` does not belong to `trustedDomain`, if `untrustedUrl` cannot be converted to a valid `URL`, if protocol is not HTTP/S or WS/S, or if either argument is invalid. -## inDomain(url: URL | string, domains: string[]): boolean +## inDomain(URL | string, string[]): boolean ```js -inDomain(url: URL | string, domains: string[]): boolean +inDomain(untrustedUrl: URL | string, trustedDomains: string[]): boolean ``` ### Parameters -`url`: `URL | string` +`untrustedUrl`: `URL | string` The URL to be evaluated. -`domains`: `string[]` +`trustedDomains`: `string[]` -The list of domain names that `url` will be compared against. +The list of domain names that `untrustedUrl` will be compared against. ### Returns -* `true` if `url` belongs to any domain in `domains`. -* `false` if `url` does not belong any domain in `domains`, if `url` cannot be converted to a valid `URL`, if protocol is not HTTP/S or WS/S, or if either argument is invalid. +* `true` if `untrustedUrl` belongs to any domain in `trustedDomains`. +* `false` if `untrustedUrl` does not belong to any domain in `trustedDomains`, if `untrustedUrl` cannot be converted to a valid `URL`, if protocol is not HTTP/S or WS/S, or if either argument is invalid. + +## Examples + +```javascript +const { URIValidator } = require('@microsoft/antissrf'); + +URIValidator.inDomain('https://api.mycompany.com/data', 'mycompany.com'); +// β†’ true + +URIValidator.inDomain('https://api.mycompany.com/data', ['mycompany.com', 'trusted.com']); +// β†’ true + +URIValidator.inDomain('https://evil.com/secrets', 'mycompany.com'); +// β†’ false +``` From b17f72be95738e5dae813c5d294652542d008024 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Mon, 4 May 2026 01:09:15 -0700 Subject: [PATCH 3/7] nodejs api --- docs/dotnet-api/antissrfhandler.md | 100 +++++------------- docs/dotnet-api/antissrfpolicy/constructor.md | 73 ++++--------- docs/dotnet-api/antissrfpolicy/index.md | 80 +++++--------- .../methods/addallowedaddresses.md | 45 +++++--- .../methods/adddeniedaddresses.md | 47 +++++--- .../methods/adddeniedheaders.md | 48 ++++++++- .../methods/addrequiredheaders.md | 51 ++++++++- .../antissrfpolicy/methods/gethandler.md | 12 +-- .../antissrfpolicy/methods/index.md | 20 +++- .../antissrfpolicy/properties/addxffheader.md | 8 +- .../properties/allowedaddresses.md | 6 +- .../properties/allowplaintexthttp.md | 8 +- .../properties/deniedaddresses.md | 6 +- .../properties/deniedheaders.md | 6 +- .../properties/denyallunspecifiedips.md | 8 +- .../antissrfpolicy/properties/index.md | 15 ++- .../properties/requiredheaders.md | 6 +- docs/dotnet-api/changelog.md | 6 +- docs/dotnet-api/index.md | 28 ++--- .../urivalidator/inazurekeyvaultdomain.md | 52 +++++---- .../urivalidator/inazurestoragedomain.md | 52 +++++---- docs/dotnet-api/urivalidator/index.md | 32 +++--- docs/dotnet-api/urivalidator/indomain.md | 46 ++++++-- docs/nodejs-api/antissrfpolicy/constructor.md | 2 +- .../methods/addallowedaddresses.md | 2 +- .../methods/adddeniedaddresses.md | 2 +- .../antissrfpolicy/properties/addxffheader.md | 2 +- .../properties/allowplaintexthttp.md | 2 +- .../properties/denyallunspecifiedips.md | 2 +- docs/nodejs-api/index.md | 4 +- docs/nodejs-api/urivalidator/index.md | 2 +- 31 files changed, 430 insertions(+), 343 deletions(-) diff --git a/docs/dotnet-api/antissrfhandler.md b/docs/dotnet-api/antissrfhandler.md index 314b934..fd7ab78 100644 --- a/docs/dotnet-api/antissrfhandler.md +++ b/docs/dotnet-api/antissrfhandler.md @@ -1,88 +1,44 @@ --- layout: default title: AntiSSRFHandler -parent: C# API Reference +parent: .NET API Reference +nav_order: 2 description: "HttpMessageHandler that enforces AntiSSRF policies" --- -# AntiSSRFHandler Class +# AntiSSRFHandler -## Definition +`AntiSSRFHandler` is the type of the object returned from `AntiSSRFPolicy.GetHandler`. The `AntiSSRFHandler` wraps `HttpClientHandler` or `HttpSocketsHandler` and implements `HttpMessageHandler` while exposing some properties on the inner handler. This handler performs DNS resolution validation, scheme enforcement, header checks, and redirect following according to the configured policy. -Namespace: `Microsoft.Security.AntiSSRF` +### .NET Core -An `HttpMessageHandler` that enforces the `AntiSSRFPolicy` on all outgoing HTTP requests made via `HttpClient`. This handler performs DNS resolution validation, scheme enforcement, header checks, and redirect following according to the configured policy. +In .NET Core, the inner handler is an `HttpSocketsHandler`. The exposed properties below can be used exactly as they are used in the original `HttpSocketsHandler` type. Please see [HttpSocketsHandler](https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpsocketshandler) for details. ```csharp -public sealed class AntiSSRFHandler : HttpMessageHandler +- public bool AllowAutoRedirect { get; set; } +- public int MaxAutomaticRedirections { get; set; } +- public CookieContainer CookieContainer { get; set; } +- public ICredentials? Credentials { get; set; } +- public int MaxConnectionsPerServer { get; set; } +- public int MaxResponseHeadersLength { get; set; } +- public bool UseCookies { get; set; } +- public TimeSpan ConnectTimeout { get; set; } +- public TimeSpan ResponseDrainTimeout { get; set; } +- public TimeSpan PooledConnectionLifetime { get; set; } +- public SslClientAuthenticationOptions SslOptions { get; set; } ``` -## Remarks +### .NET Standard 2.0 / .NET Framework -`AntiSSRFHandler` instances are created via `AntiSSRFPolicy.GetHandler()` and should not be constructed directly. The handler is designed to be used with `HttpClient`: +In .NET Standard 2.0 / .NET Framework, the inner handler is an `HttpClientHandler`. The exposed properties below can be used exactly as they are used in the original `HttpClientHandler` type. Please see [HttpClientHandler](https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler) for details. ```csharp -var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); -using var handler = policy.GetHandler(); -using var client = new HttpClient(handler); -``` - -The handler enforces the policy at two levels: -1. **HTTP request validation** β€” Checks the request scheme, denied/required headers, and optionally adds the `X-Forwarded-For` header. -2. **Network connection validation** β€” On .NET Core, uses a custom `ConnectCallback` to resolve DNS and verify IP addresses against the policy before establishing a TCP connection. On .NET Standard, validates IP addresses in the `SendAsync` override. - -The handler also manages redirects internally, re-validating the policy on each redirect hop. - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| `AllowAutoRedirect` | `bool` | Gets or sets whether the handler should automatically follow HTTP redirects. Default: `true`. | -| `MaxAutomaticRedirections` | `int` | Gets or sets the maximum number of redirects to follow. Default: `50`. | -| `Credentials` | `ICredentials?` | Gets or sets the credentials to use for outgoing requests. | -| `MaxConnectionsPerServer` | `int` | Gets or sets the maximum number of concurrent connections per server. | -| `MaxResponseHeadersLength` | `int` | Gets or sets the maximum length of response headers in kilobytes. | - -### .NET Core Only Properties - -| Property | Type | Description | -| --- | --- | --- | -| `CookieContainer` | `CookieContainer` | Gets or sets the cookie container for outgoing requests. | -| `UseCookies` | `bool` | Gets or sets whether cookies should be sent with requests. | -| `ConnectTimeout` | `TimeSpan` | Gets or sets the timeout for establishing a connection. | -| `ResponseDrainTimeout` | `TimeSpan` | Gets or sets the timeout for draining the response content. | -| `PooledConnectionIdleTimeout` | `TimeSpan` | Gets or sets the idle timeout for pooled connections. | -| `PooledConnectionLifetime` | `TimeSpan` | Gets or sets the maximum lifetime for pooled connections. | -| `SslOptions` | `SslClientAuthenticationOptions` | Gets or sets the SSL/TLS options for outgoing requests. | - -### .NET Standard Only Properties - -| Property | Type | Description | -| --- | --- | --- | -| `CheckCertificateRevocationList` | `bool` | Gets or sets whether the certificate revocation list is checked during SSL/TLS handshake. | -| `ServerCertificateCustomValidationCallback` | `Func<...>?` | Gets or sets a custom callback for server certificate validation. | -| `SslProtocols` | `SslProtocols` | Gets or sets the SSL/TLS protocols to use. | - -## Exceptions - -All properties throw `ObjectDisposedException` if the handler has been disposed, and `InvalidOperationException` if modified after a request has been sent. - -`MaxAutomaticRedirections` throws `ArgumentOutOfRangeException` if set to a value less than or equal to 0. - -## Example - -```csharp -using Microsoft.Security.AntiSSRF; -using System.Net.Http; - -var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); - -using var handler = policy.GetHandler(); -handler.AllowAutoRedirect = true; -handler.MaxAutomaticRedirections = 10; - -string untrustedUri = "<some_uri_constructed_with_untrusted_input>"; - -using var client = new HttpClient(handler); -var response = await client.GetAsync(untrustedUri); -``` +- public bool AllowAutoRedirect { get; set; } +- public int MaxAutomaticRedirections { get; set; } +- public ICredentials? Credentials { get; set; } +- public int MaxConnectionsPerServer { get; set; } +- public int MaxResponseHeadersLength { get; set; } +- public bool CheckCertificateRevocationList { get; set; } +- public Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool>? ServerCertificateCustomValidationCallback { get; set; } +- public SslProtocols SslProtocols { get; set; } +``` \ No newline at end of file diff --git a/docs/dotnet-api/antissrfpolicy/constructor.md b/docs/dotnet-api/antissrfpolicy/constructor.md index c09b32f..8b35e41 100644 --- a/docs/dotnet-api/antissrfpolicy/constructor.md +++ b/docs/dotnet-api/antissrfpolicy/constructor.md @@ -1,8 +1,8 @@ --- layout: default title: Constructor -parent: AntiSSRFPolicy (C#) -grand_parent: C# API Reference +parent: AntiSSRFPolicy +grandparent: .NET API Reference nav_order: 1 description: "AntiSSRFPolicy constructor documentation" --- @@ -11,74 +11,41 @@ description: "AntiSSRFPolicy constructor documentation" ## Definition -Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. +Creates a new [AntiSSRFPolicy](../) instance with a predefined security configuration. -```csharp -public AntiSSRFPolicy(PolicyConfigOptions config) +```cs +AntiSSRFPolicy(config: PolicyConfigOptions) ``` ### Parameters `config`: `PolicyConfigOptions` -* `PolicyConfigOptions.InternalOnly` -* `PolicyConfigOptions.ExternalOnlyV1` -* `PolicyConfigOptions.ExternalOnlyLatest` -* `PolicyConfigOptions.None` +Choose from the following predefined policy configurations: -### Exceptions +### PolicyConfigOptions -`ArgumentOutOfRangeException` -Thrown when an invalid `PolicyConfigOptions` value is provided. - -### PolicyConfigOptions.InternalOnly - -Recommended when: -* The policy should enforce requests only reach internal addresses, blocking all requests to external addresses. -* **OR** the policy should enforce requests only reach addresses specified by `AddAllowedAddresses`. - -Configuration: -* Sets `DenyAllUnspecifiedIPs` to `true`, blocking all requests to all IP addresses by default, only allowing requests to IP addresses that have been explicitly specified by `AddAllowedAddresses`. - -### PolicyConfigOptions.ExternalOnlyV1 - -Recommended when: -* The policy should enforce that requests should not reach any internal or special-purpose address, unless otherwise specified by `AddAllowedAddresses`. - -Configuration: -* Blocks all requests to internal and special-purpose addresses as specified by `IPAddressRanges.recommendedV1`. This excludes any address ranges that have been explicitly specified by `AddAllowedAddresses`. -* Sets `AddXFFHeader` to `true` on all outgoing requests that do not already have the header. This can be disabled with `policy.AddXFFHeader = false`. - -### PolicyConfigOptions.ExternalOnlyLatest +| Option | Use Case | Behavior | +| --- | --- | --- | +| **InternalOnly** | Making requests to internal addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [AddAllowedAddresses](../methods/addallowedaddresses). | +| **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedrangesv1). Automatically adds `X-Forwarded-For` header to requests. | +| **ExternalOnlyLatest** | Currently the same as `ExternalOnlyV1` with automatic security updates | Always stays up to date with the latest `ExternalOnly` version, independent of semantic versioning. | +| **None** | Custom policy configuration | No restrictions applied. Requires manual configuration via policy methods. | {: .important } -> This policy does NOT follow semantic versioning. It will always stay up-to-date with the latest recommended addresses with no code changes required by the user. - -Recommended when: -* Currently the same as `PolicyConfigOptions.ExternalOnlyV1`, if you want your security requirements updated automatically and are okay with changes that are not reflected in the package's semantic version. - -Configuration: -* Currently the same as `PolicyConfigOptions.ExternalOnlyV1`. - -### PolicyConfigOptions.None - -Recommended when: -* You plan to manually configure all policy customizations. - -Configuration: -* Unless customized, this policy will not update any requests and will not block any requests. +> `PolicyConfigOptions.ExternalOnlyLatest` does NOT follow semantic versioning. It will always stay up-to-date with the latest recommended addresses with no code changes required by the user. -### Security Notes +## Security Notes To prevent SSRF vulnerabilities, it is a best practice to ensure that your code can make requests to external endpoints or to internal endpoints, but never both. -If your service needs to make outbound requests to external endpoints, you need to make sure that it can't be used to access internal endpoints as well. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. +If your service needs to make requests to external endpoints, you need to make sure that it can’t be abused to access internal resources. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. -If your service needs to make outbound requests to internal endpoints, you need to make sure that it can't be used to access external endpoints as well. In this case, we recommend using `PolicyConfigOptions.InternalOnly` to block all unspecified addresses, then use `AddAllowedAddresses(...)` with the specific internal IP addresses that your service might need to access. +If your service needs to make requests to backend services, you must prevent data exfiltration by ensuring it cannot be used to send data to external endpoints. In this case, we recommend using `PolicyConfigOptions.InternalOnly` to block all unspecified addresses, then use `AddAllowedAddresses(...)` with the specific internal IP addresses that your service might need to access. -For more about the `X-Forwarded-For` header, see [AddXFFHeader](properties/addxffheader.html). +For more about the `X-Forwarded-For` header, see [addXFFHeader](../properties/addxffheader). -### Immutability After Handler Creation +## Immutability After Handler Creation -{: .warning } +{: .note } > Once `GetHandler()` is called, the policy becomes immutable. Any attempt to change properties or call customization methods will throw an `AntiSSRFException`. diff --git a/docs/dotnet-api/antissrfpolicy/index.md b/docs/dotnet-api/antissrfpolicy/index.md index 874c1f2..952218f 100644 --- a/docs/dotnet-api/antissrfpolicy/index.md +++ b/docs/dotnet-api/antissrfpolicy/index.md @@ -1,91 +1,59 @@ --- layout: default title: AntiSSRFPolicy -parent: C# API Reference +parent: .NET API Reference description: "Main policy configuration class for SSRF protection" +nav_order: 1 has_children: true +has_toc: false --- # AntiSSRFPolicy Class ## Use Case -You would use this class whenever you are accessing a URL that can belong to **any domain** or **some untrusted domain**. +Use this class whenever you are accessing a URL that can belong to **any domain** or **some untrusted domain**. -When you are accessing a URL that was constructed with external input (user input or input from other services), you need to make sure the final constructed URL cannot be abused to access unexpected internal endpoints. This class allows you to use built-in configurations or customize your own policy, then provides an [`AntiSSRFHandler`](../antissrfhandler.html) (an `HttpMessageHandler`) that will enforce that policy across all `HttpClient` requests and redirects. +This use case addresses two distinct security scenarios. For requests to external endpoints, the policy enforces that IP addresses are not internal or special-use addresses, preventing URLs from being abused to gain access to internal resources. For requests to backend resources, the policy blocks all IP addresses except for specific ranges that you expect to see, ensuring that URLs cannot be used to exfiltrate data to unauthorized destinations. {: .note } -> * If you instead expect the domain to be a **specific, trusted domain**, see [URIValidator.InDomain](../urivalidator/indomain.html). -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [URIValidator.InAzureStorageDomain](../urivalidator/inazurestoragedomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [URIValidator.InAzureKeyVaultDomain](../urivalidator/inazurekeyvaultdomain.html). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [URIValidator.InAzureKeyVaultDomain](../urivalidator/inazurekeyvaultdomain). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [URIValidator.InAzureStorageDomain](../urivalidator/inazurestoragedomain). +> * If you instead expect the domain to be a **specific, trusted domain**, see [URIValidator.InDomain](../urivalidator/indomain). ## Definition -Namespace: `Microsoft.Security.AntiSSRF` - -Represents a customizable security policy and provides an `AntiSSRFHandler` to ensure all outgoing `HttpClient` requests match the security policy. - -```csharp -public class AntiSSRFPolicy -``` +The `AntiSSRFPolicy` allows you to customize security requirements for headers, IP addresses, and protocols. You can configure the policy using built-in settings or define your own custom rules. The policy then provides an `HttpMessageHandler` that automatically enforces these security requirements on all outgoing requests. ## Constructors | Constructor | Description | | --- | --- | -| `AntiSSRFPolicy(PolicyConfigOptions config)` | Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. | +| [AntiSSRFPolicy(PolicyConfigOptions)](constructor) | Initializes a new instance of the `AntiSSRFPolicy` class with the specified initial configuration. | ## Properties -| Property | Type | Description | -| --- | --- | --- | -| `AllowPlainTextHttp` | `bool` | Determines whether HTTPS is required or HTTP is allowed. | -| `DenyAllUnspecifiedIPs` | `bool` | Determines whether all IP addresses should be blocked by default or only `DeniedAddresses` IP addresses should be blocked. | -| `AddXFFHeader` | `bool` | Determines whether to add the `X-Forwarded-For` header to requests that are missing the header. | -| `AllowedAddresses` | `IReadOnlyList<string>` | Read-only list of IPv4/IPv6 addresses or subnets that are explicitly allowed by the policy. | -| `DeniedAddresses` | `IReadOnlyList<string>` | Read-only list of IPv4/IPv6 addresses or subnets that are explicitly blocked by the policy. | -| `RequiredHeaders` | `IReadOnlyList<string>` | Read-only list of headers that are required to be present in all outgoing requests. | -| `DeniedHeaders` | `IReadOnlyList<string>` | Read-only list of headers that are forbidden from being included in outgoing requests. | +| Property | Description | +| --- | --- | +| [AddXFFHeader](properties/addxffheader) | Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don't already include it. | +| [AllowedAddresses](properties/allowedaddresses) | List of IP networks that are explicitly allowed by the policy. | +| [AllowPlainTextHttp](properties/allowplaintexthttp) | Determines whether HTTPS is required or HTTP is allowed. | +| [DeniedAddresses](properties/deniedaddresses) | List of IP networks that are explicitly blocked by the policy. | +| [DeniedHeaders](properties/deniedheaders) | List of headers that are forbidden from being included in outgoing requests. | +| [DenyAllUnspecifiedIPs](properties/denyallunspecifiedips) | Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. | +| [RequiredHeaders](properties/requiredheaders) | List of headers that are required to be present in outgoing requests. | ## Policy Customization Methods | Method | Description | | --- | --- | -| `AddAllowedAddresses(string[] networks)` | Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly allowed by the policy. | -| `AddDeniedAddresses(string[] networks)` | Adds to a list of IPv4/IPv6 addresses or subnets to be explicitly blocked by the policy. | -| `AddRequiredHeaders(string[] headers)` | Adds to the list of headers explicitly required by the policy. Outgoing requests that are missing a required header will be blocked. | -| `AddDeniedHeaders(string[] headers)` | Adds to the list of headers explicitly blocked by the policy. Outgoing requests that include a denied header will be blocked. | +| [AddAllowedAddresses(string[])](methods/addallowedaddresses) | Adds IP networks to be explicitly allowed by the policy. | +| [AddDeniedAddresses(string[])](methods/adddeniedaddresses) | Adds IP networks to be explicitly blocked by the policy. | +| [AddDeniedHeaders(string[])](methods/adddeniedheaders) | Adds headers to be explicitly blocked by the policy. | +| [AddRequiredHeaders(string[])](methods/addrequiredheaders) | Adds headers to be explicitly required by the policy. | ## Policy Use Method | Method | Description | | --- | --- | -| `GetHandler()` | Creates and returns a new `AntiSSRFHandler` instance based on the current policy configuration. | - -## Example - -```csharp -using Microsoft.Security.AntiSSRF; -using System.Net.Http; - -// Create a policy that blocks internal/special-purpose addresses -AntiSSRFPolicy policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); - -// Get the handler and create an HttpClient -AntiSSRFHandler handler = policy.GetHandler(); -HttpClient client = new HttpClient(handler); - -string untrustedUri = "<some_uri_constructed_with_untrusted_input>"; - -// All requests through this client are now protected -try -{ - HttpResponseMessage response = await client.GetAsync(untrustedUri); - // The request was successfully made - the request and untrustedUri matched the policy -} -catch (AntiSSRFException) -{ - // The request was not made - the IP address, headers, or protocol did not match the policy -} - -``` +| [GetHandler()](methods/gethandler) | Creates and returns a new `AntiSSRFHandler` that will enforce the policy on all outgoing requests. | \ No newline at end of file diff --git a/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md b/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md index fac266c..1e27fee 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md +++ b/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md @@ -3,8 +3,7 @@ layout: default title: AddAllowedAddresses parent: Methods grand_parent: AntiSSRFPolicy -ancestor: C# API Reference -nav_order: 1 +ancestor: .NET API Reference description: "AddAllowedAddresses method documentation" --- @@ -12,7 +11,7 @@ description: "AddAllowedAddresses method documentation" ## Definition -Adds IP networks to the allow list. Requests to any IP address that matches any of the specified networks will be allowed by the handler. Allowed addresses take precedence over denied addresses, so if an IP address matches a network on both the allow and deny list, it will be allowed. +Adds IP networks to be explicitly allowed by the policy. ```csharp public void AddAllowedAddresses(string[] networks) @@ -25,19 +24,7 @@ public void AddAllowedAddresses(string[] networks) `networks`: `string[]` -The list of IPv4/IPv6 addresses or subnets to be explicitly allowed by the policy. - -Networks can be: -* IPv4 addresses in dotted-quad notation - * e.g. `127.0.0.1` -* IPv6 addresses in expanded notation `x:x:x:x:x:x:x:x`, where the `x`s are one to four hexadecimal digits - * e.g. `ABCD:EF01:2345:6789:ABCD:EF01:2345:6789` -* IPv6 addresses in compressed notation, where one group of consecutive 0s is represented with `::` - * e.g. `ABCD::`, `::1`, `ABCD:EF01::2345:6789` -* IPv6 in mixed notation `x:x:x:x:x:x:d.d.d.d`, where the `x`s are hexadecimal values and the `d`s are decimal - * e.g. `::FFFF:127.0.0.1` -* Any of the above addresses with a decimal prefix length `<ip-address>/<prefix-length>` - * e.g. `192.0.2.0/24`, `2001:db8::/32` +The list of IP networks to be explicitly allowed by the policy. ### Exceptions @@ -49,3 +36,29 @@ Networks can be: `AntiSSRFException` * Attempted to edit the policy after it has been used to create a handler via `GetHandler()`. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; + +// Customize the policy +var policy = new AntiSSRFPolicy(PolicyConfigOptions.None); +policy.DenyAllUnspecifiedIPs = true; +policy.AddAllowedAddresses(new[] { "1.2.3.4" }); + +// Create HttpClient with the policy handler +using var httpClient = new HttpClient(policy.GetHandler()); + +try +{ + // If the untrusted hostname directs to 1.2.3.4, + // the request will succeed here + var response = await httpClient.GetAsync("https://<some_untrusted_hostname>/public/data"); +} +catch (AntiSSRFException ex) +{ + // If untrusted hostname directs to anything besides 1.2.3.4, + // the request will fail here with an AntiSSRFException +} +``` diff --git a/docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md b/docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md index e006c09..55e44d7 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md +++ b/docs/dotnet-api/antissrfpolicy/methods/adddeniedaddresses.md @@ -3,8 +3,7 @@ layout: default title: AddDeniedAddresses parent: Methods grand_parent: AntiSSRFPolicy -ancestor: C# API Reference -nav_order: 2 +ancestor: .NET API Reference description: "AddDeniedAddresses method documentation" --- @@ -12,7 +11,7 @@ description: "AddDeniedAddresses method documentation" ## Definition -Adds IP networks to the deny list. Requests to any IP address that matches any of the specified networks will be blocked by the handler. Allowed addresses take precedence over denied addresses, so if an IP address matches a network on both the allow and deny list, it will be allowed. +Adds IP networks to be explicitly blocked by the policy. ```csharp public void AddDeniedAddresses(string[] networks) @@ -28,19 +27,7 @@ public void AddDeniedAddresses(string[] networks) `networks`: `string[]` -The list of IPv4/IPv6 addresses or subnets to be explicitly blocked by the policy. - -Networks can be: -* IPv4 addresses in dotted-quad notation - * e.g. `127.0.0.1` -* IPv6 addresses in expanded notation `x:x:x:x:x:x:x:x`, where the `x`s are one to four hexadecimal digits - * e.g. `ABCD:EF01:2345:6789:ABCD:EF01:2345:6789` -* IPv6 addresses in compressed notation, where one group of consecutive 0s is represented with `::` - * e.g. `ABCD::`, `::1`, `ABCD:EF01::2345:6789` -* IPv6 in mixed notation `x:x:x:x:x:x:d.d.d.d`, where the `x`s are hexadecimal values and the `d`s are decimal - * e.g. `::FFFF:127.0.0.1` -* Any of the above addresses with a decimal prefix length `<ip-address>/<prefix-length>` - * e.g. `192.0.2.0/24`, `2001:db8::/32` +The list of IP networks to be explicitly blocked by the policy. ### Exceptions @@ -53,3 +40,31 @@ Networks can be: `AntiSSRFException` * Attempted to edit the policy after it has been used to create a handler via `GetHandler()`. * `DenyAllUnspecifiedIPs` is already set to `true`. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; +using System.Net.Http; +using System.Threading.Tasks; + +// Customize the policy +var policy = new AntiSSRFPolicy(PolicyConfigOptions.None); +policy.AddDeniedAddresses(new[] { "1.2.3.4" }); + +// Create HttpClient with the policy handler +using var httpClient = new HttpClient(policy.GetHandler()); + +try +{ + // If the untrusted hostname directs to anything besides 1.2.3.4, + // the request will succeed here + var response = await httpClient.GetAsync("https://<some_untrusted_hostname>/public/data"); +} +catch (AntiSSRFException ex) +{ + // If untrusted hostname directs to 1.2.3.4, + // the request will fail here with an AntiSSRFException +} +``` \ No newline at end of file diff --git a/docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md b/docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md index 36965ee..45077c3 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md +++ b/docs/dotnet-api/antissrfpolicy/methods/adddeniedheaders.md @@ -3,8 +3,7 @@ layout: default title: AddDeniedHeaders parent: Methods grand_parent: AntiSSRFPolicy -ancestor: C# API Reference -nav_order: 4 +ancestor: .NET API Reference description: "AddDeniedHeaders method documentation" --- @@ -12,7 +11,7 @@ description: "AddDeniedHeaders method documentation" ## Definition -Adds headers to the list of denied headers. HTTP requests containing any of these headers will be blocked by the handler. +Adds headers to be explicitly blocked by the policy. Requests that include a denied header will be blocked. ```csharp public void AddDeniedHeaders(string[] deniedHeaders) @@ -37,3 +36,46 @@ The list of headers for the policy to block. `AntiSSRFException` * Attempted to edit the policy after it has been used to create a handler via `GetHandler()`. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; +using System.Net.Http; +using System.Threading.Tasks; + +// Customize the policy +var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.AddDeniedHeaders(new[] { "X-Real-IP", "X-Forwarded-Host" }); + +// Create HttpClient with the policy handler +using var httpClient = new HttpClient(policy.GetHandler()); + +try +{ + // This request will succeed (no denied headers) + httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0"); + httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); + + var response = await httpClient.GetAsync("https://<some_untrusted_hostname>/public/data"); +} +catch (AntiSSRFException ex) +{ + // Should not reach here +} + +try +{ + // This request will be blocked (contains denied header) + using var blockedClient = new HttpClient(policy.GetHandler()); + blockedClient.DefaultRequestHeaders.Add("X-Real-IP", "192.168.1.1"); // This header is denied + blockedClient.DefaultRequestHeaders.Add("Accept", "application/json"); + + var blockedResponse = await blockedClient.GetAsync("https://<some_untrusted_hostname>/admin/endpoint"); +} +catch (AntiSSRFException ex) +{ + Console.WriteLine($"Request blocked due to denied header: {ex.Message}"); +} +``` diff --git a/docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md b/docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md index 6b80594..7c5e9af 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md +++ b/docs/dotnet-api/antissrfpolicy/methods/addrequiredheaders.md @@ -3,8 +3,7 @@ layout: default title: AddRequiredHeaders parent: Methods grand_parent: AntiSSRFPolicy -ancestor: C# API Reference -nav_order: 3 +ancestor: .NET API Reference description: "AddRequiredHeaders method documentation" --- @@ -12,7 +11,7 @@ description: "AddRequiredHeaders method documentation" ## Definition -Adds headers to the list of required headers. HTTP requests missing any of these headers will be blocked by the handler. +Adds headers to be explicitly required by the policy. Requests that are missing a required header will be blocked. ```csharp public void AddRequiredHeaders(string[] requiredHeaders) @@ -37,3 +36,49 @@ The list of headers for the policy to require. `AntiSSRFException` * Attempted to edit the policy after it has been used to create a handler via `GetHandler()`. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; +using System.Net.Http; +using System.Threading.Tasks; + +// Customize the policy +var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.AddRequiredHeaders(new[] { "Authorization", "X-API-Key" }); + +// Create HttpClient with the policy handler +using var httpClient = new HttpClient(policy.GetHandler()); + +try +{ + // This request will succeed (all required headers present) + httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer token123"); + httpClient.DefaultRequestHeaders.Add("X-API-Key", "key456"); + httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); + + var response = await httpClient.GetAsync("https://<some_untrusted_hostname>/secure/data"); +} +catch (AntiSSRFException ex) +{ + // Should not reach here +} + +try +{ + // This request will be blocked (missing required header) + using var blockedClient = new HttpClient(policy.GetHandler()); + blockedClient.DefaultRequestHeaders.Add("Authorization", "Bearer token123"); + blockedClient.DefaultRequestHeaders.Add("Accept", "application/json"); + // Missing X-API-Key header + + var blockedResponse = await blockedClient.GetAsync("https://<some_untrusted_hostname>/secure/admin"); + // This will not execute - request will be blocked +} +catch (AntiSSRFException ex) +{ + Console.WriteLine($"Request blocked due to missing required header: {ex.Message}"); +} +``` diff --git a/docs/dotnet-api/antissrfpolicy/methods/gethandler.md b/docs/dotnet-api/antissrfpolicy/methods/gethandler.md index 26801ee..8144b8c 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/gethandler.md +++ b/docs/dotnet-api/antissrfpolicy/methods/gethandler.md @@ -3,8 +3,7 @@ layout: default title: GetHandler parent: Methods grand_parent: AntiSSRFPolicy -ancestor: C# API Reference -nav_order: 5 +ancestor: .NET API Reference description: "GetHandler method documentation" --- @@ -12,20 +11,20 @@ description: "GetHandler method documentation" ## Definition -Creates and returns a new `AntiSSRFHandler` instance based on the current policy configuration. +Builds an `AntiSSRFHandler` that will enforce the policy on all outgoing requests. ```csharp public AntiSSRFHandler GetHandler() ``` -{: .warning } +{: .note } > After calling `GetHandler()`, the policy becomes immutable. Any attempt to change properties or call customization methods will throw an `AntiSSRFException`. ### Returns `AntiSSRFHandler` -A new `AntiSSRFHandler` instance that enforces this policy. Use this handler when constructing an `HttpClient`. +A new `AntiSSRFHandler` instance that enforces this policy. ### Example @@ -33,9 +32,8 @@ A new `AntiSSRFHandler` instance that enforces this policy. Use this handler whe using Microsoft.Security.AntiSSRF; using System.Net.Http; +// Customize the policy var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); - -// Customize before getting handler policy.AddAllowedAddresses(new[] { "10.0.1.0/24" }); // Get the handler β€” policy is now locked diff --git a/docs/dotnet-api/antissrfpolicy/methods/index.md b/docs/dotnet-api/antissrfpolicy/methods/index.md index 1dbad3b..ec454c3 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/index.md +++ b/docs/dotnet-api/antissrfpolicy/methods/index.md @@ -2,7 +2,25 @@ layout: default title: Methods parent: AntiSSRFPolicy -grand_parent: C# API Reference +grand_parent: .NET API Reference +nav_order: 3 description: "AntiSSRFPolicy methods documentation" has_children: true +nav_fold: true +has_toc: false --- + +## Policy Customization Methods + +| Method | Description | +| --- | --- | +| [AddAllowedAddresses(string[])](addallowedaddresses) | Adds IP networks to be explicitly allowed by the policy. | +| [AddDeniedAddresses(string[])](adddeniedaddresses) | Adds IP networks to be explicitly blocked by the policy. | +| [AddDeniedHeaders(string[])](adddeniedheaders) | Adds headers to be explicitly blocked by the policy. | +| [AddRequiredHeaders(string[])](addrequiredheaders) | Adds headers to be explicitly required by the policy. | + +## Policy Use Method + +| Method | Description | +| --- | --- | +| [GetHandler()](gethandler) | Creates and returns a new `AntiSSRFHandler` that will enforce the policy on all outgoing requests. | diff --git a/docs/dotnet-api/antissrfpolicy/properties/addxffheader.md b/docs/dotnet-api/antissrfpolicy/properties/addxffheader.md index a2444c3..f54b6a6 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/addxffheader.md +++ b/docs/dotnet-api/antissrfpolicy/properties/addxffheader.md @@ -3,7 +3,7 @@ layout: default title: AddXFFHeader parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "AddXFFHeader property documentation" --- @@ -11,7 +11,7 @@ description: "AddXFFHeader property documentation" ## Definition -Gets or sets whether the handler should add an `X-Forwarded-For: true` header to outgoing HTTP requests that are missing the header. +Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don’t already include it. {: .important } > The header is added with the dummy value `"true"`. If your end service requires this header to be a valid IP address, you will have to add the header manually. @@ -24,7 +24,7 @@ public bool AddXFFHeader { get; set; } `bool` -* `true` if the `X-Forwarded-For` header should be added to requests where it is missing. +* `true` if the `X-Forwarded-For` header should be added to requests that don’t already include it. * `false` if the `X-Forwarded-For` header should not be added. Default: `false` (unless using `ExternalOnlyV1` or `ExternalOnlyLatest`, which set it to `true`) @@ -34,6 +34,6 @@ Default: `false` (unless using `ExternalOnlyV1` or `ExternalOnlyLatest`, which s `AntiSSRFException` Thrown when attempting to change the property after the policy has been used to create a handler via `GetHandler()`. -### Security Notes +## Security Notes The `X-Forwarded-For` header can be an important defense-in-depth strategy against SSRF vulnerabilities. Some services, including IMDS, will drop all incoming requests with the `X-Forwarded-For` header present. By ensuring that the header is added to all outgoing requests, your service can be sure that it will never have an SSRF vulnerability that leaks data from IMDS. diff --git a/docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md b/docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md index 426ec67..ee6813c 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md +++ b/docs/dotnet-api/antissrfpolicy/properties/allowedaddresses.md @@ -3,7 +3,7 @@ layout: default title: AllowedAddresses parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "AllowedAddresses property documentation" --- @@ -11,7 +11,7 @@ description: "AllowedAddresses property documentation" ## Definition -Gets a read-only view of the currently allowed IP address ranges as CIDR notation strings. +Gets a read-only view of the IP networks explicitly allowed by the policy. ```csharp public IReadOnlyList<string> AllowedAddresses { get; } @@ -24,4 +24,4 @@ public IReadOnlyList<string> AllowedAddresses { get; } `IReadOnlyList<string>` -A read-only list of the allowed IP address ranges in CIDR notation. +A read-only list of the allowed IP networks. diff --git a/docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md b/docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md index 72ae290..b6dfccb 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md +++ b/docs/dotnet-api/antissrfpolicy/properties/allowplaintexthttp.md @@ -3,18 +3,18 @@ layout: default title: AllowPlainTextHttp parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "AllowPlainTextHttp property documentation" --- # AntiSSRFPolicy.AllowPlainTextHttp Property {: .warning } -> Setting `AllowPlainTextHttp` to `true` means you will be able to send HTTP requests without the required TLS encryption. +> Changing an `AntiSSRFPolicy` instance to allow plaintext HTTP means you will be able to send HTTP requests without the recommended TLS encryption. ## Definition -Gets or sets whether plain text HTTP requests are allowed. If `false`, any request with the `http` scheme will be blocked by the handler. +Determines whether HTTPS is required or HTTP is allowed. ```csharp public bool AllowPlainTextHttp { get; set; } @@ -30,8 +30,6 @@ public bool AllowPlainTextHttp { get; set; } * `true` if HTTP should be allowed. * `false` if HTTPS should be required. -Default: `false` - ### Exceptions `AntiSSRFException` diff --git a/docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md b/docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md index fdc7485..32c186f 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md +++ b/docs/dotnet-api/antissrfpolicy/properties/deniedaddresses.md @@ -3,7 +3,7 @@ layout: default title: DeniedAddresses parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "DeniedAddresses property documentation" --- @@ -11,7 +11,7 @@ description: "DeniedAddresses property documentation" ## Definition -Gets a read-only view of the currently denied IP address ranges as CIDR notation strings. +Gets a read-only view of IP networks explicitly blocked by the policy. ```csharp public IReadOnlyList<string> DeniedAddresses { get; } @@ -27,4 +27,4 @@ public IReadOnlyList<string> DeniedAddresses { get; } `IReadOnlyList<string>` -A read-only list of the denied IP address ranges in CIDR notation. +A read-only list of the denied IP networks. diff --git a/docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md b/docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md index 9352b33..27f0a43 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md +++ b/docs/dotnet-api/antissrfpolicy/properties/deniedheaders.md @@ -3,7 +3,7 @@ layout: default title: DeniedHeaders parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "DeniedHeaders property documentation" --- @@ -11,7 +11,7 @@ description: "DeniedHeaders property documentation" ## Definition -Gets a read-only view of the currently denied headers. HTTP requests containing any of these headers will be blocked by the handler. +Gets a read-only view of headers that are forbidden from being included in outgoing requests. ```csharp public IReadOnlyList<string> DeniedHeaders { get; } @@ -24,4 +24,4 @@ public IReadOnlyList<string> DeniedHeaders { get; } `IReadOnlyList<string>` -A read-only list of the headers explicitly blocked by the policy. +A read-only list of header names that are blocked by the policy. diff --git a/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md index 4592d1a..a0877cc 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md +++ b/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md @@ -3,7 +3,7 @@ layout: default title: DenyAllUnspecifiedIPs parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "DenyAllUnspecifiedIPs property documentation" --- @@ -11,8 +11,10 @@ description: "DenyAllUnspecifiedIPs property documentation" ## Definition -Gets or sets whether the handler should deny all unspecified IP addresses. If `true`, any request to an IP address not explicitly allowed will be blocked. -To allow specific addresses, use `AddAllowedAddresses`. +Determines whether all IP addresses should be blocked by default or only `DeniedAddresses` should be blocked. + +{: .note } +> To allow specific addresses, use `AddAllowedAddresses`. ```csharp public bool DenyAllUnspecifiedIPs { get; set; } diff --git a/docs/dotnet-api/antissrfpolicy/properties/index.md b/docs/dotnet-api/antissrfpolicy/properties/index.md index 5a7f5ae..3222f73 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/index.md +++ b/docs/dotnet-api/antissrfpolicy/properties/index.md @@ -2,9 +2,22 @@ layout: default title: Properties parent: AntiSSRFPolicy -grand_parent: C# API Reference +grand_parent: .NET API Reference nav_order: 2 description: "AntiSSRFPolicy properties documentation" has_children: true nav_fold: true +has_toc: false --- + +## AntiSSRFPolicy Properties + +| Property | Description | +| --- | --- | +| [AddXFFHeader](addxffheader) | Determines whether to automatically add the `X-Forwarded-For` header to outgoing requests that don't already include it. | +| [AllowedAddresses](allowedaddresses) | List of IP networks that are explicitly allowed by the policy. | +| [AllowPlainTextHttp](allowplaintexthttp) | Determines whether HTTPS is required or HTTP is allowed. | +| [DeniedAddresses](deniedaddresses) | List of IP networks that are explicitly blocked by the policy. | +| [DeniedHeaders](deniedheaders) | List of headers that are forbidden from being included in outgoing requests. | +| [DenyAllUnspecifiedIPs](denyallunspecifiedips) | Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. | +| [RequiredHeaders](requiredheaders) | List of headers that are required to be present in outgoing requests. | diff --git a/docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md b/docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md index 9d2c7b1..0fb5d3f 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md +++ b/docs/dotnet-api/antissrfpolicy/properties/requiredheaders.md @@ -3,7 +3,7 @@ layout: default title: RequiredHeaders parent: Properties grand_parent: AntiSSRFPolicy -ancestor: C# API Reference +ancestor: .NET API Reference description: "RequiredHeaders property documentation" --- @@ -11,7 +11,7 @@ description: "RequiredHeaders property documentation" ## Definition -Gets a read-only view of the currently required headers. HTTP requests missing any of these headers will be blocked by the handler. +Gets a read-only view of headers that are required to be present in outgoing requests. ```csharp public IReadOnlyList<string> RequiredHeaders { get; } @@ -24,4 +24,4 @@ public IReadOnlyList<string> RequiredHeaders { get; } `IReadOnlyList<string>` -A read-only list of the headers explicitly required by the policy. +A read-only list of header names that are required by the policy. diff --git a/docs/dotnet-api/changelog.md b/docs/dotnet-api/changelog.md index 3aaf587..f28b79a 100644 --- a/docs/dotnet-api/changelog.md +++ b/docs/dotnet-api/changelog.md @@ -1,14 +1,14 @@ --- layout: default title: Changelog -parent: C# API Reference +parent: .NET API Reference nav_order: 99 -description: "Release notes and version history for AntiSSRF NodeJS" +description: "Release notes and version history for AntiSSRF .NET Library" --- # Changelog -All notable changes to the AntiSSRF NodeJS library will be documented in this file. +All notable changes to the AntiSSRF .NET Library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/docs/dotnet-api/index.md b/docs/dotnet-api/index.md index b863071..734d361 100644 --- a/docs/dotnet-api/index.md +++ b/docs/dotnet-api/index.md @@ -1,34 +1,34 @@ --- layout: default -title: C# API Reference +title: .NET API Reference nav_order: 3 -description: "Complete API documentation for the AntiSSRF C# library" +description: "Complete API documentation for the AntiSSRF .NET Library" has_children: true has_toc: false --- # API Documentation -## AntiSSRF C# Library +## AntiSSRF .NET Library -The **AntiSSRF C# Library** is a library for .NET applications that provides robust URL validation and HTTP request protection to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with minimal impact on the engineering team, implemented both as an `HttpMessageHandler` for use with `HttpClient` and as a static URL validator, depending on use case. +The **AntiSSRF .NET Library** is a library for C# applications using .NET that provides robust URL validation and HTTP request protection to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with minimal impact on the engineering team, implemented both as an `HttpMessageHandler` for use with `HttpClient` and as a static URL validator, depending on use case. ## Usage Instructions -There are four different ways to use this library, depending on your specific case. Identify the use case below based on the URLs your code is accessing. +The AntiSSRF library provides validation for different scenarios based on your trust requirements: -| Use Case | Steps | -| --- | --- | -| The URL you are accessing must always belong to a **specific, trusted domain**. | See [URIValidator.InDomain](urivalidator/indomain.html). | -| The URL you are accessing must be an **Azure Storage endpoint**. | See [URIValidator.InAzureStorageDomain](urivalidator/inazurestoragedomain.html). | -| The URL you are accessing must be an **Azure Key Vault endpoint**. | See [URIValidator.InAzureKeyVaultDomain](urivalidator/inazurekeyvaultdomain.html). | -| The URL you are accessing can belong to **any domain** or an **untrusted domain**, so to prevent SSRF vulnerabilities, you must ensure that it does not resolve to internal and special-purpose IP addresses. | See [AntiSSRFPolicy](antissrfpolicy/). | +| Use Case | Description | Documentation Link | +| --- | --- | --- | +| **General Case** | The untrusted URL can belong to **any domain** or an **untrusted domain**. | [AntiSSRFPolicy](antissrfpolicy) | +| **Azure Key Vault Domain** | The untrusted URL must be an **Azure Key Vault endpoint**. | [URIValidator.InAzureKeyVaultDomain](urivalidator/inazurekeyvaultdomain) | +| **Azure Storage Domain** | The untrusted URL must be an **Azure Storage endpoint**. | [URIValidator.InAzureStorageDomain](urivalidator/inazurestoragedomain) | +| **Allowlist of Trusted Domains** | The untrusted URL must belong to a **specific, trusted domain**. | [URIValidator.InDomain](urivalidator/indomain) | ## Classes | Class | Description | | --- | --- | -| [AntiSSRFPolicy](antissrfpolicy/) | Represents a customizable security policy and provides an `AntiSSRFHandler` to ensure all outgoing `HttpClient` requests match the security policy. | -| [AntiSSRFHandler](antissrfhandler.html) | An `HttpMessageHandler` that enforces the `AntiSSRFPolicy` on all outgoing requests made via `HttpClient`. | -| [IPAddressRanges](../ipaddressranges.html) | Provides predefined IP address ranges for use with AntiSSRF policies. | +| [AntiSSRFPolicy](antissrfpolicy) | Represents a customizable security policy and provides an `AntiSSRFHandler` to ensure all outgoing `HttpClient` requests match the security policy. | +| [AntiSSRFHandler](antissrfhandler) | An `HttpMessageHandler` that enforces the `AntiSSRFPolicy` on all outgoing requests. | +| [IPAddressRanges](../ipaddressranges) | Provides predefined IP address ranges for use with AntiSSRF policies. | | [URIValidator](urivalidator/) | Provides static methods for validating the hostname and protocol of URLs. | \ No newline at end of file diff --git a/docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md b/docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md index 870bd76..d24e544 100644 --- a/docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md +++ b/docs/dotnet-api/urivalidator/inazurekeyvaultdomain.md @@ -2,8 +2,7 @@ layout: default title: InAzureKeyVaultDomain parent: URIValidator -grand_parent: C# API Reference -nav_order: 3 +grand_parent: .NET API Reference description: "Check if a URI belongs to Azure Key Vault domains" --- @@ -13,35 +12,35 @@ description: "Check if a URI belongs to Azure Key Vault domains" The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to an **Azure Key Vault Domain**. +The URL is expected to belong to an [**Azure Key Vault Domain**](#azure-key-vault-domain-names). {: .note } -> * If you instead expect the domain to be another **specific, trusted domain**, see [InDomain](indomain.html). -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [InAzureStorageDomain](inazurestoragedomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [InAzureStorageDomain](inazurestoragedomain). +> * If you instead expect the domain to be another **specific, trusted domain**, see [InDomain](indomain). ## Definition -Validates if the given input is an Azure Key Vault endpoint. Only supports HTTP and HTTPS protocols. +Validates if a URL is an Azure Key Vault endpoint. ## Overloads | Method | Description | | --- | --- | -| `InAzureKeyVaultDomain(Uri uri)` | Validates if `uri` is an Azure Key Vault endpoint. | -| `InAzureKeyVaultDomain(string address)` | Validates if `address` is an Azure Key Vault endpoint. | +| [InAzureKeyVaultDomain(Uri)](#inazurekeyvaultdomainuri) | Validates if a URL is an Azure Key Vault endpoint. | +| [InAzureKeyVaultDomain(string)](#inazurekeyvaultdomainstring) | Validates if a URL is an Azure Key Vault endpoint. | ## InAzureKeyVaultDomain(Uri) ```csharp -public static bool InAzureKeyVaultDomain(Uri untrustedUri) +public static bool InAzureKeyVaultDomain(Uri uri) ``` ### Parameters -`untrustedUri`: `Uri` +`uri`: `Uri` The URI to be evaluated. @@ -49,18 +48,18 @@ The URI to be evaluated. `bool` -* `true` if `untrustedUri` belongs to any of the listed Azure Key Vault domains. -* `false` if `untrustedUri` does not belong to any of the listed Azure Key Vault domains, the URI is not valid, or the protocol is not HTTP/S. +* `true` if `uri` belongs to any of the listed Azure Key Vault domains. +* `false` if `uri` does not belong to any of the listed Azure Key Vault domains, the URI is not valid, or the protocol is not HTTP/S. ## InAzureKeyVaultDomain(string) ```csharp -public static bool InAzureKeyVaultDomain(string untrustedAddress) +public static bool InAzureKeyVaultDomain(string address) ``` ### Parameters -`untrustedAddress`: `string` +`address`: `string` The URI string to be evaluated. @@ -68,8 +67,25 @@ The URI string to be evaluated. `bool` -* `true` if `untrustedAddress` belongs to any of the listed Azure Key Vault domains. -* `false` if `untrustedAddress` does not belong to any of the listed Azure Key Vault domains, the string is not a valid URI, or the protocol is not HTTP/S. +* `true` if `address` belongs to any of the listed Azure Key Vault domains. +* `false` if `address` does not belong to any of the listed Azure Key Vault domains, the string is not a valid URI, or the protocol is not HTTP/S. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; + +URIValidator.InAzureKeyVaultDomain("https://myvault.vault.azure.net/secrets/api-key"); +// β†’ true + +URIValidator.InAzureKeyVaultDomain("https://evil.com/secrets"); +// β†’ false + +var uri = new Uri("https://myvault.vault.azure.net/secrets/api-key"); +URIValidator.InAzureKeyVaultDomain(uri); +// β†’ true +``` ## Azure Key Vault Domain Names diff --git a/docs/dotnet-api/urivalidator/inazurestoragedomain.md b/docs/dotnet-api/urivalidator/inazurestoragedomain.md index 7f2653c..77fc09e 100644 --- a/docs/dotnet-api/urivalidator/inazurestoragedomain.md +++ b/docs/dotnet-api/urivalidator/inazurestoragedomain.md @@ -2,8 +2,7 @@ layout: default title: InAzureStorageDomain parent: URIValidator -grand_parent: C# API Reference -nav_order: 2 +grand_parent: .NET API Reference description: "Check if a URI belongs to Azure Storage domains" --- @@ -13,35 +12,35 @@ description: "Check if a URI belongs to Azure Storage domains" The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to an **Azure Storage Domain**. +The URL is expected to belong to an [**Azure Storage Domain**](#azure-storage-domain-names). {: .note } -> * If you instead expect the domain to be another **specific, trusted domain**, see [InDomain](indomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [InAzureKeyVaultDomain](inazurekeyvaultdomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [InAzureKeyVaultDomain](inazurekeyvaultdomain). +> * If you instead expect the domain to be another **specific, trusted domain**, see [InDomain](indomain). ## Definition -Validates if the given input is an Azure Storage endpoint. Only supports HTTP and HTTPS protocols. +Validates if a URL is an Azure Storage endpoint. ## Overloads | Method | Description | | --- | --- | -| `InAzureStorageDomain(Uri uri)` | Validates if `uri` is an Azure Storage endpoint. | -| `InAzureStorageDomain(string address)` | Validates if `address` is an Azure Storage endpoint. | +| [InAzureStorageDomain(Uri)](#inazurestoragedomainuri) | Validates if a URL is an Azure Storage endpoint. | +| [InAzureStorageDomain(string)](#inazurestoragedomainstring) | Validates if a URL is an Azure Storage endpoint. | ## InAzureStorageDomain(Uri) ```csharp -public static bool InAzureStorageDomain(Uri untrustedUri) +public static bool InAzureStorageDomain(Uri uri) ``` ### Parameters -`untrustedUri`: `Uri` +`uri`: `Uri` The URI to be evaluated. @@ -49,18 +48,18 @@ The URI to be evaluated. `bool` -* `true` if `untrustedUri` belongs to any of the listed Azure Storage domains. -* `false` if `untrustedUri` does not belong to any of the listed Azure Storage domains, the URI is not valid, or the protocol is not HTTP/S. +* `true` if `uri` belongs to any of the listed Azure Storage domains. +* `false` if `uri` does not belong to any of the listed Azure Storage domains, the URI is not valid, or the protocol is not HTTP/S. ## InAzureStorageDomain(string) ```csharp -public static bool InAzureStorageDomain(string untrustedAddress) +public static bool InAzureStorageDomain(string address) ``` ### Parameters -`untrustedAddress`: `string` +`address`: `string` The URI string to be evaluated. @@ -68,8 +67,25 @@ The URI string to be evaluated. `bool` -* `true` if `untrustedAddress` belongs to any of the listed Azure Storage domains. -* `false` if `untrustedAddress` does not belong to any of the listed Azure Storage domains, the string is not a valid URI, or the protocol is not HTTP/S. +* `true` if `address` belongs to any of the listed Azure Storage domains. +* `false` if `address` does not belong to any of the listed Azure Storage domains, the string is not a valid URI, or the protocol is not HTTP/S. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; + +URIValidator.InAzureStorageDomain("https://mystorageaccount.blob.core.windows.net/container/file.txt"); +// β†’ true + +URIValidator.InAzureStorageDomain("https://evil.com/data"); +// β†’ false + +var uri = new Uri("https://mystorageaccount.blob.core.windows.net/container/file.txt"); +URIValidator.InAzureStorageDomain(uri); +// β†’ true +``` ## Azure Storage Domain Names diff --git a/docs/dotnet-api/urivalidator/index.md b/docs/dotnet-api/urivalidator/index.md index 9a00106..df7a196 100644 --- a/docs/dotnet-api/urivalidator/index.md +++ b/docs/dotnet-api/urivalidator/index.md @@ -1,9 +1,11 @@ --- layout: default title: URIValidator -parent: C# API Reference +parent: .NET API Reference description: "URL validation class for SSRF protection" +nav_order: 3 has_children: true +has_toc: false --- # URIValidator Class @@ -12,32 +14,26 @@ has_children: true The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** -The URL is expected to belong to a specific set of trusted domains, the Azure Storage domains, or the Azure Key Vault domains. +The URL is expected to belong to a specific set of trusted domains, the [Azure Storage domains](inazurestoragedomain#azure-storage-domain-names), or the [Azure Key Vault domains](inazurekeyvaultdomain#azure-key-vault-domain-names). {: .note } -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). ## Definition -Namespace: `Microsoft.Security.AntiSSRF` - Provides static methods for validating the hostname and protocol of URLs. -```csharp -public static class URIValidator -``` - ## Methods | Method | Description | | --- | --- | -| `InDomain(Uri uri, string domain)` | Validates if `uri` belongs to `domain`. | -| `InDomain(string address, string domain)` | Validates if `address` belongs to `domain`. | -| `InDomain(Uri uri, string[] domains)` | Validates if `uri` belongs to any domain in `domains`. | -| `InDomain(string address, string[] domains)` | Validates if `address` belongs to any domain in `domains`. | -| `InAzureKeyVaultDomain(Uri uri)` | Validates if `uri` is an Azure Key Vault endpoint. | -| `InAzureKeyVaultDomain(string address)` | Validates if `address` is an Azure Key Vault endpoint. | -| `InAzureStorageDomain(Uri uri)` | Validates if `uri` is an Azure Storage endpoint. | -| `InAzureStorageDomain(string address)` | Validates if `address` is an Azure Storage endpoint. | +| [InAzureKeyVaultDomain(Uri)](inazurekeyvaultdomain#inazurekeyvaultdomainuri) | Validates if a URL is an Azure Key Vault endpoint. | +| [InAzureKeyVaultDomain(string)](inazurekeyvaultdomain#inazurekeyvaultdomainstring) | Validates if a URL is an Azure Key Vault endpoint. | +| [InAzureStorageDomain(Uri)](inazurestoragedomain#inazurestoragedomainuri) | Validates if a URL is an Azure Storage endpoint. | +| [InAzureStorageDomain(string)](inazurestoragedomain#inazurestoragedomainstring) | Validates if a URL is an Azure Storage endpoint. | +| [InDomain(Uri, string)](indomain#indomainuri-string) | Validates if a URL belongs to a trusted domain. | +| [InDomain(string, string)](indomain#indomainstring-string) | Validates if a URL belongs to a trusted domain. | +| [InDomain(Uri, string[])](indomain#indomainuri-string-1) | Validates if a URL belongs to any of a list of trusted domains. | +| [InDomain(string, string[])](indomain#indomainstring-string-1) | Validates if a URL belongs to any of a list of trusted domains. | diff --git a/docs/dotnet-api/urivalidator/indomain.md b/docs/dotnet-api/urivalidator/indomain.md index 38b5bc4..f7c3b38 100644 --- a/docs/dotnet-api/urivalidator/indomain.md +++ b/docs/dotnet-api/urivalidator/indomain.md @@ -2,7 +2,7 @@ layout: default title: InDomain parent: URIValidator -grand_parent: C# API Reference +grand_parent: .NET API Reference nav_order: 1 description: "Check if a URI belongs to specified domain(s)" --- @@ -13,30 +13,30 @@ description: "Check if a URI belongs to specified domain(s)" The code is making requests to a URL constructed using untrusted inputs, where an input is considered untrusted if it comes from *user input* or *other services*. -AND +**AND** The URL is expected to belong to a **specific set of trusted domains**. {: .note } -> * If you instead expect the URL to be an **Azure Storage endpoint**, see [InAzureStorageDomain](inazurestoragedomain.html). -> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [InAzureKeyVaultDomain](inazurekeyvaultdomain.html). -> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy/). +> * If you instead expect the domain to be in **any domain** or **an untrusted domain**, see [AntiSSRFPolicy](../antissrfpolicy). +> * If you instead expect the URL to be an **Azure Key Vault endpoint**, see [InAzureKeyVaultDomain](inazurekeyvaultdomain). +> * If you instead expect the URL to be an **Azure Storage endpoint**, see [InAzureStorageDomain](inazurestoragedomain). {: .important } -> If your untrusted URL needs to belong to a specific domain, but you do not fully control all subdomains of the domain, you can use BOTH `InDomain` AND `AntiSSRFPolicy` to be protected. +> If your untrusted URL needs to belong to a specific domain, but you do not fully control all subdomains of the domain, you can use BOTH `InDomain` AND `AntiSSRFPolicy` to be protected. If the untrusted URL belongs to a domain that cannot be fully trusted, at least `AntiSSRFPolicy` is required for full protection. ## Definition -Validates if the given input belongs to any of the specified domains. Only supports HTTP, HTTPS, WS, and WSS protocols. +Validates if a URL belongs to any of a list of trusted domains. ## Overloads | Method | Description | | --- | --- | -| `InDomain(Uri uri, string domain)` | Validates if `uri` belongs to `domain`. | -| `InDomain(string address, string domain)` | Validates if `address` belongs to `domain`. | -| `InDomain(Uri uri, string[] domains)` | Validates if `uri` belongs to any domain in `domains`. | -| `InDomain(string address, string[] domains)` | Validates if `address` belongs to any domain in `domains`. | +| [InDomain(Uri, string)](#indomainuri-string) | Validates if a URL belongs to a trusted domain. | +| [InDomain(string, string)](#indomainstring-string) | Validates if a URL belongs to a trusted domain. | +| [InDomain(Uri, string[])](#indomainuri-string-1) | Validates if a URL belongs to any of a list of trusted domains. | +| [InDomain(string, string[])](#indomainstring-string-1) | Validates if a URL belongs to any of a list of trusted domains. | ## InDomain(Uri, string) @@ -129,3 +129,27 @@ The list of domain names that `untrustedAddress` will be compared against. * `true` if `untrustedAddress` belongs to any domain in `trustedDomains`. * `false` if `untrustedAddress` does not belong to any domain in `trustedDomains`, if `untrustedAddress` cannot be converted to a valid URI, if protocol is not HTTP/S or WS/S, or if either argument is `null`. + +## Examples + +```csharp +using Microsoft.Security.AntiSSRF; +using System; + +// Single domain validation +URIValidator.InDomain("https://api.mycompany.com/data", "mycompany.com"); +// β†’ true + +// Multiple domain validation +URIValidator.InDomain("https://api.mycompany.com/data", new[] { "mycompany.com", "trusted.com" }); +// β†’ true + +// Domain not in trusted list +URIValidator.InDomain("https://evil.com/secrets", "mycompany.com"); +// β†’ false + +// Using Uri overload +var uri = new Uri("https://api.mycompany.com/data"); +URIValidator.InDomain(uri, "mycompany.com"); +// β†’ true +``` diff --git a/docs/nodejs-api/antissrfpolicy/constructor.md b/docs/nodejs-api/antissrfpolicy/constructor.md index 2e51d6b..d4520db 100644 --- a/docs/nodejs-api/antissrfpolicy/constructor.md +++ b/docs/nodejs-api/antissrfpolicy/constructor.md @@ -29,7 +29,7 @@ Choose from the following predefined policy configurations: | Option | Use Case | Behavior | | --- | --- | --- | | **InternalOnly** | Making requests to internal addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [addAllowedAddresses](../methods/addallowedaddresses). | -| **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedramgesv1). Automatically adds `X-Forwarded-For` header to requests. | +| **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedrangesv1). Automatically adds `X-Forwarded-For` header to requests. | | **ExternalOnlyLatest** | Currently the same as `ExternalOnlyV1` with automatic security updates | Always stays up to date with the latest `ExternalOnly` version, independent of semantic versioning. | | **None** | Custom policy configuration | No restrictions applied. Requires manual configuration via policy methods. | diff --git a/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md b/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md index b6a41f6..0e2bafa 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/methods/addallowedaddresses.md @@ -68,7 +68,7 @@ const req = https.request(options, (res) => { req.on('error', (err) => { // If untrusted hostname directs to anything besides 1.2.3.4, - // the request will fail here with an AntiSSRF error + // the request will fail here with an AntiSSRFError }); req.end(); diff --git a/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md b/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md index bc5aad5..c69fe83 100644 --- a/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md +++ b/docs/nodejs-api/antissrfpolicy/methods/adddeniedaddresses.md @@ -71,7 +71,7 @@ const req = https.request(options, (res) => { req.on('error', (err) => { // If untrusted hostname directs to 1.2.3.4, - // the request will fail here with an AntiSSRF error + // the request will fail here with an AntiSSRFError }); req.end(); diff --git a/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md b/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md index a772baf..1ef1f2d 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md +++ b/docs/nodejs-api/antissrfpolicy/properties/addxffheader.md @@ -29,7 +29,7 @@ addXFFHeader: boolean { get; set; } ### Errors -`AntiSSRFException` +`AntiSSRFError` The value passed cannot be `null` or `undefined`. ## Security Notes diff --git a/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md b/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md index 90bf957..519b559 100755 --- a/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md +++ b/docs/nodejs-api/antissrfpolicy/properties/allowplaintexthttp.md @@ -32,5 +32,5 @@ allowPlainTextHttp: boolean { get; set; } ### Errors -`AntiSSRFException` +`AntiSSRFError` The value passed cannot be `null` or `undefined`. diff --git a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md index 5cec6f9..10d48d0 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md +++ b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md @@ -29,5 +29,5 @@ denyAllUnspecifiedIPs: boolean { get; set; } ### Errors -`AntiSSRFException` +`AntiSSRFError` The value passed cannot be `null` or `undefined`. diff --git a/docs/nodejs-api/index.md b/docs/nodejs-api/index.md index 988cb95..b7ccbe4 100755 --- a/docs/nodejs-api/index.md +++ b/docs/nodejs-api/index.md @@ -11,7 +11,7 @@ has_toc: false ## AntiSSRF Node.js Library -The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as [Node.js HTTP(S) agents](https://nodejs.org/api/http.html#class-httpagent) and a URL validator, depending on use case. +The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applications using Node.js that provides robust URL validation to prevent SSRF vulnerabilities in code. It is designed as an easy, drop-in library with a minimal impact on the engineering team, implemented both as [Node.js HTTP(S) agents](https://nodejs.org/api/http.html#class-httpagent) and a static URL validator, depending on use case. ## Usage Instructions @@ -30,4 +30,4 @@ The AntiSSRF library provides validation for different scenarios based on your t | --- | --- | | [AntiSSRFPolicy](antissrfpolicy) | Represents a customizable security policy and provides HTTP(S) agents to ensure all outgoing requests match the security policy. | | [IPAddressRanges](../ipaddressranges) | Provides predefined IP address ranges for use with AntiSSRF policies. | -| [URIValidator](urivalidator) | Provides methods for validating the hostname of URLs. | +| [URIValidator](urivalidator) | Provides static methods for validating the hostname and protocol of URLs. | diff --git a/docs/nodejs-api/urivalidator/index.md b/docs/nodejs-api/urivalidator/index.md index 9a57c49..bfbaf8d 100755 --- a/docs/nodejs-api/urivalidator/index.md +++ b/docs/nodejs-api/urivalidator/index.md @@ -23,7 +23,7 @@ The URL is expected to belong to a specific set of trusted domains, the [Azure S ## Definition -Provides methods for validating the hostname and protocol of URLs. +Provides static methods for validating the hostname and protocol of URLs. ## Methods From a785c4418fc90dc55c37a2c3526e69b2720a1749 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Mon, 4 May 2026 09:51:30 -0700 Subject: [PATCH 4/7] final edits? --- docs/dotnet-api/index.md | 2 +- docs/faq.md | 34 ++++++++++++++++++++++++++-------- docs/getting-started.md | 31 ++++++++++++------------------- docs/index.md | 24 +++++++++++++++++++----- docs/nodejs-api/index.md | 2 +- dotnet/src/README.md | 36 ++++++++++++++++++------------------ nodejs/README.md | 36 ++++++++++++++++++------------------ 7 files changed, 95 insertions(+), 70 deletions(-) diff --git a/docs/dotnet-api/index.md b/docs/dotnet-api/index.md index 734d361..d694fae 100644 --- a/docs/dotnet-api/index.md +++ b/docs/dotnet-api/index.md @@ -15,7 +15,7 @@ The **AntiSSRF .NET Library** is a library for C# applications using .NET that p ## Usage Instructions -The AntiSSRF library provides validation for different scenarios based on your trust requirements: +The AntiSSRF Library provides validation for different scenarios based on your trust requirements: | Use Case | Description | Documentation Link | | --- | --- | --- | diff --git a/docs/faq.md b/docs/faq.md index 1fe0530..3ba6b64 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -9,15 +9,27 @@ description: "Frequently asked questions about AntiSSRF" ## What IP addresses or subnets should my service block? -It is important to separate HTTP clients intented for internal vs. external requests. +It is important to separate HTTP clients intended for internal vs. external requests. -Ideally, for internal requests or if the range of possible IP addresses is known, use the configuration [`PolicyConfigOptions.InternalOnly`](../dotnet-api/antissrfpolicy/constructor#policyconfigoptionsinternalonly) and ONLY allow the expected ranges. +Ideally, for internal requests or if the range of possible IP addresses is known, use the configuration `PolicyConfigOptions.InternalOnly` and ONLY allow the expected ranges. -For external requests, your service should AT LEAST block the internal and special-use IP addresses, included to the configuration [`IPAddressRanges.recommendedLatest`](../ipaddressranges#recommended-ranges-latest). +For external requests, your service should AT LEAST block the internal and special-use IP addresses, included in the configuration `PolicyConfigOptions.ExternalOnlyLatest`. + +## Does the library provide protections on redirects? + +The `AntiSSRFPolicy` and its handler/agent DO re-evaluate all policy requirements for every redirect. + +The `URIValidator` methods DO NOT apply protections on redirects. When using `InAzureKeyVaultDomain` or `InAzureStorageDomain`, this is okay, since they limit to only well-known, safe domains. When using `InDomain`, the lack of protections on redirects is part of the reason you must be sure that the `trustedDomains` argument truly only includes trusted domains. + +## Does the library provide protections against DNS-rebinding based attacks? + +The `AntiSSRFPolicy` and its handler/agent DO provide protections against DNS-rebinding based attacks. The IP address that is validated by the policy is EXACTLY the IP address used in the request, eliminating the potential TOCTOU problem. + +The `URIValidator` methods DO NOT provide any protections for DNS-based attacks at all. This is okay for `InAzureKeyVaultDomain` and `InAzureStorageDomain`, since they limit to only well-known, safe domains. When using `InDomain`, the lack of DNS-based protections is part of the reason you must be sure that the `trustedDomains` argument truly only includes trusted domains. ## Does the AntiSSRF library support IPv6 functionality? -Yes, the AntiSSRF Library supports IPv6 functionality. +The `AntiSSRFPolicy` and its handler/agent DO support IPv6 addresses in all formats described by [RFC 4291](https://www.rfc-editor.org/rfc/rfc4291). ## My outgoing requests are being dropped at the destination because of an invalid X-Forwarded-For header. What should I do? @@ -25,16 +37,22 @@ By default, the external-only configurations of AntiSSRF automatically add an `X However, some destination services may reject requests with this dummy value. If your destination service is rejecting requests because of the `X-Forwarded-For: "true"` header, you can disable this behavior: -```cs -const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalLatest); -policy.addXFFHeader = false; // Disables automatic X-Forwarded-For header addition +```csharp +var policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +policy.AddXFFHeader = false; // Disables automatic X-Forwarded-For header addition ``` **Important:** Only disable this feature if you are absolutely certain that: * Your destination service drops ALL requests with the `X-Forwarded-For` header. For example, you are intentionally accessing IMDS while blocking all external IP addresses. * **OR** another component in your service stack reliably adds the `X-Forwarded-For` header to all outgoing requests. That way, the policy does not need to add the invalid dummy value to include the header. -For more information, see the [X-Forwarded-For header documentation](../dotnet-api/antissrfpolicy/properties/addxffheader#security-notes) and [`addXFFHeader` property](../dotnet-api/antissrfpolicy/properties/addxffheader). +For more information, see the [X-Forwarded-For security notes](../dotnet-api/antissrfpolicy/properties/addxffheader#security-notes) and `AddXFFHeader` property. + +## Should Microsoft services be onboarding to this library? + +If you are a Microsoft service with public code, YES! This is the Microsoft-recommended solution for mitigating SSRF vulnerabilities in Microsoft services. + +If you are a Microsoft internal service, we have a separate version of the library for you. Please search for the internal version of the library or reach out to us at [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) for help! ## What languages and frameworks are supported? diff --git a/docs/getting-started.md b/docs/getting-started.md index c0de575..f168e61 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -19,12 +19,6 @@ Install the NuGet package: dotnet add package Microsoft.Security.AntiSSRF ``` -Or using Package Manager Console: - -```powershell -Install-Package Microsoft.Security.AntiSSRF -``` - ### Node.js (JavaScript/TypeScript) Install the npm package: @@ -84,38 +78,37 @@ The AntiSSRF library provides validation for different scenarios based on your t | Use Case | Description | Documentation Link | |----------|-------------|-------------------| -| **Any Domain** | Validate untrusted URLs belonging to any domain | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) | -| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurestoragedomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurestoragedomain/) | -| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurekeyvaultdomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurekeyvaultdomain/) | -| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [.NET](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/indomain/) \| [Node.js](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/indomain/) | +| **General Case** | The untrusted URL can belong to **any domain** or an **untrusted domain**. | [.NET](../dotnet-api/antissrfpolicy) \| [Node.js](../nodejs-api/antissrfpolicy) | +| **Azure Key Vault Domain** | The untrusted URL must be an **Azure Key Vault endpoint**. | [.NET](../dotnet-api/urivalidator/inazurekeyvaultdomain) \| [Node.js](../nodejs-api/urivalidator/inazurekeyvaultdomain) | +| **Azure Storage Domain** | The untrusted URL must be an **Azure Storage endpoint**. | [.NET](../dotnet-api/urivalidator/inazurestoragedomain/) \| [Node.js](../nodejs-api/urivalidator/inazurestoragedomain/) | +| **Allowlist of Trusted Domains** | The untrusted URL must belong to a **specific, trusted domain**. | [.NET](../dotnet-api/urivalidator/indomain/) \| [Node.js](../nodejs-api/urivalidator/indomain/) | ## Best Practices -1. Use Separate Handlers for External vs. Internal Requests +1. **Use Separate Handlers for External vs. Internal Requests** - Always create separate HTTP clients for external and internal requests so that you can use the stricted security policy possible on each. + Always create separate HTTP clients for external and internal requests so that you can use the strictest security policy possible on each. This approach ensures that external API calls cannot accidentally reach internal services, and internal calls are restricted to only the networks you explicitly trust. When using the `AntiSSRFPolicy`, you can choose different built-in configuration options intended for each use-case. -2. Only Use `InDomain` for Owned and Trusted Domains +2. **Only Use `InDomain` for Owned and Trusted Domains** A domain should only be considered trusted if you fully control both the domain itself and all subdomains. You should trust the DNS responses for these domains and should be sure that no subdomain is configurable by a third party. -3. Add X-Forwarded-For Header whenever possible +3. **Add X-Forwarded-For Header whenever possible** The `X-Forwarded-For` header can be an important defense-in-depth strategy against SSRF vulnerabilities. Some services, including IMDS, will drop all incoming requests with the `X-Forwarded-For` present. By ensuring that the header is added to all outgoing requests, your service can be sure that it will never have an SSRF vulnerability that leaks data from IMDS. -4. Stay up-to-date +4. **Stay up-to-date** Keep the library updated to receive the latest security changes. Instead of using `PolicyConfigOptions.ExternalV1`, consider using `PolicyConfigOptions.ExternalOnlyLatest`. ## Next Steps ### Learn More - -- πŸ“– **API Documentation**: [.NET API](../dotnet-api/) | [Node.js API](../nodejs-api/) -- ❓ **Common Questions**: [FAQ](../faq/) +- πŸ“– **API Documentation**: [.NET API](../dotnet-api) \| [Node.js API](../nodejs-api) +- ❓ **Common Questions**: [FAQ](../faq) ### Get Support - πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) -- πŸ“§ **Contact**: antissrf-oss@microsoft.com +- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) diff --git a/docs/index.md b/docs/index.md index 50a9225..c699d16 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,6 +6,8 @@ description: "Microsoft AntiSSRF Documentation - Protect your applications from permalink: / --- +# Microsoft AntiSSRF Libraries + ## What is Server-Side Request Forgery (SSRF)? Server-Side Request Forgery (also known as SSRF) is a critical web security vulnerability in which an attacker can manipulate the server-side application to make network requests to an arbitrary endpoint. Through this vulnerability, the attacker manipulates the target web server to connect to internal, sensitive networks or exfiltrate sensitive data to an untrusted endpoint on the Internet. @@ -27,15 +29,15 @@ SSRF can lead (but is not limited) to: Even data that doesn't initially appear to be a URL should be treated as one. For example, a workspace name or resource identifier that gets concatenated into a URL. All untrusted input used in URL construction MUST be validated. -## What is the Microsoft `AntiSSRF` Library? +## What is the Microsoft AntiSSRF Library? -The Microsoft `AntiSSRF` library is a security-developed, exhaustively-tested secure code library available for multiple platforms, that provides robust URL validation to mitigate the risk of SSRF vulnerabilities in code where it is integrated. It is an easy-to-use drop-in library with a minimal toil of adoption on developers. +The Microsoft AntiSSRF Library is a security-developed, exhaustively-tested secure code library available for multiple platforms, that provides robust URL validation to mitigate the risk of SSRF vulnerabilities in code where it is integrated. It is an easy-to-use drop-in library with a minimal toil of adoption on developers. ### How the Microsoft AntiSSRF Library Helps A common scenario in many online services is handling requests from customers containing customer-supplied strings that are, or are used to construct a URL. These strings are often not validated properly, leading to vulnerabilities such as Server-Side Request Forgery which can result in token theft. -`AntiSSRF` helps mitigate these risks by: +AntiSSRF helps mitigate these risks by: - Automatically validating URLs and network connections and rejecting/refusing unsafe input - Providing an agent that ensures HTTP requests cannot reach internal or sensitive IP addresses @@ -49,5 +51,17 @@ A common scenario in many online services is handling requests from customers co {: .note } > Broader platform support is under development. -> -> For questions regarding the usage of this library or for more information, please contact [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). + +## Next Steps + +### Learn More + +- οΏ½ **Getting Started**: [Installation and Quick Start Guide](getting-started) +- πŸ“– **API Documentation**: [.NET API](dotnet-api) \| [Node.js API](nodejs-api) +- ❓ **Common Questions**: [FAQ](faq) + +### Get Support + +- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) +- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) + diff --git a/docs/nodejs-api/index.md b/docs/nodejs-api/index.md index b7ccbe4..059c8e9 100755 --- a/docs/nodejs-api/index.md +++ b/docs/nodejs-api/index.md @@ -15,7 +15,7 @@ The **AntiSSRF Node.js Library** is a library for JavaScript/TypeScript applicat ## Usage Instructions -The AntiSSRF library provides validation for different scenarios based on your trust requirements: +The AntiSSRF Library provides validation for different scenarios based on your trust requirements: | Use Case | Description | Documentation Link | | --- | --- | --- | diff --git a/dotnet/src/README.md b/dotnet/src/README.md index b6551dd..6a70c2d 100644 --- a/dotnet/src/README.md +++ b/dotnet/src/README.md @@ -1,23 +1,23 @@ ## Microsoft AntiSSRF for .NET -The Microsoft AntiSSRF library for .NET is a security-developed, exhaustively-tested library that provides robust URL validation to protect .NET applications from Server-Side Request Forgery (SSRF) vulnerabilities. Designed specifically for .NET Framework and .NET Core applications, it integrates seamlessly with `HttpClient` through the `AntiSSRFHandler` class, allowing developers to secure outbound HTTP requests with minimal code changes. +The Microsoft AntiSSRF Library for .NET is a security-developed, exhaustively-tested library that provides robust URL validation to protect .NET applications from Server-Side Request Forgery (SSRF) vulnerabilities. Designed specifically for .NET Framework and .NET Core applications, it integrates seamlessly with `HttpClient` through the `AntiSSRFHandler` class, allowing developers to secure outbound HTTP requests with minimal code changes. ## How to Use -The AntiSSRF library provides validation for different scenarios based on your trust requirements: +The AntiSSRF Library provides validation for different scenarios based on your trust requirements: | Use Case | Description | Documentation Link | -|----------|-------------|-------------------| -| **Any Domain** | Validate untrusted URLs belonging to any domain | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) | -| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [InAzureStorageDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurestoragedomain/) | -| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [InAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurekeyvaultdomain/) | -| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [InDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/indomain/) | +| --- | --- | --- | +| **General Case** | The untrusted URL can belong to **any domain** or an **untrusted domain**. | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy) | +| **Azure Key Vault Domain** | The untrusted URL must be an **Azure Key Vault endpoint**. | [URIValidator.InAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurekeyvaultdomain) | +| **Azure Storage Domain** | The untrusted URL must be an **Azure Storage endpoint**. | [URIValidator.InAzureStorageDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/inazurestoragedomain) | +| **Allowlist of Trusted Domains** | The untrusted URL must belong to a **specific, trusted domain**. | [URIValidator.InDomain](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/indomain) | ## Key Features πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts -🚫 **Private Network Protection** - - Separate built-in configuration options for internal vs. external address HTTP clients +🚫 **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks @@ -33,16 +33,16 @@ Explore our comprehensive documentation to get the most out of Microsoft AntiSSR ### Getting Started - πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) -- πŸš€ **Quick Start Guide**: [Getting Started with .NET](https://microsoft.github.io/AntiSSRF/getting-started/) -- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started/#best-practices) -- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq/) -- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/dotnet-api/changelog/) +- πŸš€ **Quick Start Guide**: [Getting Started with .NET](https://microsoft.github.io/AntiSSRF/getting-started) +- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) +- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) +- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/dotnet-api/changelog) ### API Documentation -- πŸ”§ **C# API Reference**: [Complete .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/) -- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfhandler/) -- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy/) -- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator/) +- πŸ”§ **C# API Reference**: [Complete .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api) +- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfhandler) +- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy) +- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator) ## Feedback & Contributing @@ -50,8 +50,8 @@ We welcome feedback and contributions from the community! Here's how you can get - πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features - 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project -- πŸ“§ **Contact**: antissrf-oss@microsoft.com - Direct email for questions and feedback +- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback ## Support Policy -For support inquiries, contact antissrf-oss@microsoft.com. \ No newline at end of file +For support inquiries, contact [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). \ No newline at end of file diff --git a/nodejs/README.md b/nodejs/README.md index a8447a5..b599661 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -1,23 +1,23 @@ ## Microsoft AntiSSRF for Node.js -The Microsoft AntiSSRF library for Node.js is a security-developed, exhaustively-tested library that provides robust URL validation to protect Node.js applications from Server-Side Request Forgery (SSRF) vulnerabilities. It integrates seamlessly with Node.js HTTP/HTTPS agents, allowing developers to secure outbound HTTP requests with minimal code changes. +The Microsoft AntiSSRF Library for Node.js is a security-developed, exhaustively-tested library that provides robust URL validation to protect Node.js applications from Server-Side Request Forgery (SSRF) vulnerabilities. It integrates seamlessly with Node.js HTTP/HTTPS agents, allowing developers to secure outbound HTTP requests with minimal code changes. ## How to Use -The AntiSSRF library provides validation for different scenarios based on your trust requirements: +The AntiSSRF Library provides validation for different scenarios based on your trust requirements: | Use Case | Description | Documentation Link | -|----------|-------------|-------------------| -| **Any Domain** | Validate untrusted URLs belonging to any domain | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) | -| **Azure Storage Domain** | Validate that URLs are Azure Storage endpoints | [inAzureStorageDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurestoragedomain/) | -| **Azure Key Vault Domain** | Validate URLs are Azure Key Vault endpoints | [inAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurekeyvaultdomain/) | -| **Allowlist of Trusted Domains** | Validate that URLs belong to your custom allowlist of trusted domains | [inDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/indomain/) | +| --- | --- | --- | +| **General Case** | The untrusted URL can belong to **any domain** or an **untrusted domain**. | [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy) | +| **Azure Key Vault Domain** | The untrusted URL must be an **Azure Key Vault endpoint**. | [URIValidator.inAzureKeyVaultDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurekeyvaultdomain) | +| **Azure Storage Domain** | The untrusted URL must be an **Azure Storage endpoint**. | [URIValidator.inAzureStorageDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/inazurestoragedomain) | +| **Allowlist of Trusted Domains** | The untrusted URL must belong to a **specific, trusted domain**. | [URIValidator.inDomain](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/indomain) | ## Key Features πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts -🚫 **Private Network Protection** - - Separate built-in configuration options for internal vs. external address HTTP clients +🚫 **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks @@ -33,16 +33,16 @@ Explore our comprehensive documentation to get the most out of Microsoft AntiSSR ### Getting Started - πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) -- πŸš€ **Quick Start Guide**: [Getting Started with Node.js](https://microsoft.github.io/AntiSSRF/getting-started/) -- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started/#best-practices) -- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq/) -- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/nodejs-api/changelog/) +- πŸš€ **Quick Start Guide**: [Getting Started with Node.js](https://microsoft.github.io/AntiSSRF/getting-started) +- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) +- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) +- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/nodejs-api/changelog) ### API Documentation -- πŸ”§ **JavaScript API Reference**: [Complete Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) -- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfhandler/) -- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy/) -- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator/) +- πŸ”§ **JavaScript API Reference**: [Complete Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api) +- πŸ›‘οΈ **Node.js Agent**: [HTTP Agent Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfhandler) +- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy) +- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator) ## Feedback & Contributing @@ -50,8 +50,8 @@ We welcome feedback and contributions from the community! Here's how you can get - πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features - 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project -- πŸ“§ **Contact**: antissrf-oss@microsoft.com - Direct email for questions and feedback +- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback ## Support Policy -For support inquiries, contact antissrf-oss@microsoft.com. \ No newline at end of file +For support inquiries, contact [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). \ No newline at end of file From 7b69a01cf9a730b0fc084b54ea05607e731a7072 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Mon, 4 May 2026 10:21:05 -0700 Subject: [PATCH 5/7] starting samples --- docs/nodejs-api/changelog.md | 2 +- docs/nodejs-api/samples/axios.md | 121 ++++++++++++++++++++ docs/nodejs-api/samples/follow-redirects.md | 76 ++++++++++++ docs/nodejs-api/samples/index.md | 11 ++ docs/nodejs-api/samples/node-fetch.md | 0 5 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 docs/nodejs-api/samples/axios.md create mode 100644 docs/nodejs-api/samples/follow-redirects.md create mode 100644 docs/nodejs-api/samples/index.md create mode 100644 docs/nodejs-api/samples/node-fetch.md diff --git a/docs/nodejs-api/changelog.md b/docs/nodejs-api/changelog.md index aa0cb25..76c3d30 100644 --- a/docs/nodejs-api/changelog.md +++ b/docs/nodejs-api/changelog.md @@ -2,7 +2,7 @@ layout: default title: Changelog parent: Node.js API Reference -nav_order: 99 +nav_order: 98 description: "Release notes and version history for AntiSSRF Node.js Library" --- diff --git a/docs/nodejs-api/samples/axios.md b/docs/nodejs-api/samples/axios.md new file mode 100644 index 0000000..718587d --- /dev/null +++ b/docs/nodejs-api/samples/axios.md @@ -0,0 +1,121 @@ +--- +layout: default +title: Axios +parent: Samples +grand_parent: Node.js API Reference +description: "AntiSSRF agent with Axios" +--- + +# AntiSSRFPolicy with the Axios Library + +## Introduction + +[Axios](https://axios-http.com/docs/intro) is one of the most commonly used request libraries for JavaScript/TypeScript. It is very easy to use with the AntiSSRF Node.js Library, as shown in the examples below. + +{: .important } +> Be careful of options that can bypass AntiSSRF protections: +> * Changing the `adapter` option could lead to requests without a Node.js agent, and therefore without the `AntiSSRFPolicy` applied. +> * Like the AntiSSRF agents themselves, using a custom `lookup` function will bypass the IP address validations from `AntiSSRFPolicy`. +> * Using `proxy` with AntiSSRF will largely not work, since the `AntiSSRFPolicy` will not be used once control is passed to the proxy. + +## Axios with Axios Instance + +Axios allows you to create an Axios instance with a custom `config` including the `AntiSSRFPolicy` agents. As long as you don't overwrite the request `config` agents, the instance will enforce the policy. + +### Setup + +Set up the `AntiSSRFPolicy`, then create an Axios instance with the AntiSSRF agents from the policy. + +```js +import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +import axios from "axios"; + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Use the policy with Axios +const secureClient = axios.create({ + httpAgent: policy.getHttpAgent(), + httpsAgent: policy.getHttpsAgent({ keepAlive: true }) +}); +``` + +### Use the Axios Instance for Requests + +Every request to an endpoint with untrusted input should use the `secureClient`. + +```js +secureClient.get( + "<some_https_url_constructed_with_untrusted_input>", + { + auth: { + username: 'janedoe', + password: 's00pers3cret' + } + }) + .then(function (res) { + /** + * Will get here if the untrusted URL does NOT direct the request to + * an internal or special-use IP address + */ + }) + .catch(function (err) { + /** + * Will get here if the untrusted URL directs the request to an + * internal or special-use IP address + */ + }); +``` + +## Axios with Request Agents + +Just like Node.js requests, Axios allows you to add agents to individual requests. + + +### Setup + +Set up the `AntiSSRFPolicy`, then get the AntiSSRF agents from the policy. + +```js +import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +import axios from "axios"; + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Get the AntiSSRF agents +const httpAgent = policy.getHttpAgent(); +const httpsAgent = policy.getHttpsAgent({ keepAlive: true }); +``` + +### Use the AntiSSRF Agents for Requests + +Every request to an endpoint with untrusted input should include the AntiSSRF agents. + +```js +axios.get( + "<some_https_url_constructed_with_untrusted_input>", + { + httpAgent: httpAgent, + httpsAgent: httpsAgent, + auth: { + username: 'janedoe', + password: 's00pers3cret' + } + }) + .then(function (res) { + /** + * Will get here if the untrusted URL does NOT direct the request to + * an internal or special-use IP address + */ + }) + .catch(function (err) { + /** + * Will get here if the untrusted URL directs the request to an + * internal or special-use IP address + */ + }); +``` + +{: .note } +> If you want different examples or if you find any bug while using `AntiSSRFPolicy` with Axios, please let us know at [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). diff --git a/docs/nodejs-api/samples/follow-redirects.md b/docs/nodejs-api/samples/follow-redirects.md new file mode 100644 index 0000000..bd58e9b --- /dev/null +++ b/docs/nodejs-api/samples/follow-redirects.md @@ -0,0 +1,76 @@ +--- +layout: default +title: follow-redirects +parent: Samples +grand_parent: Node.js API Reference +description: "AntiSSRF agent with follow-redirects" +--- + +# AntiSSRFPolicy with the follow-redirects Library + +## Introduction + +The [follow-redirects library](https://github.com/follow-redirects/follow-redirects/blob/694d6b47a42bc8377e5ef1480394de451e16bd5b/README.md) is a commonly used request library to extend Node.js http(s) functionality with the ability to automatically follow redirects. The example below shows how you can use the follow-redirects library with the AntiSSRF Node.js library. + +> [!NOTE] +> Be careful if you use the `wrap` method, since this could lead to requests without a NodeJS agent, and therefore without the `AntiSSRFPolicy` applied. + +{: .important } +> Be careful of options that can bypass AntiSSRF protections: +> * Changing the `adapter` option could lead to requests without a Node.js agent, and therefore without the `AntiSSRFPolicy` applied. +> * Like the AntiSSRF agents themselves, using a custom `lookup` function will bypass the IP address validations from `AntiSSRFPolicy`. +> * Using `proxy` with AntiSSRF will largely not work, since the `AntiSSRFPolicy` will not be used once control is passed to the proxy. + +## Example + +follow-redirects allows you to [make requests](https://github.com/follow-redirects/follow-redirects/blob/694d6b47a42bc8377e5ef1480394de451e16bd5b/README.md#per-request-options) either with the option `agent`, like in normal NodeJS requests, or the option `agents`, with both `http` and `https` agents for use in redirects. + +### Setup + +Set up the AntiSSRF policy for your specific use case, then get the AntiSSRF agents from the policy. + +```TypeScript +import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +import { http, https } from "follow-redirects"; + +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +const agents = { + httpAgent: policy.getHttpAgent(), + httpsAgent: policy.getHttpsAgent({ keepAlive: true }) +} +``` + +### Use the AntiSSRF Agents for Requests + +Every request to an endpoint with untrusted input should include the AntiSSRF agents. + +```TypeScript +const httpsReq = https.get( + "<some_https_url_constructed_with_untrusted_input>", + { + agents: agents, + auth: { + username: 'janedoe', + password: 's00pers3cret' + } + }, + (res) => { + /** + * Will get here if the untrusted URL does NOT direct the request to an internal, + * sensitive IP address + */ + }); + +httpsReq.on("error", (err) => { + /** + * Will get here if the untrusted URL directs the request to an internal, + * sensitive IP address + */ +}); + +httpsReq.end(); +``` + +> [!NOTE] +> If you want different examples or if you find any bug while using `AntiSSRFPolicy` with follow-redirects, please let us know at [antissrf@microsoft.com](mailto:antissrf@microsoft.com). diff --git a/docs/nodejs-api/samples/index.md b/docs/nodejs-api/samples/index.md new file mode 100644 index 0000000..bba5278 --- /dev/null +++ b/docs/nodejs-api/samples/index.md @@ -0,0 +1,11 @@ +--- +layout: default +title: Samples +parent: Node.js API Reference +description: "Sample code for agent integration" +nav_order: 99 +has_children: true +has_toc: false +--- + +TODO \ No newline at end of file diff --git a/docs/nodejs-api/samples/node-fetch.md b/docs/nodejs-api/samples/node-fetch.md new file mode 100644 index 0000000..e69de29 From 19288b648d1d7380da7bff5b51255b2f5effa576 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Mon, 4 May 2026 11:12:28 -0700 Subject: [PATCH 6/7] samples --- docs/nodejs-api/samples/axios.md | 4 +- docs/nodejs-api/samples/follow-redirects.md | 30 +++++----- docs/nodejs-api/samples/index.md | 5 +- docs/nodejs-api/samples/node-fetch.md | 64 +++++++++++++++++++++ 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/docs/nodejs-api/samples/axios.md b/docs/nodejs-api/samples/axios.md index 718587d..3569618 100644 --- a/docs/nodejs-api/samples/axios.md +++ b/docs/nodejs-api/samples/axios.md @@ -27,7 +27,7 @@ Axios allows you to create an Axios instance with a custom `config` including th Set up the `AntiSSRFPolicy`, then create an Axios instance with the AntiSSRF agents from the policy. ```js -import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +import { AntiSSRFPolicy, PolicyConfigOptions } from '@microsoft/antissrf'; import axios from "axios"; // Customize the policy @@ -77,7 +77,7 @@ Just like Node.js requests, Axios allows you to add agents to individual request Set up the `AntiSSRFPolicy`, then get the AntiSSRF agents from the policy. ```js -import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +import { AntiSSRFPolicy, PolicyConfigOptions } from '@microsoft/antissrf'; import axios from "axios"; // Customize the policy diff --git a/docs/nodejs-api/samples/follow-redirects.md b/docs/nodejs-api/samples/follow-redirects.md index bd58e9b..39e065c 100644 --- a/docs/nodejs-api/samples/follow-redirects.md +++ b/docs/nodejs-api/samples/follow-redirects.md @@ -12,29 +12,27 @@ description: "AntiSSRF agent with follow-redirects" The [follow-redirects library](https://github.com/follow-redirects/follow-redirects/blob/694d6b47a42bc8377e5ef1480394de451e16bd5b/README.md) is a commonly used request library to extend Node.js http(s) functionality with the ability to automatically follow redirects. The example below shows how you can use the follow-redirects library with the AntiSSRF Node.js library. -> [!NOTE] -> Be careful if you use the `wrap` method, since this could lead to requests without a NodeJS agent, and therefore without the `AntiSSRFPolicy` applied. - {: .important } > Be careful of options that can bypass AntiSSRF protections: -> * Changing the `adapter` option could lead to requests without a Node.js agent, and therefore without the `AntiSSRFPolicy` applied. +> * Changing the `wrap` option could lead to requests without a Node.js agent, and therefore without the `AntiSSRFPolicy` applied. > * Like the AntiSSRF agents themselves, using a custom `lookup` function will bypass the IP address validations from `AntiSSRFPolicy`. -> * Using `proxy` with AntiSSRF will largely not work, since the `AntiSSRFPolicy` will not be used once control is passed to the proxy. ## Example -follow-redirects allows you to [make requests](https://github.com/follow-redirects/follow-redirects/blob/694d6b47a42bc8377e5ef1480394de451e16bd5b/README.md#per-request-options) either with the option `agent`, like in normal NodeJS requests, or the option `agents`, with both `http` and `https` agents for use in redirects. +follow-redirects allows you to [make requests](https://github.com/follow-redirects/follow-redirects/blob/694d6b47a42bc8377e5ef1480394de451e16bd5b/README.md#per-request-options) either with the option `agent`, like in normal Node.js requests, or the option `agents`, with both `http` and `https` agents for use in redirects. ### Setup -Set up the AntiSSRF policy for your specific use case, then get the AntiSSRF agents from the policy. +Set up the `AntiSSRFPolicy`, then get the AntiSSRF agents from the policy. -```TypeScript -import { AntiSSRFPolicy, PolicyConfigOptions } from '@azuresecurity/antissrf'; +```js +import { AntiSSRFPolicy, PolicyConfigOptions } from '@microsoft/antissrf'; import { http, https } from "follow-redirects"; +// Customize the policy const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); +// Get the AntiSSRF agents const agents = { httpAgent: policy.getHttpAgent(), httpsAgent: policy.getHttpsAgent({ keepAlive: true }) @@ -45,7 +43,7 @@ const agents = { Every request to an endpoint with untrusted input should include the AntiSSRF agents. -```TypeScript +```js const httpsReq = https.get( "<some_https_url_constructed_with_untrusted_input>", { @@ -57,20 +55,20 @@ const httpsReq = https.get( }, (res) => { /** - * Will get here if the untrusted URL does NOT direct the request to an internal, - * sensitive IP address + * Will get here if the untrusted URL does NOT direct the request to + * an internal or special-purpose IP address */ }); httpsReq.on("error", (err) => { /** - * Will get here if the untrusted URL directs the request to an internal, - * sensitive IP address + * Will get here if the untrusted URL directs the request to an internal + * or special-purpose IP address */ }); httpsReq.end(); ``` -> [!NOTE] -> If you want different examples or if you find any bug while using `AntiSSRFPolicy` with follow-redirects, please let us know at [antissrf@microsoft.com](mailto:antissrf@microsoft.com). +{: .note } +> If you want different examples or if you find any bug while using `AntiSSRFPolicy` with follow-redirects, please let us know at [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). diff --git a/docs/nodejs-api/samples/index.md b/docs/nodejs-api/samples/index.md index bba5278..69ee6ec 100644 --- a/docs/nodejs-api/samples/index.md +++ b/docs/nodejs-api/samples/index.md @@ -8,4 +8,7 @@ has_children: true has_toc: false --- -TODO \ No newline at end of file +Sample code showing AntiSSRF integrating with common open-source request libraries: +* [Axios](axios) - Popular promise-based HTTP client for Node.js +* [follow-redirects](follow-redirects) - HTTP and HTTPS modules that follow redirects +* [node-fetch](node-fetch) - A light-weight module bringing Fetch API to Node.js \ No newline at end of file diff --git a/docs/nodejs-api/samples/node-fetch.md b/docs/nodejs-api/samples/node-fetch.md index e69de29..9f11189 100644 --- a/docs/nodejs-api/samples/node-fetch.md +++ b/docs/nodejs-api/samples/node-fetch.md @@ -0,0 +1,64 @@ +--- +layout: default +title: node-fetch +parent: Samples +grand_parent: Node.js API Reference +description: "AntiSSRF agent with node-fetch" +--- + +# AntiSSRFPolicy with the node-fetch Library + +## Introduction + +The [node-fetch library](https://github.com/node-fetch/node-fetch/tree/2.x#readme) is a commonly used request library to extend Node.js http(s) functionality with a `window.fetch` compatible API. The example below shows how you can use the node-fetch library with the AntiSSRF Node.js library. + +## Example + +node-fetch allows you to make requests with the option `agent`, which is either a Node.js HTTP/S agent or a function to return a Node.js HTTP/S agent. + +### Setup + +Set up the `AntiSSRFPolicy`, then get the AntiSSRF agents from the policy. + +```js +import { AntiSSRFPolicy, PolicyConfigOptions } from '@microsoft/antissrf'; +import fetch from "node-fetch"; + +// Customize the policy +const policy = new AntiSSRFPolicy(PolicyConfigOptions.ExternalOnlyLatest); + +// Get the AntiSSRF agents +const httpAgent = policy.getHttpAgent(); +const httpsAgent = policy.getHttpsAgent({ keepAlive: true }); + +const agentFn = (_parsedURL: URL) => { + return _parsedURL.protocol === "https:" ? httpsAgent : httpAgent; +} +``` + +### Use the AntiSSRF Agents for Requests + +Every request to an endpoint with untrusted input should include the AntiSSRF agents. + +```js +fetch( + "<some_https_url_constructed_with_untrusted_input>", + { + agent: agentFn + }) + .then((res) => { + /** + * Will get here if the untrusted URL does NOT direct the request to + * an internal or special-purpose IP address + */ + }) + .catch((err) => { + /** + * Will get here if the untrusted URL directs the request to an internal + * or special-purpose IP address + */ + }); +``` + +{: .note } +> If you want different examples or if you find any bug while using `AntiSSRFPolicy` with node-fetch, please let us know at [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com). From 48f279fda8069789fcfecef15c7a68aaee648ce7 Mon Sep 17 00:00:00 2001 From: Leah Restad <leahrestad@microsoft.com> Date: Mon, 4 May 2026 15:12:18 -0700 Subject: [PATCH 7/7] feedback --- .github/ISSUE_TEMPLATE/feature_request.yml | 12 +++---- README.md | 17 +++++++-- docs/dotnet-api/antissrfpolicy/constructor.md | 4 +-- .../methods/addallowedaddresses.md | 3 ++ .../properties/denyallunspecifiedips.md | 2 +- docs/nodejs-api/antissrfpolicy/constructor.md | 4 +-- .../properties/denyallunspecifiedips.md | 2 +- dotnet/src/README.md | 36 +++++++++---------- nodejs/README.md | 36 +++++++++---------- 9 files changed, 64 insertions(+), 52 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index bbafeab..4f3e2c9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -43,17 +43,15 @@ body: validations: required: false - - type: dropdown + - type: checkboxes attributes: label: Applicable Libraries - description: Select which AntiSSRF library or libraries this feature request applies to. + description: Select all that apply for which AntiSSRF library or libraries this feature request applies to. options: - - .NET Library - - Node.js Library - - Both Libraries - - None or N/A + - label: .NET Library + - label: Node.js Library validations: - required: true + required: false - type: markdown attributes: diff --git a/README.md b/README.md index a93318b..67c89a6 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,17 @@ SSRF can lead (but is not limited) to: - Service disruption - Remote code execution +### What is "Untrusted" Input? + +**All incoming HTTP requests are untrusted.** Any data originating from outside your service's immediate trust boundary must be treated as potentially malicious. This includes: + +- User-provided URLs, filenames, or identifiers +- Data from external APIs, webhooks, or partner services +- Configuration values, metadata, or file contents that users can influence +- Requests from your own service's backend applications or other components within the same environment (query parameters, headers, form fields, etc.) + +Even data that doesn't initially appear to be a URL should be treated as one. For example, a workspace name or resource identifier that gets concatenated into a URL. All untrusted input used in URL construction MUST be validated. + ## How the Microsoft AntiSSRF Library Helps A common scenario in many online services is handling requests from customers containing customer-supplied strings that are, or are used to construct a URL. These strings are often not validated properly, leading to vulnerabilities such as Server-Side Request Forgery which can result in token theft. @@ -22,17 +33,17 @@ AntiSSRF helps mitigate these risks by: ## Getting Started -### .NET Framework and .NET Core +### C# (.NET Framework and .NET Core) - πŸ“¦ **NuGet Package**: [Microsoft.Security.AntiSSRF](https://www.nuget.org/packages/Microsoft.Security.AntiSSRF/) -- πŸ“– **Documentation**: [AntiSSRF C# API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) +- πŸ“– **Documentation**: [AntiSSRF .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/) - πŸš€ **Quick Start**: [Getting Started Guide](https://microsoft.github.io/AntiSSRF/getting-started) - πŸ“‹ **Library README**: [.NET README](dotnet/README.md) ### JavaScript/TypeScript (Node.js) - πŸ“¦ **npm Package**: [@microsoft/antissrf](https://www.npmjs.com/package/@microsoft/antissrf) -- πŸ“– **Documentation**: [AntiSSRF JavaScript API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) +- πŸ“– **Documentation**: [AntiSSRF Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/) - πŸš€ **Quick Start**: [Getting Started Guide](https://microsoft.github.io/AntiSSRF/getting-started) - πŸ“‹ **Library README**: [Node.js README](nodejs/README.md) diff --git a/docs/dotnet-api/antissrfpolicy/constructor.md b/docs/dotnet-api/antissrfpolicy/constructor.md index 8b35e41..87ac853 100644 --- a/docs/dotnet-api/antissrfpolicy/constructor.md +++ b/docs/dotnet-api/antissrfpolicy/constructor.md @@ -2,7 +2,7 @@ layout: default title: Constructor parent: AntiSSRFPolicy -grandparent: .NET API Reference +grand_parent: .NET API Reference nav_order: 1 description: "AntiSSRFPolicy constructor documentation" --- @@ -27,7 +27,7 @@ Choose from the following predefined policy configurations: | Option | Use Case | Behavior | | --- | --- | --- | -| **InternalOnly** | Making requests to internal addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [AddAllowedAddresses](../methods/addallowedaddresses). | +| **InternalOnly** | Making requests to internal, non-public addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [AddAllowedAddresses](../methods/addallowedaddresses). | | **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedrangesv1). Automatically adds `X-Forwarded-For` header to requests. | | **ExternalOnlyLatest** | Currently the same as `ExternalOnlyV1` with automatic security updates | Always stays up to date with the latest `ExternalOnly` version, independent of semantic versioning. | | **None** | Custom policy configuration | No restrictions applied. Requires manual configuration via policy methods. | diff --git a/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md b/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md index 1e27fee..52b9eff 100644 --- a/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md +++ b/docs/dotnet-api/antissrfpolicy/methods/addallowedaddresses.md @@ -41,6 +41,9 @@ The list of IP networks to be explicitly allowed by the policy. ```csharp using Microsoft.Security.AntiSSRF; +using System; +using System.Net.Http; +using System.Threading.Tasks; // Customize the policy var policy = new AntiSSRFPolicy(PolicyConfigOptions.None); diff --git a/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md index a0877cc..a0e4ddd 100644 --- a/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md +++ b/docs/dotnet-api/antissrfpolicy/properties/denyallunspecifiedips.md @@ -14,7 +14,7 @@ description: "DenyAllUnspecifiedIPs property documentation" Determines whether all IP addresses should be blocked by default or only `DeniedAddresses` should be blocked. {: .note } -> To allow specific addresses, use `AddAllowedAddresses`. +> To allow specific addresses, see [addAllowedAddresses](../methods/addallowedaddresses). ```csharp public bool DenyAllUnspecifiedIPs { get; set; } diff --git a/docs/nodejs-api/antissrfpolicy/constructor.md b/docs/nodejs-api/antissrfpolicy/constructor.md index d4520db..5ed2ad6 100644 --- a/docs/nodejs-api/antissrfpolicy/constructor.md +++ b/docs/nodejs-api/antissrfpolicy/constructor.md @@ -28,7 +28,7 @@ Choose from the following predefined policy configurations: | Option | Use Case | Behavior | | --- | --- | --- | -| **InternalOnly** | Making requests to internal addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [addAllowedAddresses](../methods/addallowedaddresses). | +| **InternalOnly** | Making requests to internal, non-public addresses only **OR** restricting requests to specific allowed addresses | Blocks all IP addresses by default. Only allows addresses explicitly added via [addAllowedAddresses](../methods/addallowedaddresses). | | **ExternalOnlyV1** | Making requests to external APIs while blocking internal access | Blocks internal and special-purpose IP addresses per [IPAddressRanges.recommendedV1](../../ipaddressranges#recommendedrangesv1). Automatically adds `X-Forwarded-For` header to requests. | | **ExternalOnlyLatest** | Currently the same as `ExternalOnlyV1` with automatic security updates | Always stays up to date with the latest `ExternalOnly` version, independent of semantic versioning. | | **None** | Custom policy configuration | No restrictions applied. Requires manual configuration via policy methods. | @@ -40,7 +40,7 @@ Choose from the following predefined policy configurations: To prevent SSRF vulnerabilities, it is a best practice to ensure that your code can make requests to external endpoints or to internal endpoints, but never both. -If your service needs to make requests to external endpoints, you need to make sure that it can’t be abused to access internal resources. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. +If your service needs to make requests to external endpoints, you need to make sure that it cannot be abused to access internal resources. In this case, we recommend using `PolicyConfigOptions.ExternalOnlyLatest`, which takes care of blocking internal and special-purpose addresses automatically. If your service needs to make requests to backend services, you must prevent data exfiltration by ensuring it cannot be used to send data to external endpoints. In this case, we recommend using `PolicyConfigOptions.InternalOnly` to block all unspecified addresses, then use `addAllowedAddresses(...)` with the specific internal IP addresses that your service might need to access. diff --git a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md index 10d48d0..209d3d0 100644 --- a/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md +++ b/docs/nodejs-api/antissrfpolicy/properties/denyallunspecifiedips.md @@ -14,7 +14,7 @@ description: "denyAllUnspecifiedIPs property documentation" Determines whether all IP addresses should be blocked by default or only `deniedAddresses` should be blocked. {: .note } -> To allow specific addresses, use `addAllowedAddresses`. +> To allow specific addresses, see [addAllowedAddresses](../methods/addallowedaddresses). ```js denyAllUnspecifiedIPs: boolean { get; set; } diff --git a/dotnet/src/README.md b/dotnet/src/README.md index 6a70c2d..b9414a2 100644 --- a/dotnet/src/README.md +++ b/dotnet/src/README.md @@ -15,42 +15,42 @@ The AntiSSRF Library provides validation for different scenarios based on your t ## Key Features -πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts +* **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts -🚫 **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients +* **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients -πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks +* **DNS Rebinding Protection** - Guards against DNS-based attacks -πŸ”„ **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts +* **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts -🌐 **Protocol Validation** - Ensures only safe protocols are used +* **Protocol Validation** - Ensures only safe protocols are used -βš™οΈ **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies +* **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies ## Additional Documentation Explore our comprehensive documentation to get the most out of Microsoft AntiSSRF: ### Getting Started -- πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) -- πŸš€ **Quick Start Guide**: [Getting Started with .NET](https://microsoft.github.io/AntiSSRF/getting-started) -- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) -- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) -- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/dotnet-api/changelog) +- [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) +- [Quick Start Guide](https://microsoft.github.io/AntiSSRF/getting-started) +- [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) +- [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) +- [Changelog](https://microsoft.github.io/AntiSSRF/dotnet-api/changelog) ### API Documentation -- πŸ”§ **C# API Reference**: [Complete .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api) -- πŸ›‘οΈ **AntiSSRFHandler**: [HTTP Handler Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfhandler) -- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy) -- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator) +- [Complete .NET API Documentation](https://microsoft.github.io/AntiSSRF/dotnet-api) +- [AntiSSRFHandler](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfhandler) +- [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/dotnet-api/antissrfpolicy) +- [URIValidator](https://microsoft.github.io/AntiSSRF/dotnet-api/urivalidator) ## Feedback & Contributing We welcome feedback and contributions from the community! Here's how you can get involved: -- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features -- 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project -- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback +- **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features +- **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project +- **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback ## Support Policy diff --git a/nodejs/README.md b/nodejs/README.md index b599661..183f897 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -15,42 +15,42 @@ The AntiSSRF Library provides validation for different scenarios based on your t ## Key Features -πŸ›‘οΈ **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts +* **SSRF Attack Prevention** - Blocks malicious server-side request forgery attempts -🚫 **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients +* **Private Network Protection** - Separate built-in configuration options for internal vs. external address HTTP clients -πŸ”’ **DNS Rebinding Protection** - Guards against DNS-based attacks +* **DNS Rebinding Protection** - Guards against DNS-based attacks -πŸ”„ **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts +* **Redirect Protection** - Re-validates on all redirects to prevent bypass attempts -🌐 **Protocol Validation** - Ensures only safe protocols are used +* **Protocol Validation** - Ensures only safe protocols are used -βš™οΈ **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies +* **Fully Customizable** - Configure domain allowlists, IP ranges, headers, and validation policies ## Additional Documentation Explore our comprehensive documentation to get the most out of Microsoft AntiSSRF: ### Getting Started -- πŸ“– **Documentation Home**: [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) -- πŸš€ **Quick Start Guide**: [Getting Started with Node.js](https://microsoft.github.io/AntiSSRF/getting-started) -- πŸ’‘ **Best Practices**: [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) -- ❓ **FAQ**: [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) -- πŸ”„ **Changelog**: [Version History and Updates](https://microsoft.github.io/AntiSSRF/nodejs-api/changelog) +- [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/) +- [Quick Start Guide](https://microsoft.github.io/AntiSSRF/getting-started) +- [Security Best Practices](https://microsoft.github.io/AntiSSRF/getting-started#best-practices) +- [Frequently Asked Questions](https://microsoft.github.io/AntiSSRF/faq) +- [Changelog](https://microsoft.github.io/AntiSSRF/nodejs-api/changelog) ### API Documentation -- πŸ”§ **JavaScript API Reference**: [Complete Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api) -- πŸ›‘οΈ **Node.js Agent**: [HTTP Agent Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfhandler) -- βš™οΈ **AntiSSRFPolicy**: [Policy Configuration Guide](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy) -- πŸ” **URIValidator**: [URL Validation Methods](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator) +- [Complete Node.js API Documentation](https://microsoft.github.io/AntiSSRF/nodejs-api) +- [AntiSSRF Node.js Agent](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfhandler) +- [AntiSSRFPolicy](https://microsoft.github.io/AntiSSRF/nodejs-api/antissrfpolicy) +- [URIValidator](https://microsoft.github.io/AntiSSRF/nodejs-api/urivalidator) ## Feedback & Contributing We welcome feedback and contributions from the community! Here's how you can get involved: -- πŸ› **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features -- 🀝 **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project -- πŸ“§ **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback +- **Report Issues**: [GitHub Issues](https://github.com/Microsoft/AntiSSRF/issues) - Report bugs or request new features +- **Contribute**: [Contributing Guide](https://github.com/Microsoft/AntiSSRF/blob/main/CONTRIBUTING.md) - Learn how to contribute to the project +- **Contact**: [antissrf-oss@microsoft.com](mailto:antissrf-oss@microsoft.com) - Direct email for questions and feedback ## Support Policy