hyperswitch icon indicating copy to clipboard operation
hyperswitch copied to clipboard

feat(security): add XSS and sqli validation for dashboard metadata fields

Open kanikabansal-juspay opened this issue 7 months ago • 1 comments

Type of Change

  • [ ] Bugfix
  • [ ] New feature
  • [x] Enhancement
  • [ ] Refactoring
  • [ ] Dependency updates
  • [ ] Documentation
  • [ ] CI/CD

Description

Added comprehensive XSS (Cross-Site Scripting) and SQLi protection to dashboard metadata fields. Implemented a new SafeString type wrapper that validates input against XSS attacks during JSON deserialization.

Dependencies Added

  • ammonia = "3.3" - HTML sanitization library
  • urlencoding = "2.1.3" - URL decoding for encoded payloads

Additional Changes

  • [ ] This PR modifies the API contract
  • [ ] This PR modifies the database schema
  • [ ] This PR modifies application configuration/environment variables

Motivation and Context

  • XSS vulnerability in dashboard metadata fields (legal_business_name, description, etc.)
  • Malicious JavaScript payloads were being persistently stored and executed

How did you test it?

Testing

XSS Test Cases Validated

All malicious payloads return 400 Bad Request with validation error:

{
    "error": {
        "error_type": "invalid_request",
        "message": "Json deserialize error: Input contains potentially malicious content at line 5 column 62",
        "code": "IR_06"
    }
}

1. Basic Script Tags

{
    "ProdIntent": {
        "legal_business_name": "<script>alert('xss')</script>"
    }
}

2. Event Handlers

{
    "ProdIntent": {
        "comments": "onload=alert('xss') onclick=alert('xss') onmouseover=alert('xss')"
    }
}

3. JavaScript URLs

{
    "ProdIntent": {
        "business_website": "javascript:alert('xss')"
    }
}

4. Data URLs

{
    "ProdIntent": {
        "business_website": "data:text/html,<script>alert('xss')</script>"
    }
}

5. Dangerous Tags (iframe, svg, object, embed)

{
    "ProdIntent": {
        "legal_business_name": "<iframe src=javascript:alert('xss')></iframe>"
    }
}

6. SVG with Script

{
    "ProdIntent": {
        "legal_business_name": "<svg><script>alert('xss')</script></svg>"
    }
}

7. Object/Embed Tags

{
    "ProdIntent": {
        "legal_business_name": "<object data=javascript:alert('xss')></object>"
    }
}

8. Mixed Case and Encoded Payloads

{
    "ProdIntent": {
        "legal_business_name": "<ScRiPt>alert('xss')</ScRiPt>"
    }
}

9. Multiple Fields with XSS

{
    "ProdIntent": {
        "legal_business_name": "<script>alert('xss1')</script>",
        "business_website": "javascript:alert('xss2')",
        "comments": "onload=alert('xss3')"
    }
}

10. Edge Cases

{
    "ProdIntent": {
        "legal_business_name": "Test<script>alert('xss')</script>Company"
    }
}

11. Math/Embedded Objects

{
    "ProdIntent": {
        "legal_business_name": "<math><script>alert('xss')</script></math>"
    }
}

12. Percent Encoding

{
    "ProdIntent": {
        "legal_business_name": "javascript%3Aalert('xss')"
    }
}

13. Basic Tautology Injection

{
  "ProdIntent": {
    "legal_business_name": "' OR '1'='1"
  }
}

14. Blind SQL Injection (time-based)

{
  "ProdIntent": {
    "legal_business_name": "' OR SLEEP(5) --"
  }
}

15. Encoded SQL Injection (percent encoding)

{
  "ProdIntent": {
    "legal_business_name": "%27%20OR%20%271%27%3D%271"
  }
}

Valid Data Test Case

1. Legitimate Business Data

{
    "ProdIntent": {
        "poc_email": "[email protected]",
        "is_completed": true,
        "legal_business_name": "My Test Company Ltd.",
        "business_location": "IN",
        "business_website": "https://example.com",
        "poc_name": "Kanika Bansal",
        "business_country_name": "India",
        "product_type": "orchestration",
        "comments": "This is a legitimate business comment with no malicious content."
    }
}

200 OK

Checklist

  • [ ] I formatted the code cargo +nightly fmt --all
  • [ ] I addressed lints thrown by cargo clippy
  • [ ] I reviewed the submitted code
  • [ ] I added unit tests for my changes where possible

kanikabansal-juspay avatar Aug 29 '25 10:08 kanikabansal-juspay

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/utils/user/dashboard_metadata.rs  90% smaller
  crates/router/src/services/email/types.rs  79% smaller
  crates/router/src/core/user/dashboard_metadata.rs  60% smaller
  Cargo.lock Unsupported file format
  crates/api_models/src/user/dashboard_metadata.rs  0% smaller
  crates/common_types/src/primitive_wrappers.rs  0% smaller
  crates/common_utils/Cargo.toml Unsupported file format
  crates/common_utils/src/validation.rs  0% smaller

semanticdiff-com[bot] avatar Aug 29 '25 10:08 semanticdiff-com[bot]