CVE-2017-0907: Server-Side Request Forgery (SSRF) (CWE-918)
value: The Recurly Client .NET Library before 1.0.1, 1.1.10, 1.2.8, 1.3.2, 1.4.14, 1.5.3, 1.6.2, 1.7.1, 1.8.1 is vulnerable to a Server-Side Request Forgery vulnerability due to incorrect use of "Uri.EscapeUriString" that could result in compromise of API keys or other critical resources.
CWE description: The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
CVSS v3 base score: 9.8
Published: 2017-11-13T17:29Z
Repository: https://github.com/recurly/recurly-client-net
Language: C#
Files changed: Library/Account.cs, Library/AccountBalance.cs, Library/AddOn.cs, Library/Adjustment.cs, Library/BillingInfo.cs, Library/Coupon.cs, Library/CouponRedemption.cs, Library/Export.cs, Library/GiftCard.cs, Library/Invoice.cs, Library/MeasuredUnit.cs, Library/Plan.cs, Library/Subscription.cs, Library/Transaction.cs
Commit date: 2017-11-08 14:35:49 -0800
Commit message: SSRF fix: replace EscapeUriString with EscapeDataString

Diff: diff --git a/Library/Account.cs b/Library/Account.cs
index dff7ba8..29b3c2d 100644
--- a/Library/Account.cs
+++ b/Library/Account.cs
@@ -143,11 +143,11 @@ namespace Recurly
         /// Delete an account's billing info.
         /// </summary>
         public void DeleteBillingInfo()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/billing_info");
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/billing_info");
             _billingInfo = null;
         }
 
         /// <summary>
         /// Create a new account in Recurly
@@ -163,11 +163,11 @@ namespace Recurly
         /// </summary>
         public void Update()
         {
             // PUT /accounts/<account code>
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(AccountCode),
+                UrlPrefix + Uri.EscapeDataString(AccountCode),
                 WriteXml);
         }
 
         /// <summary>
         /// Close the account and cancel any active subscriptions (if there is one).
@@ -197,11 +197,11 @@ namespace Recurly
         /// </summary>
         public Invoice InvoicePendingCharges(Invoice invoice = null)
         {
             var i = invoice ?? new Invoice();
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/invoices",
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/invoices",
                 i.WriteXml,
                 i.ReadXml);
 
             return i;
         }
@@ -211,11 +211,11 @@ namespace Recurly
         /// </summary>
         public Invoice PreviewInvoicePendingCharges(Invoice invoice = null)
         {
             var i = invoice ?? new Invoice();
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/invoices/preview",
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/invoices/preview",
                 i.WriteXml,
                 i.ReadXml);
 
             return i;
         }
@@ -229,11 +229,11 @@ namespace Recurly
         public RecurlyList<Adjustment> GetAdjustments(Adjustment.AdjustmentType type = Adjustment.AdjustmentType.All,
             Adjustment.AdjustmentState state = Adjustment.AdjustmentState.Any)
         {
             var adjustments = new AdjustmentList();
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/adjustments/"
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/adjustments/"
                 + Build.QueryStringWith(Adjustment.AdjustmentState.Any == state ? "" : "state=" + state.ToString().EnumNameToTransportCase())
                 .AndWith(Adjustment.AdjustmentType.All == type ? "" : "type=" + type.ToString().EnumNameToTransportCase())
                 , adjustments.ReadXmlList);
 
             return statusCode == HttpStatusCode.NotFound ? null : adjustments;
@@ -245,11 +245,11 @@ namespace Recurly
         /// <returns></returns>
         public RecurlyList<ShippingAddress> GetShippingAddresses()
         {
             var shippingAddresses = new ShippingAddressList(this);
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/shipping_addresses/",
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/shipping_addresses/",
                 shippingAddresses.ReadXmlList);
 
             return statusCode == HttpStatusCode.NotFound ? null : shippingAddresses;
         }
 
