[GH-ISSUE #215] Work with not trusted HTTPS certificates #169

Closed
opened 2026-05-07 00:20:58 +02:00 by BreizhHardware · 27 comments

Originally created by @MuratovAS on GitHub (Apr 17, 2022).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/215

Good afternoon
Small observations regarding the application.

I use my own server for NTFY. I have no opportunity and desire to make the application public. I prefer even to use HTTPS on the local network.
As part of its network, all services I issue domains and certificates.

In such a scenario there are some difficulties, Android security policy on my phone does not allow working with impervious CA. Your application is no exception.

This problem can be bypass using the corresponding Magisk module. After adding your own CA in the certificate store. But this method is possible only on root devices.
https://github.com/NVISOsecurity/MagiskTrustUserCerts

For example, in the DAVX5-OSE application, this problem is solved elegant. When the connection is first, the application gives a dialog box that allows you to trust / do not trust this HTTPS certificate.
https://github.com/bitfireAT/davx5-ose

Dear developers, I propose to write about it in Wiki or within the application, implement a mechanism for permission to work with not trusted certificates.

P.S. Let's leave it here who can come in handy)

Originally created by @MuratovAS on GitHub (Apr 17, 2022). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/215 Good afternoon Small observations regarding the application. I use my own server for NTFY. I have no opportunity and desire to make the application public. I prefer even to use HTTPS on the local network. As part of its network, all services I issue domains and certificates. In such a scenario there are some difficulties, Android security policy on my phone does not allow working with impervious CA. Your application is no exception. This problem can be bypass using the corresponding Magisk module. After adding your own CA in the certificate store. But this method is possible only on root devices. https://github.com/NVISOsecurity/MagiskTrustUserCerts For example, in the DAVX5-OSE application, this problem is solved elegant. When the connection is first, the application gives a dialog box that allows you to trust / do not trust this HTTPS certificate. https://github.com/bitfireAT/davx5-ose Dear developers, I propose to write about it in Wiki or within the application, implement a mechanism for permission to work with not trusted certificates. P.S. Let's leave it here who can come in handy)
Author
Owner

@dcousens commented on GitHub (May 7, 2022):

Preferably, you should be able to provide a custom CA certificate to the application itself, preventing it from accepting connections to anything else.

The equivalent of --cacert for curl.

I don't mind something like a --known_hosts option; presuming the information shown is verifiable to the end user.
For example, it could show the sha256 fingerprint of the certificate.

<!-- gh-comment-id:1120207692 --> @dcousens commented on GitHub (May 7, 2022): Preferably, you should be able to provide a custom CA certificate to the application itself, preventing it from accepting connections to anything else. The equivalent of `--cacert` for `curl`. I don't mind something like a `--known_hosts` option; presuming the information shown is verifiable to the end user. For example, it could show the sha256 fingerprint of the certificate.
Author
Owner

@Kenix3 commented on GitHub (May 12, 2022):

This would be a great feature! At the very least a setting like curl -k to skip the verification step.

<!-- gh-comment-id:1125397712 --> @Kenix3 commented on GitHub (May 12, 2022): This would be a great feature! At the very least a setting like `curl -k` to skip the verification step.
Author
Owner

@binwiederhier commented on GitHub (May 27, 2022):

So, I am a little bit torn on this one. With Let's Encrypt certs being freely available and the DNS challenge making it possible to issue certs for internal servers, why would I go through the trouble of supporting custom certs. Because if I do that, I have to support ways to manage these certs to (create/update/delete), which is a whole new set of UIs.

Right now I don't see any reason to implement this, because it can be solved differently. I'll leave it open for comment.

<!-- gh-comment-id:1139564299 --> @binwiederhier commented on GitHub (May 27, 2022): So, I am a little bit torn on this one. With Let's Encrypt certs being freely available and the DNS challenge making it possible to issue certs for internal servers, why would I go through the trouble of supporting custom certs. Because if I do that, I have to support ways to manage these certs to (create/update/delete), which is a whole new set of UIs. Right now I don't see any reason to implement this, because it can be solved differently. I'll leave it open for comment.
Author
Owner

@MuratovAS commented on GitHub (May 27, 2022):

I think for starters you just need to add a checkmark "Use untrusted certificates". That is, let the program not check the authenticity of the certificate. Without any authentication.

<!-- gh-comment-id:1139593541 --> @MuratovAS commented on GitHub (May 27, 2022): I think for starters you just need to add a checkmark "Use untrusted certificates". That is, let the program not check the authenticity of the certificate. Without any authentication.
Author
Owner

@Curid commented on GitHub (May 28, 2022):

Android security policy on my phone does not allow working with impervious CA. Your application is no exception.

@MuratovAS Are you sure about that? What do you mean by "impervious CA"? Which Android version?

<!-- gh-comment-id:1140302695 --> @Curid commented on GitHub (May 28, 2022): > Android security policy on my phone does not allow working with impervious CA. Your application is no exception. @MuratovAS Are you sure about that? What do you mean by "impervious CA"? Which Android version?
Author
Owner

@binwiederhier commented on GitHub (Sep 24, 2023):

@MuratovAS I was so confused why I couldn't find this ticket anymore. This feature is requested a lot, so I do want to keep it open if you don't mind.

<!-- gh-comment-id:1732603835 --> @binwiederhier commented on GitHub (Sep 24, 2023): @MuratovAS I was so confused why I couldn't find this ticket anymore. This feature is requested a lot, so I do want to keep it open if you don't mind.
Author
Owner

@kevin-king commented on GitHub (Sep 27, 2023):

I'm interested in this as well. I use https with ntfy in the browser. On Android, however, I point it at http and have another server entry in nginx config for port 80 so that changes to IP/port don't require a change to the Android app configuration. I'd say this is good enough of a solution for self hosting except for the fact that file attachments can't be downloaded over http. My workaround is to copy the url and paste it into my mobile browser (which doesn't have the https CA restriction).

<!-- gh-comment-id:1738127069 --> @kevin-king commented on GitHub (Sep 27, 2023): I'm interested in this as well. I use https with ntfy in the browser. On Android, however, I point it at http and have another server entry in nginx config for port 80 so that changes to IP/port don't require a change to the Android app configuration. I'd say this is good enough of a solution for self hosting except for the fact that file attachments can't be downloaded over http. My workaround is to copy the url and paste it into my mobile browser (which doesn't have the https CA restriction).
Author
Owner

@ghost commented on GitHub (Dec 8, 2023):

Can't you just import your own CA certificate into the Android user certificate store? The required setting in the app to utilize user certificates seems to be set: https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/xml/network_security_config.xml. Also make sure that the certificate is valid for your host, see https://github.com/home-assistant/companion.home-assistant/pull/1011/files.

(not an ntfy user, but I stumbled upon this issue when searching for a solution to a similar issue in Android)

<!-- gh-comment-id:1847980901 --> @ghost commented on GitHub (Dec 8, 2023): Can't you just import your own CA certificate into the Android user certificate store? The required setting in the app to utilize user certificates seems to be set: https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/xml/network_security_config.xml. Also make sure that the certificate is valid for your host, see https://github.com/home-assistant/companion.home-assistant/pull/1011/files. (not an ntfy user, but I stumbled upon this issue when searching for a solution to a similar issue in Android)
Author
Owner

@kevin-king commented on GitHub (Dec 10, 2023):

Can't you just import your own CA certificate into the Android user certificate store?

I don't exactly remember this one anymore, but I believe that yes, you can install a user cert as long as that user cert is legitimate. Meaning something from Let's Encrypt or any authority with a matching root cert to your phone's system root certs.

If memory serves, what you cannot do is install a self-signed cert, which is a reasonable thing to do for self-hosted LAN services that will never be exposed to the internet.

That said, this is becoming such a problem across all applications these days that I caved and now use a Let's Encrypt cert for my LAN-only services and do what you mention--install it into my Android system's User certs. It's just annoying to need real SSL certs in a LAN-only context. The more complicated the self-hosted setup gets the harder it is to maintain. I'll add that acme.sh has made this process MUCH better than with certbot.

<!-- gh-comment-id:1848961753 --> @kevin-king commented on GitHub (Dec 10, 2023): > Can't you just import your own CA certificate into the Android user certificate store? I don't exactly remember this one anymore, but I believe that yes, you can install a user cert as long as that user cert is legitimate. Meaning something from Let's Encrypt or any authority with a matching root cert to your phone's system root certs. If memory serves, what you cannot do is install a self-signed cert, which is a reasonable thing to do for self-hosted LAN services that will never be exposed to the internet. That said, this is becoming such a problem across all applications these days that I caved and now use a Let's Encrypt cert for my LAN-only services and do what you mention--install it into my Android system's User certs. It's just annoying to need real SSL certs in a LAN-only context. The more complicated the self-hosted setup gets the harder it is to maintain. I'll add that acme.sh has made this process MUCH better than with certbot.
Author
Owner

@ghost commented on GitHub (Dec 10, 2023):

I just installed a self-signed certificate on Android. You just need to make sure you set the correct certificate properties during creation - take a look the the second link from my previous post if you are interested.

<!-- gh-comment-id:1849004048 --> @ghost commented on GitHub (Dec 10, 2023): I just installed a self-signed certificate on Android. You just need to make sure you set the correct certificate properties during creation - take a look the the second link from my previous post if you are interested.
Author
Owner

@kevin-king commented on GitHub (Dec 10, 2023):

Interesting thanks for testing. Out of curiosity, to which IP does YOUR_HA_STATIC_IP_HERE refer? In my case, neither ntfy nor my reverse proxy pointing to it (through ntfy.mydomain.com) are public. Are you setting YOUR_HA_STATIC_IP_HERE to be your internal IP like 10.x.x.x/192.168.x.x? Or are you setting it to a public static IP? (Please forgive me if this is a dumb question)

<!-- gh-comment-id:1849011479 --> @kevin-king commented on GitHub (Dec 10, 2023): Interesting thanks for testing. Out of curiosity, to which IP does `YOUR_HA_STATIC_IP_HERE` refer? In my case, neither ntfy nor my reverse proxy pointing to it (through `ntfy.mydomain.com`) are public. Are you setting `YOUR_HA_STATIC_IP_HERE` to be your internal IP like `10.x.x.x`/`192.168.x.x`? Or are you setting it to a public static IP? (Please forgive me if this is a dumb question)
Author
Owner

@ghost commented on GitHub (Dec 10, 2023):

I am using the local IP address of the server which I connect to via LAN, 192.168.x.x.

<!-- gh-comment-id:1849019275 --> @ghost commented on GitHub (Dec 10, 2023): I am using the local IP address of the server which I connect to via LAN, `192.168.x.x`.
Author
Owner

@Pysis868 commented on GitHub (Jul 17, 2024):

Already have my cert. Found this nice, but unfortunate summary, which may mean the dev would still need to add more to support this:
https://stackoverflow.com/a/56295643

Update:

There is no way to add self signed server certificates at device level in Android. However you can trust such a self signed certificate in your application by creating your own Trust manager.

Check out this android doc link:

https://developer.android.com/training/articles/security-ssl#SelfSigned

I also found a tutorial which shows how add self signed certificates to a browser in android (Chrome and Firefox), however it is still not applicable device wide and just that those applications enable you trust your certificates in them.

https://coderwall.com/p/wv6fpq/add-self-signed-ssl-certificate-to-android-for-browsing

<!-- gh-comment-id:2234202309 --> @Pysis868 commented on GitHub (Jul 17, 2024): Already have my cert. Found this nice, but unfortunate summary, which may mean the dev would still need to add more to support this: https://stackoverflow.com/a/56295643 > Update: > > There is no way to add self signed server certificates at device level in Android. However you can trust such a self signed certificate in your application by creating your own Trust manager. > > Check out this android doc link: > > https://developer.android.com/training/articles/security-ssl#SelfSigned > > I also found a tutorial which shows how add self signed certificates to a browser in android (Chrome and Firefox), however it is still not applicable device wide and just that those applications enable you trust your certificates in them. > > https://coderwall.com/p/wv6fpq/add-self-signed-ssl-certificate-to-android-for-browsing
Author
Owner

@Fmstrat commented on GitHub (Apr 28, 2025):

Can't you just import your own CA certificate into the Android user certificate store? The required setting in the app to utilize user certificates seems to be set: https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/xml/network_security_config.xml. Also make sure that the certificate is valid for your host, see https://github.com/home-assistant/companion.home-assistant/pull/1011/files.

(not an ntfy user, but I stumbled upon this issue when searching for a solution to a similar issue in Android)

Unfortunately, this doesn't seem to be the case as it's not working in my testing. Perhaps Ntfy uses a custom HTTP library that the trust store isn't set for?

<!-- gh-comment-id:2835953852 --> @Fmstrat commented on GitHub (Apr 28, 2025): > Can't you just import your own CA certificate into the Android user certificate store? The required setting in the app to utilize user certificates seems to be set: https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/xml/network_security_config.xml. Also make sure that the certificate is valid for your host, see https://github.com/home-assistant/companion.home-assistant/pull/1011/files. > > (not an ntfy user, but I stumbled upon this issue when searching for a solution to a similar issue in Android) Unfortunately, this doesn't seem to be the case as it's not working in my testing. Perhaps Ntfy uses a custom HTTP library that the trust store isn't set for?
Author
Owner

@Fmstrat commented on GitHub (Apr 28, 2025):

After further investigation, this seems to be the case. Ntfy is using OkHTTP (just realized there is a separate repo there for this): https://github.com/search?q=repo%3Abinwiederhier%2Fntfy-android+okhttp&type=code

I believe OkHTTP requires a Trust Store to be added from the system. Something like the below on every occurrence of the Builder.

val trustManagerFactory = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm()
)
trustManagerFactory.init(null as KeyStore?)
val trustManagers = trustManagerFactory.trustManagers
require(trustManagers.size == 1 && trustManagers[0] is X509TrustManager) {
    "Unexpected default trust managers: ${trustManagers.contentToString()}"
}
val trustManager = trustManagers[0] as X509TrustManager

val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
val sslSocketFactory = sslContext.socketFactory

val okHttpClient = OkHttpClient.Builder()
    .sslSocketFactory(sslSocketFactory, trustManager)
    .build()

Note, there could also be a secondary issue. I set up a proxy using a Let's Encrypt cert, and use my local DNS server to set the valid domain host to point to an internal IP. Ntfy can't seem to connect to that, either. My only guess is that Ntfy is for some reason ignoring the system DNS setting there, but I don't see anything obvious for that.

<!-- gh-comment-id:2836078084 --> @Fmstrat commented on GitHub (Apr 28, 2025): After further investigation, this seems to be the case. Ntfy is using OkHTTP (just realized there is a separate repo there for this): https://github.com/search?q=repo%3Abinwiederhier%2Fntfy-android+okhttp&type=code I believe OkHTTP requires a Trust Store to be added from the system. Something like the below on every occurrence of the `Builder`. ``` val trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() ) trustManagerFactory.init(null as KeyStore?) val trustManagers = trustManagerFactory.trustManagers require(trustManagers.size == 1 && trustManagers[0] is X509TrustManager) { "Unexpected default trust managers: ${trustManagers.contentToString()}" } val trustManager = trustManagers[0] as X509TrustManager val sslContext = SSLContext.getInstance("TLS") sslContext.init(null, arrayOf<TrustManager>(trustManager), null) val sslSocketFactory = sslContext.socketFactory val okHttpClient = OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, trustManager) .build() ``` Note, there could also be a secondary issue. I set up a proxy using a Let's Encrypt cert, and use my local DNS server to set the valid domain host to point to an internal IP. Ntfy can't seem to connect to that, either. My only guess is that Ntfy is for some reason ignoring the system DNS setting there, but I don't see anything obvious for that.
Author
Owner

@Fmstrat commented on GitHub (Apr 28, 2025):

Ok, got it working. This turned out to be a combination of things that led to it looking like a cert issue. If you are running into issues with a self-hosted CA:

  • Ensure you've added the CA to the Android device
  • Clear all storage from the ntfy app. This is important as the cache is holding login credentials, and if you change your default server in the app, these credentials may invalidate if you are swapping a URL
  • Ensure you've updated the NTFY_BASE_URL to the appropriate URL (this turned out to be my issue, as I was switching from an external to an internal domain)

After that, all is golden. I'm guessing the Trust Manager I mention above is somewhere else in the code away from the OkHTTP builder.

<!-- gh-comment-id:2836627137 --> @Fmstrat commented on GitHub (Apr 28, 2025): Ok, got it working. This turned out to be a combination of things that led to it looking like a cert issue. If you are running into issues with a self-hosted CA: - Ensure you've added the CA to the Android device - Clear all storage from the `ntfy` app. This is important as the cache is holding login credentials, and if you change your default server in the app, these credentials may invalidate if you are swapping a URL - Ensure you've updated the `NTFY_BASE_URL` to the appropriate URL (this turned out to be my issue, as I was switching from an external to an internal domain) After that, all is golden. I'm guessing the Trust Manager I mention above is somewhere else in the code away from the OkHTTP builder.
Author
Owner

@binwiederhier commented on GitHub (Jan 4, 2026):

I am working on this in https://github.com/binwiederhier/ntfy-android/pull/149. It's still WIP, but it'll turn out great. The trusted cert part is already working nicely, but I am working on a better user flow. I'll also add a way to add mTLS (which is also working, but a little awkward).

<!-- gh-comment-id:3707606206 --> @binwiederhier commented on GitHub (Jan 4, 2026): I am working on this in https://github.com/binwiederhier/ntfy-android/pull/149. It's still WIP, but it'll turn out great. The trusted cert part is already working nicely, but I am working on a better user flow. I'll also add a way to add mTLS (which is also working, but a little awkward).
Author
Owner

@binwiederhier commented on GitHub (Jan 4, 2026):

Relates to #530

<!-- gh-comment-id:3707606337 --> @binwiederhier commented on GitHub (Jan 4, 2026): Relates to #530
Author
Owner

@binwiederhier commented on GitHub (Jan 5, 2026):

📢 Question: For the "manage certificates" feature, would people be fine to just trust specific certificates, or do people want to add a CA cert and trust anything signed by that?

When adding a topic from your own server with self-signed cert Manage certs overview View/delete certificate
Image Image Image
<!-- gh-comment-id:3708632833 --> @binwiederhier commented on GitHub (Jan 5, 2026): 📢 ❓ Question: For the "manage certificates" feature, would people be fine to just trust specific certificates, or do people want to add a CA cert and trust anything signed by that? <table> <tr> <td>When adding a topic from your own server with self-signed cert <td>Manage certs overview <td>View/delete certificate <tr> <td><img width="777" height="1578" alt="Image" src="https://github.com/user-attachments/assets/a0207d71-6d5b-4b8b-9b2b-b5ce0ee56573" /> <td><img width="777" height="1578" alt="Image" src="https://github.com/user-attachments/assets/8704d035-2b83-499b-90bd-ddacf33d26ec" /> <td><img width="777" height="1578" alt="Image" src="https://github.com/user-attachments/assets/f087b779-5563-478f-ba5b-30ff4b4f6546" />
Author
Owner

@binwiederhier commented on GitHub (Jan 5, 2026):

It's looking really good: https://ntfy.sh/file/1znMWy4YkEdf.webm

<!-- gh-comment-id:3708968114 --> @binwiederhier commented on GitHub (Jan 5, 2026): It's looking really good: https://ntfy.sh/file/1znMWy4YkEdf.webm
Author
Owner

@binwiederhier commented on GitHub (Jan 6, 2026):

@cyb3rko has offered to test it out a bit. He made some good comments around how the CertUtil in the PR (https://github.com/binwiederhier/ntfy-android/pull/149). Let me try to summarize them here (please correct me if I'm wrong):

  • The hostname verifier should never be disabled, because if a self-signed cert's key is stolen and the attacker is in the network, they could MITM
  • The cert exceptions should be per-hostname, not just "trust this cert entirely regardless of the hostname"

Please let me know if this is accurate.

--

I think what this means is this:

(a) In the flow "AddFragment -> TrustedCertFragment" (= unknown certificate, UNKNOWN mode), when we click "Trust", we add a "(baseUrl, cert)" combo to the database, e.g. "https://ntfy.example.com, ". If I connect to https://10.0.0.1 and it presents the same cert, it is not trusted, but TrustedCertFragment dialog is shown again instead, and when I click "Trust", I have a second entry.

This is how Firefox does it too:

Image

(b) In the "CertificateSettingsFragment -> TrustedCertFragment" (= manually add cert, ADD mode), we show a baseUrl field that the user has to fill out.

(c) What about CAs? I honestly don't know how to handle that. Do we have a third section for CAs in the CertificateSettingsFragment, and then we add the CA to the combinedTrustManager, but WITH hostname validation enabled?

<!-- gh-comment-id:3715025034 --> @binwiederhier commented on GitHub (Jan 6, 2026): @cyb3rko has offered to test it out a bit. He made some good comments around how the `CertUtil` in the PR (https://github.com/binwiederhier/ntfy-android/pull/149). Let me try to summarize them here (please correct me if I'm wrong): - The hostname verifier should never be disabled, because if a self-signed cert's key is stolen and the attacker is in the network, they could MITM - The cert exceptions should be per-hostname, not just "trust this cert entirely regardless of the hostname" Please let me know if this is accurate. -- I think what this means is this: (a) In the flow "AddFragment -> TrustedCertFragment" (= unknown certificate, UNKNOWN mode), when we click "Trust", we add a "(baseUrl, cert)" combo to the database, e.g. "https://ntfy.example.com, <certpem>". If I connect to https://10.0.0.1 and it presents the same cert, it is not trusted, but TrustedCertFragment dialog is shown again instead, and when I click "Trust", I have a second entry. This is how Firefox does it too: <img width="1104" height="774" alt="Image" src="https://github.com/user-attachments/assets/fc0f3793-32de-4b5e-a3fc-3bd86ce8c432" /> (b) In the "CertificateSettingsFragment -> TrustedCertFragment" (= manually add cert, ADD mode), we show a baseUrl field that the user has to fill out. (c) What about CAs? I honestly don't know how to handle that. Do we have a third section for CAs in the CertificateSettingsFragment, and then we add the CA to the combinedTrustManager, but WITH hostname validation enabled?
Author
Owner

@cyb3rko commented on GitHub (Jan 7, 2026):

The hostname verifier should never be disabled, because if a self-signed cert's key is stolen and the attacker is in the network, they could MITM

At least NOT by default. If anybody can deliver valid use-cases of ignoring hostname validation, we could talk about a opt-out option for that.

The cert exceptions should be per-hostname, not just "trust this cert entirely regardless of the hostname"

To be exact not only based on the hostname, but rather the whole endpoint (on transport layer, so without protocol or full URL), so the combination of hostname/IP address and port.

If I connect to 10.0.0.1 and it presents the same cert, it is not trusted, but TrustedCertFragment dialog is shown again instead, and when I click "Trust", I have a second entry.

In that case, we should remove the previous certificate for that exact endpoint. Having two trusted certificates for a single endpoint is not really a good solution in my eyes. But to be fair, I don't know how for example Firefox handles that edge-case.

<!-- gh-comment-id:3721114423 --> @cyb3rko commented on GitHub (Jan 7, 2026): > The hostname verifier should never be disabled, because if a self-signed cert's key is stolen and the attacker is in the network, they could MITM At least NOT by default. If anybody can deliver valid use-cases of ignoring hostname validation, we could talk about a opt-out option for that. > The cert exceptions should be per-hostname, not just "trust this cert entirely regardless of the hostname" To be exact not only based on the hostname, but rather the whole endpoint (on transport layer, so without protocol or full URL), so the combination of hostname/IP address and port. > If I connect to [10.0.0.1](https://10.0.0.1/) and it presents the same cert, it is not trusted, but TrustedCertFragment dialog is shown again instead, and when I click "Trust", I have a second entry. In that case, we should remove the previous certificate for that exact endpoint. Having two trusted certificates for a single endpoint is not really a good solution in my eyes. But to be fair, I don't know how for example Firefox handles that edge-case.
Author
Owner

@cyb3rko commented on GitHub (Jan 7, 2026):

What about CAs? I honestly don't know how to handle that. Do we have a third section for CAs in the CertificateSettingsFragment, and then we add the CA to the combinedTrustManager, but WITH hostname validation enabled?

I feel like supporting "Trusted certificates" and "Trusted CAs" is a bit over-the-top.
Either you add your own CA and all your self-hosted endpoints are trusted if correctly signed, OR you have to trust your server certificates individually.
If we combine both, it becomes messy real quick.

<!-- gh-comment-id:3721123046 --> @cyb3rko commented on GitHub (Jan 7, 2026): > What about CAs? I honestly don't know how to handle that. Do we have a third section for CAs in the CertificateSettingsFragment, and then we add the CA to the combinedTrustManager, but WITH hostname validation enabled? I feel like supporting "Trusted certificates" and "Trusted CAs" is a bit over-the-top. Either you add your own CA and all your self-hosted endpoints are trusted if correctly signed, OR you have to trust your server certificates individually. If we combine both, it becomes messy real quick.
Author
Owner

@binwiederhier commented on GitHub (Jan 8, 2026):

I think I'll try to model it after Firefox's UIs. It has

  • Your certificates (= client certs)
  • Servers (= per-hostname trusted/pinned certs)
  • Authorities (= Trusted CAs) [I may not do this at all]

It shouldn't be difficult to update the code to achieve this, and it'll be more secure. I'm note sure if I will name it the same, because Firefox's naming is weird as hell. Chrome has "Local certificates" and "Your certificates". Local certificates are split into trusted certs, intermediate certs and distrusted certs. That's also a tad weird.

<!-- gh-comment-id:3726222740 --> @binwiederhier commented on GitHub (Jan 8, 2026): I think I'll try to model it after Firefox's UIs. It has - Your certificates (= client certs) - Servers (= per-hostname trusted/pinned certs) - Authorities (= Trusted CAs) [I may not do this at all] It shouldn't be difficult to update the code to achieve this, and it'll be more secure. I'm note sure if I will name it the same, because Firefox's naming is weird as hell. Chrome has "Local certificates" and "Your certificates". Local certificates are split into trusted certs, intermediate certs and distrusted certs. That's also a tad weird.
Author
Owner

@binwiederhier commented on GitHub (Jan 8, 2026):

I think just doing "Client certs" and "Trusted certs" (per-hostname exceptions) would be best for now. If you have a custom CA, then this will still work, because you can manually click "Trust".

<!-- gh-comment-id:3726226758 --> @binwiederhier commented on GitHub (Jan 8, 2026): I think just doing "Client certs" and "Trusted certs" (per-hostname exceptions) would be best for now. If you have a custom CA, then this will still work, because you can manually click "Trust".
Author
Owner

@binwiederhier commented on GitHub (Jan 9, 2026):

I've updated the code and it's much cleaner now. I still have to do a lot of cleanup, but I like the approach more.

<!-- gh-comment-id:3729252485 --> @binwiederhier commented on GitHub (Jan 9, 2026): I've updated the code and it's much cleaner now. I still have to do a lot of cleanup, but I like the approach more.
Author
Owner

@binwiederhier commented on GitHub (Jan 10, 2026):

I like this enough to merge it. I've extensively self-reviewed https://github.com/binwiederhier/ntfy-android/pull/149. Please feel free to still review and/or comment on this design.

Image Image Image
Image Image Image
Image Image
<!-- gh-comment-id:3731322092 --> @binwiederhier commented on GitHub (Jan 10, 2026): I like this enough to merge it. I've extensively self-reviewed https://github.com/binwiederhier/ntfy-android/pull/149. Please feel free to still review and/or comment on this design. <table><tr> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/592c968a-924d-4242-bdf6-745be16334b3" /> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/301c7e1a-e252-485c-88e1-8b6f9c4cff21" /> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/a7efb037-174f-41cd-a24e-faaeba012669" /> <tr> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/2d8b716d-0115-4e29-8e0c-7184ae5e2989" /> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/e22f5bb3-f3ca-46b0-aa7e-a575d1b1d813" /> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/9582cf5a-b266-447b-827e-adfbfd22ea4f" /> <tr> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/da2883ac-b651-4579-85e6-03a58b09646e" /> <td><img width="792" height="1626" alt="Image" src="https://github.com/user-attachments/assets/4af96894-b517-493a-9bf4-fd4b69688c97" />
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#169
No description provided.