{"items":[{"id":"NVI-00004186","kind":"vulnerability","title":"spomky-labs/otphp: Unbounded digits parameter in a provisioning URI triggers an uncaught DivisionByZeroError in OTP generation","revision":1,"unknowns":["Customer inventory, deployment, reachability and exploitation have not been inspected."],"lifecycle":"active","identifiers":["GHSA-g7m4-839x-ch6v"],"plain_summary":"OSV carries this publisher advisory for spomky-labs/otphp. This is an aggregated source copy; consult the original publisher and compare update dates.","review_status":"source_listed","control_topics":[],"public_actions":[{"summary":"The original advisory lists fixed boundaries 11.4.3 for spomky-labs/otphp. Confirm the publisher’s latest guidance.","source_ids":["sr-5c3b602b6e3fceda54a4f63a7e1357e7"],"action_type":"vendor_patch","limitations":"Confirm current vendor support, compatibility and deployment evidence. This report has not tested a fix in your system.","current_supported_target":null}],"schema_version":"1.1.0","source_metrics":[],"why_it_matters":"Published affected context helps an owner decide what evidence to gather. This report has not examined your application.","related_sources":[{"id":"sr-5c3b602b6e3fceda54a4f63a7e1357e7","url":"https://github.com/advisories/GHSA-g7m4-839x-ch6v","basis":"vendor_advisory","notes":"GitHub-origin advisory, CC-BY-4.0; OSV is an aggregate copy, not independent corroboration.","title":"GHSA-g7m4-839x-ch6v","publisher":"GitHub Advisory Database via OSV","observed_at":"2026-10-31T21:42:20.412Z"}],"affected_context":[{"certainty":"source_listed","source_ids":["sr-5c3b602b6e3fceda54a4f63a7e1357e7"],"technology":"spomky-labs/otphp","known_exclusions":[],"conditions_summary":"## Summary\n\nThe `digits` parameter parsed from a provisioning URI is validated only with a lower bound (`$value > 0`) and has no upper bound (`src/OTP.php:353-357`). OTP generation computes `$code % (10 ** $this->getDigits())` (`src/OTP.php:283`). When `digits` is large enough that `10 ** digits` overflows PHP's integer range and the `(int)` cast yields `0` (around `digits >= 40` on 64-bit PHP 8.x), the modulo operand becomes `0` and PHP raises a `DivisionByZeroError`.\n\n## Impact\n\n`OTPHP\\Factory::loadFromProvisioningUri()` forwards the attacker-controlled `digits` query value to `setParameter('digits', $value)`, so a hostile URI such as `otpauth://totp/Alice?secret=JBSWY3DPEHPK3PXP&digits=50` produces an OTP object whose `at()`, `now()`, and `verify()` all throw `DivisionByZeroError`. Because `DivisionByZeroError` extends `Error` (not `Exception`), callers that guard OTP generation with a `catch (\\Exception)` do not catch it, turning a malformed URI into an unhandled fatal error (denial of service of the verification path).\n\nMeasured threshold on PHP 8.3: `digits = 30` works, `digits >= 40` throws `DivisionByZeroError: Modulo by zero`.\n\n## Affected component\n\n- `src/OTP.php:353-357","public_affected_ranges":["ECOSYSTEM: introduced 0; fixed 11.4.3"]}],"null_published_at":"2026-10-31T22:12:52.633Z","source_updated_at":"2026-09-10T03:50:49.441Z","source_disclosed_at":"2026-06-18T20:45:47.000Z","is_synthetic_fixture":false,"null_last_reviewed_at":null,"public_change_summary":"First indexed by Null; source disclosure date is shown separately.","null_first_observed_at":"2026-10-31T21:42:20.412Z"}],"next_cursor":null,"snapshot_revision":"42594"}