@@ -267,11 +267,11 @@ namespace Recurly
         /// </summary>
         /// <param name="state"></param>
         /// <returns></returns>
         public RecurlyList<Subscription> GetSubscriptions(Subscription.SubscriptionState state = Subscription.SubscriptionState.All)
         {
-            return new SubscriptionList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/subscriptions/"
+            return new SubscriptionList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/subscriptions/"
                 + Build.QueryStringWith(state.Equals(Subscription.SubscriptionState.All) ? "" : "state=" + state.ToString().EnumNameToTransportCase()));
         }
 
         /// <summary>
         /// Returns a list of transactions for this account, by transaction type
@@ -280,18 +280,18 @@ namespace Recurly
         /// <param name="type">Transactions of this type will be retrieved. Optional, default: All.</param>
         /// <returns></returns>
         public RecurlyList<Transaction> GetTransactions(TransactionList.TransactionState state = TransactionList.TransactionState.All,
             TransactionList.TransactionType type = TransactionList.TransactionType.All)
         {
-            return new TransactionList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/transactions/"
+            return new TransactionList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/transactions/"
                  + Build.QueryStringWith(state != TransactionList.TransactionState.All ? "state=" + state.ToString().EnumNameToTransportCase() : "")
                    .AndWith(type != TransactionList.TransactionType.All ? "type=" + type.ToString().EnumNameToTransportCase() : ""));
         }
 
         public RecurlyList<Note> GetNotes()
         {
-            return new NoteList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/notes/");
+            return new NoteList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/notes/");
         }
 
         /// <summary>
         /// Returns a new adjustment (credit or charge) for this account
         /// </summary>
@@ -326,11 +326,11 @@ namespace Recurly
         public RecurlyList<CouponRedemption> GetActiveRedemptions()
         {
             var redemptions = new CouponRedemptionList();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/redemptions",
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/redemptions",
                 redemptions.ReadXmlList);
 
             return statusCode == HttpStatusCode.NotFound ? null : redemptions;
         }
 
@@ -558,11 +558,11 @@ namespace Recurly
         public static Account Get(string accountCode)
         {
             var account = new Account();
             // GET /accounts/<account code>
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(accountCode),
+                UrlPrefix + Uri.EscapeDataString(accountCode),
                 account.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : account;
         }
 
@@ -573,22 +573,22 @@ namespace Recurly
         /// <param name="accountCode">Account Code</param>
         public static void Close(string accountCode)
         {
             // DELETE /accounts/<account code>
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                Account.UrlPrefix + Uri.EscapeUriString(accountCode));
+                Account.UrlPrefix + Uri.EscapeDataString(accountCode));
         }
 
         /// <summary>
         /// Reopen an existing account in recurly.
         /// </summary>
         /// <param name="accountCode">Account Code</param>
         public static void Reopen(string accountCode)
         {
             // PUT /accounts/<account code>/reopen
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                Account.UrlPrefix + Uri.EscapeUriString(accountCode) + "/reopen");
+                Account.UrlPrefix + Uri.EscapeDataString(accountCode) + "/reopen");
         }
 
         /// <summary>
         /// Lists accounts, limited to state
         /// </summary>
diff --git a/Library/AccountBalance.cs b/Library/AccountBalance.cs
index 90af82a..6102dbb 100644
--- a/Library/AccountBalance.cs
+++ b/Library/AccountBalance.cs
@@ -17,11 +17,11 @@ namespace Recurly
         public static AccountBalance Get(string accountCode)
         {
             var accountBalance = new AccountBalance();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(accountCode) + "/balance", accountBalance.ReadXml);
+                UrlPrefix + Uri.EscapeDataString(accountCode) + "/balance", accountBalance.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : accountBalance;
         }
 
         internal override void ReadXml(XmlTextReader reader)
diff --git a/Library/AddOn.cs b/Library/AddOn.cs
index cc70cd8..9b88f54 100644
--- a/Library/AddOn.cs
+++ b/Library/AddOn.cs
@@ -62,33 +62,33 @@ namespace Recurly
         /// Creates an addon
         /// </summary>
         public void Create()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix,
