View Issue Details

IDProjectCategoryView StatusLast Update
0012122Talerwallet (iOS App)public2026-11-11 21:04
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0012122: Add payment service: text that is not an address ("GLS Bank") is answered with "Internal core error" and raw JSON -- the alert validates nothing and Add is always enabled
DescriptionSettings -> Payment Services -> "+" opens an alert titled "Add payment
service" with one text field ("Enter the URL"). Whatever is typed there is
handed to wallet-core unchanged, and anything wallet-core cannot read as an
address comes back to the user as the generic error sheet titled "Internal
core error", with wallet-core's JSON as the body (screenshot attached).

Two ordinary mistakes, two different codes, the same sheet:

  * typing a name, "GLS Bank":

        { "code" : 7048,
          "detail" : "URL contains characters that are not allowed in a URL" }

  * the fuzzer's own input, an e-mail address run together with a host
    name ("...@tripwire.taler.netBytripwire.taler.nettaler.net"):

        { "code" : 7035,
          "hint" : "expected a taler://add-exchange/ URI", ... }

Nothing internal went wrong; the user mistyped. The alert's Add button
carries no .disabled() at all, so by the code it is enabled for an empty
field too (not tried).

Steps to reproduce (iOS simulator, iPhone 17, fresh install, developer mode
on, demo cash withdrawn; no fault injection):

  1. Settings -> Payment Services -> "+"
  2. type "GLS Bank"
  3. Add

Result: "Internal core error" + JSON + "Copy" + "OK".
Expected: the Add button stays disabled until the text can be an address
(or the error says the address is not valid, in words).

Cause
-----

TalerWallet1/Views/Settings/Exchange/ExchangeListView.swift:

    Button(addButtonStr) {
        addExchange(newExchange, model: model)
        ...

and the file-level addExchange() calls model.addExchange(uri:) with
viewHandles left false, so every WalletBackendError goes to the global error
sheet. There is no check between the text field and the request.
(BankListView.swift:28 has a second addExchange() with the same shape.)

Proposed patch
--------------

Below.
It adds exchangeAddress(_:) -- trims, rejects whitespace, accepts taler://
URIs, a bare host or an http(s) URL without user part -- and disables Add
until it returns something. NOT compiled or run on a device yet.

    diff --git a/TalerWallet1/Views/Settings/Exchange/ExchangeListView.swift b/TalerWallet1/Views/Settings/Exchange/ExchangeListView.swift
    index 2017f245..fe42ecc6 100644
    --- a/TalerWallet1/Views/Settings/Exchange/ExchangeListView.swift
    +++ b/TalerWallet1/Views/Settings/Exchange/ExchangeListView.swift
    @@ -9,6 +9,24 @@ import SwiftUI
     import taler_swift
     import SymLog
     
    +/// What the user typed into the "Add payment service" alert, if it can be an
    +/// address at all. wallet-core answers anything else with 7048 ("URL contains
    +/// characters that are not allowed") or 7035 ("expected a taler://add-exchange/
    +/// URI"), which reached the user as "Internal core error" with the raw JSON.
    +fileprivate
    +func exchangeAddress(_ typed: String) -> String? {
    + let text = typed.trimmingCharacters(in: .whitespacesAndNewlines)
    + if text.isEmpty || text.contains(where: { $0.isWhitespace }) { return nil }
    + if text.lowercased().hasPrefix("taler") && text.contains("://") { return text }
    + let withScheme = text.contains("://") ? text : "https://" + text
    + guard let components = URLComponents(string: withScheme),
    + let scheme = components.scheme?.lowercased(), scheme == "https" || scheme == "http",
    + let host = components.host, !host.isEmpty,
    + components.user == nil
    + else { return nil }
    + return text
    +}
    +
     @MainActor
     fileprivate
     func addExchange(_ exchange: String, model: WalletModel) -> Void {
    @@ -88,11 +106,14 @@ struct ExchangeListView: View {
                             .accessibilityLabel(enterURL)
     // .textFieldStyle(.roundedBorder) Yikes: when adding style the alert will stop showing the textfield! Don't do this.
                         Button(addButtonStr) {
    - addExchange(newExchange, model: model)
    - DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    - checkExchanges()
    + if let address = exchangeAddress(newExchange) {
    + addExchange(address, model: model)
    + DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    + checkExchanges()
    + }
                             }
                         }
    + .disabled(exchangeAddress(newExchange) == nil)
                         Button("Cancel", role: .cancel) { }
                     } message: {
                         Text(enterURL)
    @@ -104,7 +125,9 @@ struct ExchangeListView: View {
                                           title: addTitleStr,
                                        doneText: addButtonStr,
                                            text: $newExchange) { text in
    - addExchange(text, model: model)
    + if let address = exchangeAddress(text) {
    + addExchange(address, model: model)
    + }
                     }
             }
         }

How it was found
----------------

UI fuzzing campaign c2h-23, episode 14 (the walk typed a contact alias into
the field). Reduced to the deterministic harness scenario
scenarios/candidate/exchange-add-not-a-url.json, which is green (UI
assertions plus the "addExchange with error ... not allowed in a URL" line in
the app's os_log) on wallet build df63756f.

Same family as 12064 (Add bank account, X-TALER-BANK).
TagsNo tags attached.
Attached Files

Required notifications

Address or linkRemarkAdded byNotifiedActions

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-11 21:04bot-cgNew Issue
2026-11-11 21:04bot-cgFile Added: add-payment-service-internal-core-error.png