Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions AUDIT-INPUT-VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Input Validation and Sanitization Audit

## Input Entry Points Inventory

This section inventories all the points where untrusted input enters the system.

### Go API (`poindexter.go`)

- **`Hello(name string)`**: Accepts a string input, which is used in a greeting message.

### WebAssembly Interface (`wasm/main.go`)

The following functions are exposed to JavaScript and represent the primary attack surface from a web environment:

- **`pxHello(name string)`**: Accepts a string from JS.
- **`pxNewTree(dim int)`**: Accepts an integer dimension.
- **`pxInsert(treeId int, point js.Value)`**: Accepts a JS object with `id` (string), `coords` (array of numbers), and `value` (string).
- **`pxDeleteByID(treeId int, id string)`**: Accepts a string point ID.
- **`pxNearest(treeId int, query []float64)`**: Accepts an array of numbers.
- **`pxKNearest(treeId int, query []float64, k int)`**: Accepts an array of numbers and an integer.
- **`pxRadius(treeId int, query []float64, r float64)`**: Accepts an array of numbers and a float.
- **`pxComputePeerQualityScore(metrics js.Value, weights js.Value)`**: Accepts JS objects for metrics and weights, containing various numeric and string fields.
- **`pxComputeTrustScore(metrics js.Value)`**: Accepts a JS object for trust metrics, containing various numeric and string fields.
- **`pxGetExternalToolLinks(domain string)`**: Accepts a domain string.
- **`pxGetExternalToolLinksIP(ip string)`**: Accepts an IP address string.
- **`pxGetExternalToolLinksEmail(emailOrDomain string)`**: Accepts an email or domain string.
- **`pxBuildRDAPDomainURL(domain string)`**: Accepts a domain string.
- **`pxBuildRDAPIPURL(ip string)`**: Accepts an IP address string.
- **`pxBuildRDAPASNURL(asn string)`**: Accepts an ASN string.

### DNS Tools (`dns_tools.go`)

These functions are called internally but are also exposed via the WASM interface. They interact with external DNS resolvers and RDAP servers.

- **`DNSLookup(domain string, recordType DNSRecordType)`**: Accepts a domain string.
- **`RDAPLookupDomain(domain string)`**: Accepts a domain string.
- **`RDAPLookupIP(ip string)`**: Accepts an IP address string.
- **`RDAPLookupASN(asn string)`**: Accepts an ASN string.
- **`GetExternalToolLinks(domain string)`**: Accepts a domain string.
- **`GetExternalToolLinksIP(ip string)`**: Accepts an IP address string.
- **`GetExternalToolLinksEmail(emailOrDomain string)`**: Accepts an email or domain string.

## Validation Gaps Found

- **WASM Interface**: The functions exposed to JavaScript in `wasm/main.go` perform minimal validation. For example, `pxComputePeerQualityScore` and `pxComputeTrustScore` accept numeric and string inputs from JS objects without proper sanitization.
- **DNS Tools**: The `GetExternalToolLinks` functions in `dns_tools.go` use `url.QueryEscape` but do not validate the input strings for correctness, potentially allowing malformed data to be passed to external services.

## Injection Vectors Discovered

- **URL Injection**: The `GetExternalToolLinks` functions could be vulnerable to URL injection if an attacker provides a maliciously crafted domain or IP address. For example, an input like `example.com?some_param=some_value` could alter the behavior of the external service being linked to.

## Remediation Recommendations

To address the identified vulnerabilities, the following remediation actions are recommended:

### 1. Sanitize Inputs in WASM Interface

All inputs from JavaScript should be treated as untrusted and validated before use.

**Example: `pxComputePeerQualityScore`**

```go
// wasm/main.go

import (
"errors"
"regexp"
)

var (
// Basic validation for domain names and IPs
domainRegex = regexp.MustCompile(`^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$`)
ipRegex = regexp.MustCompile(`^(\d{1,3}\.){3}\d{1,3}$`)
)

func computePeerQualityScore(_ js.Value, args []js.Value) (any, error) {
if len(args) < 1 {
return nil, errors.New("computePeerQualityScore(metrics)")
}
m := args[0]
metrics := pd.NATRoutingMetrics{
ConnectivityScore: m.Get("connectivityScore").Float(),
SymmetryScore: m.Get("symmetryScore").Float(),
RelayProbability: m.Get("relayProbability").Float(),
DirectSuccessRate: m.Get("directSuccessRate").Float(),
AvgRTTMs: m.Get("avgRttMs").Float(),
JitterMs: m.Get("jitterMs").Float(),
PacketLossRate: m.Get("packetLossRate").Float(),
BandwidthMbps: m.Get("bandwidthMbps").Float(),
NATType: m.Get("natType").String(),
}

// Add validation for NATType
if !isValidNATType(metrics.NATType) {
return nil, errors.New("invalid NATType")
}

// ... rest of the function
}

func isValidNATType(natType string) bool {
// Implement validation logic for NATType
return natType == "static" || natType == "dynamic"
}
```

### 2. Validate and Sanitize DNS Tool Inputs

Before creating external links, validate that the input is a valid domain, IP, or email.

**Example: `GetExternalToolLinks`**

```go
// dns_tools.go

import (
"net"
"net/url"
"regexp"
)

var (
domainRegex = regexp.MustCompile(`^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$`)
)

func GetExternalToolLinks(domain string) ExternalToolLinks {
if !domainRegex.MatchString(domain) {
// Return empty links or an error
return ExternalToolLinks{Target: domain, Type: "domain"}
}
encoded := url.QueryEscape(domain)
// ... rest of the function
}

func GetExternalToolLinksIP(ip string) ExternalToolLinks {
if net.ParseIP(ip) == nil {
return ExternalToolLinks{Target: ip, Type: "ip"}
}
encoded := url.QueryEscape(ip)
// ... rest of the function
}
```
Loading