+                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix,
                 WriteXml,
                 ReadXml);
         }
 
         /// <summary>
         /// Update an existing add on in Recurly
         /// </summary>
         public void Update()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix + Uri.EscapeUriString(AddOnCode),
+                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix + Uri.EscapeDataString(AddOnCode),
                 WriteXml,
                 ReadXml);
         }
 
         /// <summary>
         /// Deletes this add on, making it inactive
         /// </summary>
         public void Delete()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix + Uri.EscapeUriString(AddOnCode));
+                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix + Uri.EscapeDataString(AddOnCode));
         }
 
 
         #region Read and Write XML documents
 
diff --git a/Library/Adjustment.cs b/Library/Adjustment.cs
index 8a0a436..4385d18 100644
--- a/Library/Adjustment.cs
+++ b/Library/Adjustment.cs
@@ -113,11 +113,11 @@ namespace Recurly
         /// </summary>
         public void Create()
         {
             // POST /accounts/<account code>/adjustments
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                UrlPrefix + Uri.EscapeUriString(AccountCode) + UrlPostfix,
+                UrlPrefix + Uri.EscapeDataString(AccountCode) + UrlPostfix,
                 WriteXml,
                 ReadXml);
         }
 
         /// <summary>
@@ -127,11 +127,11 @@ namespace Recurly
         /// </summary>
         public void Delete()
         {
             // DELETE /adjustments/<uuid>
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPostfix + Uri.EscapeUriString(Uuid));
+                UrlPostfix + Uri.EscapeDataString(Uuid));
         }
 
 
         #region Read and Write XML documents
 
@@ -282,11 +282,11 @@ namespace Recurly
     {
         public static Adjustment Get(string uuid)
         {
             var adjustment = new Adjustment();
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                "/adjustments/" + Uri.EscapeUriString(uuid),
+                "/adjustments/" + Uri.EscapeDataString(uuid),
                 adjustment.ReadXml);
             return adjustment;
         }
     }
 }
diff --git a/Library/BillingInfo.cs b/Library/BillingInfo.cs
index 5953550..e3a3a6d 100644
--- a/Library/BillingInfo.cs
+++ b/Library/BillingInfo.cs
@@ -184,11 +184,11 @@ namespace Recurly
                 ReadXml);
         }
 
         private static string BillingInfoUrl(string accountCode)
         {
-            return UrlPrefix + Uri.EscapeUriString(accountCode) + UrlPostfix;
+            return UrlPrefix + Uri.EscapeDataString(accountCode) + UrlPostfix;
         }
 
         internal override void ReadXml(XmlTextReader reader)
         {
             while (reader.Read())
diff --git a/Library/Coupon.cs b/Library/Coupon.cs
index a444eca..200965f 100644
--- a/Library/Coupon.cs
+++ b/Library/Coupon.cs
@@ -173,28 +173,28 @@ namespace Recurly
         }
 
         public void Update()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(CouponCode),
+                UrlPrefix + Uri.EscapeDataString(CouponCode),
                 WriteXmlUpdate);
         }
 
         public void Restore()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(CouponCode) + "/restore",
+                UrlPrefix + Uri.EscapeDataString(CouponCode) + "/restore",
                 WriteXmlUpdate);
         }
 
         /// <summary>
         /// Deactivates this coupon.
         /// </summary>
         public void Deactivate()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPrefix + Uri.EscapeUriString(CouponCode));
