#1823·Aegis

Negative digits in otpauth:// URI causes ArithmeticException crash

Author: woolcoxmCreated Aug 5, 2026Updated Aug 5, 2026

Summary

An otpauth:// URI with a negative digits parameter causes Aegis to crash with an
uncaught ArithmeticException (integer modulo by zero) when the app tries to generate
the code for that entry. The digits value is read from the URI and stored without any
range validation.

Steps to reproduce

  1. Create / share a QR code (or send an otpauth:// intent) containing a negative
    digits value, e.g.:
    otpauth://totp/Test:acct?secret=JBSWY3DPEHPK3PXP&digits=-1                                                                                                                                                                                                                                                       
  2. In Aegis, scan the QR (or open the shared URI) and add the entry.
  3. The app crashes when it attempts to generate/display the code.

Expected

The entry is rejected (or digits is clamped to a valid range) — no crash.

Actual

Crash with ArithmeticException from OTP.java.

Root cause

In GoogleAuthInfo.parseUri() (file app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java),
the digits query parameter is parsed and passed through with no range check:

java
String digits = uri.getQueryParameter("digits");                                                                                                                                                                                                                                                                    
if (digits != null) {                                                                                                                                                                                                                                                                                               
    info.setDigits(Integer.parseInt(digits));   // no validation                                                                                                                                                                                                                                                    
}                                                                                                                                                                                                                                                                                                                   

setDigits() stores the value. Later, when the code is generated, OTP computes:

java
int code = _code % (int) Math.pow(10, _digits);                                                                                                                                                                                                                                                                     

For _digits < 0, (int) Math.pow(10, _digits) evaluates to 0 (e.g.
(int) Math.pow(10, -1) == 0), so the expression becomes code % 0
ArithmeticException: / by zero, which is uncaught and crashes the app.

Suggested fix

Validate digits (and, for consistency, period/counter) in GoogleAuthInfo.parseUri
before setting them — e.g. reject or clamp non-positive / out-of-range values, and
whitelist the algorithm. Something like:

java
String digits = uri.getQueryParameter("digits");                                                                                                                                                                                                                                                                    
if (digits != null) {                                                                                                                                                                                                                                                                                               
    int d = Integer.parseInt(digits);                                                                                                                                                                                                                                                                               
    if (d < 1 || d > 10) {   // sane bounds for OTP digit counts                                                                                                                                                                                                                                                    
        throw new GoogleAuthInfoException(uri, "Invalid digits: " + digits);                                                                                                                                                                                                                                        
    }                                                                                                                                                                                                                                                                                                               
    info.setDigits(d);                                                                                                                                                                                                                                                                                              
}                                                                                                                                                                                                                                                                                                                   

Notes

  • Severity: low — it's a local DoS (app crash); the user has to scan/import a
    malicious entry themselves. No data loss (the vault is intact; reopening the app is fine
    once the bad entry is removed).
  • While reviewing, I noticed period, counter, and algorithm are likewise read from
    the URI without validation. period = 0 doesn't crash (it's floating-point division in
    TOTP.generateOTP), but a co