This commit introduces a new audit report, AUDIT-INPUT-VALIDATION.md, which details the security audit of the project's input validation and sanitization. The report includes: - An inventory of input entry points. - An analysis of validation gaps. - A description of potential injection vectors. - Remediation recommendations with code examples. Co-authored-by: Snider <631881+Snider@users.noreply.github.com>
5.5 KiB
5.5 KiB
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 withid(string),coords(array of numbers), andvalue(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.goperform minimal validation. For example,pxComputePeerQualityScoreandpxComputeTrustScoreaccept numeric and string inputs from JS objects without proper sanitization. - DNS Tools: The
GetExternalToolLinksfunctions indns_tools.gouseurl.QueryEscapebut do not validate the input strings for correctness, potentially allowing malformed data to be passed to external services.
Injection Vectors Discovered
- URL Injection: The
GetExternalToolLinksfunctions could be vulnerable to URL injection if an attacker provides a maliciously crafted domain or IP address. For example, an input likeexample.com?some_param=some_valuecould 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
// 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
// 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
}