+                UrlPrefix + Uri.EscapeDataString(CouponCode));
         }
 
         public RecurlyList<Coupon> GetUniqueCouponCodes()
         {
             var coupons = new CouponList();
@@ -533,11 +533,11 @@ namespace Recurly
         public static Coupon Get(string couponCode)
         {
             var coupon = new Coupon();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                Coupon.UrlPrefix + Uri.EscapeUriString(couponCode),
+                Coupon.UrlPrefix + Uri.EscapeDataString(couponCode),
                 coupon.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : coupon;
         }
 
diff --git a/Library/CouponRedemption.cs b/Library/CouponRedemption.cs
index 757461f..ce81349 100644
--- a/Library/CouponRedemption.cs
+++ b/Library/CouponRedemption.cs
@@ -44,11 +44,11 @@ namespace Recurly
         internal static CouponRedemption Redeem(string accountCode, string couponCode, string currency, string subscriptionUuid=null)
         {
             var cr = new CouponRedemption {AccountCode = accountCode, Currency = currency, SubscriptionUuid = subscriptionUuid};
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-               "/coupons/" + Uri.EscapeUriString(couponCode) + "/redeem",
+               "/coupons/" + Uri.EscapeDataString(couponCode) + "/redeem",
                cr.WriteXml,
                cr.ReadXml);
 
             return cr;
 
@@ -58,12 +58,12 @@ namespace Recurly
         /// Removes a coupon from an account
         /// </summary>
         public void Delete()
         {
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                "/accounts/" + Uri.EscapeUriString(AccountCode) +
-                "/redemptions/" + Uri.EscapeUriString(Uuid));
+                "/accounts/" + Uri.EscapeDataString(AccountCode) +
+                "/redemptions/" + Uri.EscapeDataString(Uuid));
             AccountCode = null;
             CouponCode = null;
             Currency = null;
         }
 
diff --git a/Library/Export.cs b/Library/Export.cs
index 00244ea..14c7808 100644
--- a/Library/Export.cs
+++ b/Library/Export.cs
@@ -109,11 +109,11 @@ namespace Recurly
 
         public static ExportFile DownloadExportFile(DateTime date, string fileName)
         {
             var exportFile = new ExportFile();
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                string.Format(ExportFile.FileUrlPrefix, date.ToString("yyyy-MM-dd"), Uri.EscapeUriString(fileName)),
+                string.Format(ExportFile.FileUrlPrefix, date.ToString("yyyy-MM-dd"), Uri.EscapeDataString(fileName)),
                 exportFile.ReadXml);
 
             return statusCode != HttpStatusCode.NotFound ? exportFile : null;
         }
     }
diff --git a/Library/GiftCard.cs b/Library/GiftCard.cs
index e79a993..32d14b9 100644
--- a/Library/GiftCard.cs
+++ b/Library/GiftCard.cs
@@ -322,11 +322,11 @@ namespace Recurly
         public static GiftCard Get(long id)
         {
             var giftCard = new GiftCard();
             // GET /gift_cards/<id>
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(id.ToString()),
+                UrlPrefix + Uri.EscapeDataString(id.ToString()),
                 giftCard.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : giftCard;
         }
 
diff --git a/Library/Invoice.cs b/Library/Invoice.cs
index 180aad7..c16e659 100644
--- a/Library/Invoice.cs
+++ b/Library/Invoice.cs
@@ -119,22 +119,22 @@ namespace Recurly
         /// Post an invoice on an account using it's pending charges
         /// </summary>
         public void Create(string accountCode)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix,
+                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix,
                 WriteXml,
                 ReadXml);
         }
 
         /// <summary>
         /// Preview an invoice on an account using it's pending charges
         /// </summary>
         public void Preview(string accountCode)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix + "preview",
+                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix + "preview",
                 WriteXml,
                 ReadXml);
         }
 
         /// <summary>
@@ -451,11 +451,11 @@ namespace Recurly
 
     public sealed class Invoices
     {
         public static RecurlyList<Invoice> List(string accountCode)
         {
-            return new InvoiceList("/accounts/" + Uri.EscapeUriString(accountCode) + "/invoices");
+            return new InvoiceList("/accounts/" + Uri.EscapeDataString(accountCode) + "/invoices");
         }
 
         public static RecurlyList<Invoice> List()
         {
             return new InvoiceList(Invoice.UrlPrefix);
@@ -502,11 +502,11 @@ namespace Recurly
         public static Invoice Create(string accountCode)
         {
             var invoice = new Invoice();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix,
+                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix,
                 invoice.ReadXml);
 
             return (int)statusCode == ValidationException.HttpStatusCode ? null : invoice;
         }
     }
diff --git a/Library/MeasuredUnit.cs b/Library/MeasuredUnit.cs
index 42007be..c6417cc 100644
--- a/Library/MeasuredUnit.cs
+++ b/Library/MeasuredUnit.cs
@@ -54,21 +54,21 @@ namespace Recurly
         /// Update an existing measured unit in Recurly
         /// </summary>
         public void Update()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Id.ToString()),
+                UrlPrefix + Uri.EscapeDataString(Id.ToString()),
                 WriteXml);
         }
 
         /// <summary>
         /// Deletes this measured unit
         /// </summary>
         public void Delete()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPrefix + Uri.EscapeUriString(Id.ToString()));
+                UrlPrefix + Uri.EscapeDataString(Id.ToString()));
         }
 
         #region Read and Write XML documents
 
         internal override void ReadXml(XmlTextReader reader)
diff --git a/Library/Plan.cs b/Library/Plan.cs
index 64703c1..106f5d1 100644
--- a/Library/Plan.cs
+++ b/Library/Plan.cs
@@ -56,11 +56,11 @@ namespace Recurly
         {
             get
             {
                 if (_addOns == null)
                 {
-                    var url = UrlPrefix + Uri.EscapeUriString(PlanCode) + "/add_ons/";
+                    var url = UrlPrefix + Uri.EscapeDataString(PlanCode) + "/add_ons/";
                     _addOns = new AddOnList(url);
                 }
                 return _addOns;
             }
         }
@@ -118,20 +118,20 @@ namespace Recurly
         /// Update an existing plan in Recurly
         /// </summary>
         public void Update()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(PlanCode),
+                UrlPrefix + Uri.EscapeDataString(PlanCode),
                 WriteXml);
         }
 
         /// <summary>
         /// Deletes this plan, making it inactive
         /// </summary>
         public void Deactivate()
         {
-            Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete, UrlPrefix + Uri.EscapeUriString(PlanCode));
+            Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete, UrlPrefix + Uri.EscapeDataString(PlanCode));
         }
 
         /// <summary>
         /// Returns an new add on associated with this plan.
         /// </summary>
@@ -147,11 +147,11 @@ namespace Recurly
         public AddOn GetAddOn(string addOnCode)
         {
             var addOn = new AddOn();
 
             var status = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(PlanCode) + "/add_ons/" + Uri.EscapeUriString(addOnCode),
+                UrlPrefix + Uri.EscapeDataString(PlanCode) + "/add_ons/" + Uri.EscapeDataString(addOnCode),
                 addOn.ReadXml);
 
             if (status != HttpStatusCode.OK) return null;
 
             // PlanCode is needed to update the AddOn
@@ -443,11 +443,11 @@ namespace Recurly
         public static Plan Get(string planCode)
         {
             var plan = new Plan();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                Plan.UrlPrefix + Uri.EscapeUriString(planCode),
+                Plan.UrlPrefix + Uri.EscapeDataString(planCode),
                 plan.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : plan;
         }
     }
diff --git a/Library/Subscription.cs b/Library/Subscription.cs
index 5f666ad..1e2a01f 100644
--- a/Library/Subscription.cs
+++ b/Library/Subscription.cs
@@ -370,11 +370,11 @@ namespace Recurly
                 writeXmlDelegate = WriteChangeSubscriptionAtRenewalXml;
             else
                 writeXmlDelegate = WriteChangeSubscriptionNowXml;
 
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid),
+                UrlPrefix + Uri.EscapeDataString(Uuid),
                 writeXmlDelegate,
                 ReadXml);
         }
 
         public void ChangeSubscription()
@@ -387,32 +387,32 @@ namespace Recurly
         /// through the remainder of the current term.
         /// </summary>
         public void Cancel()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/cancel",
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/cancel",
                 ReadXml);
         }
 
         /// <summary>
         /// Reactivate a canceled subscription.  The subscription will renew at the end of its current term.
         /// </summary>
         public void Reactivate()
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/reactivate",
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/reactivate",
                 ReadXml);
         }
 
         /// <summary>
         /// Terminates the subscription immediately.
         /// </summary>
         /// <param name="refund"></param>
         public void Terminate(RefundType refund)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/terminate?refund=" + refund.ToString().EnumNameToTransportCase(),
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/terminate?refund=" + refund.ToString().EnumNameToTransportCase(),
                 ReadXml);
         }
 
         /// <summary>
         /// Transforms this object into a preview Subscription applied to the account.
@@ -458,11 +458,11 @@ namespace Recurly
                 writeXmlDelegate = WriteChangeSubscriptionNowXml;
 
             var previewSubscription = new Subscription();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Post,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/preview",
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/preview",
                 writeXmlDelegate,
                 previewSubscription.ReadPreviewXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : previewSubscription;
         }
@@ -478,18 +478,18 @@ namespace Recurly
         /// <param name="nextRenewalDate">The specified time the subscription will be postponed</param>
         /// <param name="bulk">bulk = false (default) or true to bypass the 60 second wait while postponing</param>
         public void Postpone(DateTime nextRenewalDate, bool bulk = false)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/postpone?next_renewal_date=" + nextRenewalDate.ToString("s") + "&bulk=" + bulk.ToString().ToLower(),
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/postpone?next_renewal_date=" + nextRenewalDate.ToString("s") + "&bulk=" + bulk.ToString().ToLower(),
                 ReadXml);
         }
 
         public bool UpdateNotes(Dictionary<string, string> notes)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Put,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/notes",
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/notes",
                 WriteSubscriptionNotesXml(notes),
                 ReadXml);
 
             CustomerNotes = notes["CustomerNotes"];
             TermsAndConditions = notes["TermsAndConditions"];
@@ -500,11 +500,11 @@ namespace Recurly
 
         public RecurlyList<CouponRedemption> GetRedemptions()
         {
             var coupons = new CouponRedemptionList();
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + "/redemptions/",
+                UrlPrefix + Uri.EscapeDataString(Uuid) + "/redemptions/",
                 coupons.ReadXmlList);
 
             return statusCode == HttpStatusCode.NotFound ? null : coupons;
         }
 
@@ -966,11 +966,11 @@ namespace Recurly
 
         public static Subscription Get(string uuid)
         {
             var s = new Subscription();
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                Subscription.UrlPrefix + Uri.EscapeUriString(uuid),
+                Subscription.UrlPrefix + Uri.EscapeDataString(uuid),
                 s.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : s;
         }
     }
diff --git a/Library/Transaction.cs b/Library/Transaction.cs
index e662691..1e3a86a 100644
--- a/Library/Transaction.cs
+++ b/Library/Transaction.cs
@@ -144,11 +144,11 @@ namespace Recurly
         /// </summary>
         /// <param name="refund">If present, the amount to refund. Otherwise it is a full refund.</param>
         public void Refund(int? refund = null)
         {
             Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete,
-                UrlPrefix + Uri.EscapeUriString(Uuid) + (refund.HasValue ? "?amount_in_cents=" + refund.Value : ""),
+                UrlPrefix + Uri.EscapeDataString(Uuid) + (refund.HasValue ? "?amount_in_cents=" + refund.Value : ""),
                 ReadXml);
         }
 
         public Invoice GetInvoice()
         {
@@ -397,11 +397,11 @@ namespace Recurly
         public static Transaction Get(string transactionId)
         {
             var transaction = new Transaction();
 
             var statusCode = Client.Instance.PerformRequest(Client.HttpRequestMethod.Get,
-                Transaction.UrlPrefix + Uri.EscapeUriString(transactionId),
+                Transaction.UrlPrefix + Uri.EscapeDataString(transactionId),
                 transaction.ReadXml);
 
             return statusCode == HttpStatusCode.NotFound ? null : transaction;
         }
     }

Vulnerable code:                 UrlPrefix + Uri.EscapeUriString(AccountCode) + "/billing_info");
                UrlPrefix + Uri.EscapeUriString(AccountCode),
                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/invoices",
                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/invoices/preview",
                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/adjustments/"
                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/shipping_addresses/",
            return new SubscriptionList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/subscriptions/"
            return new TransactionList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/transactions/"
            return new NoteList(UrlPrefix + Uri.EscapeUriString(AccountCode) + "/notes/");
                UrlPrefix + Uri.EscapeUriString(AccountCode) + "/redemptions",
                UrlPrefix + Uri.EscapeUriString(accountCode),
                Account.UrlPrefix + Uri.EscapeUriString(accountCode));
                Account.UrlPrefix + Uri.EscapeUriString(accountCode) + "/reopen");
                UrlPrefix + Uri.EscapeUriString(accountCode) + "/balance", accountBalance.ReadXml);
                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix,
                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix + Uri.EscapeUriString(AddOnCode),
                UrlPrefix + Uri.EscapeUriString(PlanCode) + UrlPostfix + Uri.EscapeUriString(AddOnCode));
                UrlPrefix + Uri.EscapeUriString(AccountCode) + UrlPostfix,
                UrlPostfix + Uri.EscapeUriString(Uuid));
                "/adjustments/" + Uri.EscapeUriString(uuid),
            return UrlPrefix + Uri.EscapeUriString(accountCode) + UrlPostfix;
                UrlPrefix + Uri.EscapeUriString(CouponCode),
                UrlPrefix + Uri.EscapeUriString(CouponCode) + "/restore",
                UrlPrefix + Uri.EscapeUriString(CouponCode));
                Coupon.UrlPrefix + Uri.EscapeUriString(couponCode),
               "/coupons/" + Uri.EscapeUriString(couponCode) + "/redeem",
                "/accounts/" + Uri.EscapeUriString(AccountCode) +
                "/redemptions/" + Uri.EscapeUriString(Uuid));
                string.Format(ExportFile.FileUrlPrefix, date.ToString("yyyy-MM-dd"), Uri.EscapeUriString(fileName)),
                UrlPrefix + Uri.EscapeUriString(id.ToString()),
                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix,
                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix + "preview",
            return new InvoiceList("/accounts/" + Uri.EscapeUriString(accountCode) + "/invoices");
                "/accounts/" + Uri.EscapeUriString(accountCode) + Invoice.UrlPrefix,
                UrlPrefix + Uri.EscapeUriString(Id.ToString()),
                UrlPrefix + Uri.EscapeUriString(Id.ToString()));
                    var url = UrlPrefix + Uri.EscapeUriString(PlanCode) + "/add_ons/";
                UrlPrefix + Uri.EscapeUriString(PlanCode),
            Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete, UrlPrefix + Uri.EscapeUriString(PlanCode));
                UrlPrefix + Uri.EscapeUriString(PlanCode) + "/add_ons/" + Uri.EscapeUriString(addOnCode),
                Plan.UrlPrefix + Uri.EscapeUriString(planCode),
                UrlPrefix + Uri.EscapeUriString(Uuid),
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/cancel",
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/reactivate",
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/terminate?refund=" + refund.ToString().EnumNameToTransportCase(),
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/preview",
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/postpone?next_renewal_date=" + nextRenewalDate.ToString("s") + "&bulk=" + bulk.ToString().ToLower(),
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/notes",
                UrlPrefix + Uri.EscapeUriString(Uuid) + "/redemptions/",
                Subscription.UrlPrefix + Uri.EscapeUriString(uuid),
                UrlPrefix + Uri.EscapeUriString(Uuid) + (refund.HasValue ? "?amount_in_cents=" + refund.Value : ""),
                Transaction.UrlPrefix + Uri.EscapeUriString(transactionId),
Fixed code:                 UrlPrefix + Uri.EscapeDataString(AccountCode) + "/billing_info");
                UrlPrefix + Uri.EscapeDataString(AccountCode),
                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/invoices",
                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/invoices/preview",
                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/adjustments/"
                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/shipping_addresses/",
            return new SubscriptionList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/subscriptions/"
            return new TransactionList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/transactions/"
            return new NoteList(UrlPrefix + Uri.EscapeDataString(AccountCode) + "/notes/");
                UrlPrefix + Uri.EscapeDataString(AccountCode) + "/redemptions",
                UrlPrefix + Uri.EscapeDataString(accountCode),
                Account.UrlPrefix + Uri.EscapeDataString(accountCode));
                Account.UrlPrefix + Uri.EscapeDataString(accountCode) + "/reopen");
                UrlPrefix + Uri.EscapeDataString(accountCode) + "/balance", accountBalance.ReadXml);
                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix,
                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix + Uri.EscapeDataString(AddOnCode),
                UrlPrefix + Uri.EscapeDataString(PlanCode) + UrlPostfix + Uri.EscapeDataString(AddOnCode));
                UrlPrefix + Uri.EscapeDataString(AccountCode) + UrlPostfix,
                UrlPostfix + Uri.EscapeDataString(Uuid));
                "/adjustments/" + Uri.EscapeDataString(uuid),
            return UrlPrefix + Uri.EscapeDataString(accountCode) + UrlPostfix;
                UrlPrefix + Uri.EscapeDataString(CouponCode),
                UrlPrefix + Uri.EscapeDataString(CouponCode) + "/restore",
                UrlPrefix + Uri.EscapeDataString(CouponCode));
                Coupon.UrlPrefix + Uri.EscapeDataString(couponCode),
               "/coupons/" + Uri.EscapeDataString(couponCode) + "/redeem",
                "/accounts/" + Uri.EscapeDataString(AccountCode) +
                "/redemptions/" + Uri.EscapeDataString(Uuid));
                string.Format(ExportFile.FileUrlPrefix, date.ToString("yyyy-MM-dd"), Uri.EscapeDataString(fileName)),
                UrlPrefix + Uri.EscapeDataString(id.ToString()),
                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix,
                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix + "preview",
            return new InvoiceList("/accounts/" + Uri.EscapeDataString(accountCode) + "/invoices");
                "/accounts/" + Uri.EscapeDataString(accountCode) + Invoice.UrlPrefix,
                UrlPrefix + Uri.EscapeDataString(Id.ToString()),
                UrlPrefix + Uri.EscapeDataString(Id.ToString()));
                    var url = UrlPrefix + Uri.EscapeDataString(PlanCode) + "/add_ons/";
                UrlPrefix + Uri.EscapeDataString(PlanCode),
            Client.Instance.PerformRequest(Client.HttpRequestMethod.Delete, UrlPrefix + Uri.EscapeDataString(PlanCode));
                UrlPrefix + Uri.EscapeDataString(PlanCode) + "/add_ons/" + Uri.EscapeDataString(addOnCode),
                Plan.UrlPrefix + Uri.EscapeDataString(planCode),
                UrlPrefix + Uri.EscapeDataString(Uuid),
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/cancel",
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/reactivate",
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/terminate?refund=" + refund.ToString().EnumNameToTransportCase(),
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/preview",
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/postpone?next_renewal_date=" + nextRenewalDate.ToString("s") + "&bulk=" + bulk.ToString().ToLower(),
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/notes",
                UrlPrefix + Uri.EscapeDataString(Uuid) + "/redemptions/",
                Subscription.UrlPrefix + Uri.EscapeDataString(uuid),
                UrlPrefix + Uri.EscapeDataString(Uuid) + (refund.HasValue ? "?amount_in_cents=" + refund.Value : ""),
                Transaction.UrlPrefix + Uri.EscapeDataString(transactionId),