mirror of
https://github.com/PR0M3TH3AN/bitlogin.git
synced 2026-10-27 08:31:21 +00:00
BL-16 (high): a remote signer's auth_url is attacker-controlled input that became a clickable href. sanitizeAuthUrl in core now admits only https (or loopback http) -- javascript:/data:/blob:/custom schemes are dropped without consuming the surfacing slot -- and the widget link shows the hostname. Hostile-scheme tests at both layers. BL-17: the post-creation PRF fallback assertion is pinned via allowCredentials to the credential that was just created, so a multi- passkey account sheet can no longer silently bind an older passkey's account. BL-18: queryOnce's timeout path sent CLOSE before settling, unguarded -- a relay dying mid-query stranded the promise and everything queued behind the worker's serial queue. The send is guarded; settling is unconditional. MockRelay.close() now terminates live sockets (it previously waited on them forever), and a suppressEose switch models the silent relay. BL-19: relays are no longer trusted to honor limits. Buffered queries enforce filter.limit locally, drop replayed duplicate ids, and cap at 1000 events; a 20-copy replay now yields one event. BL-20: the .semgrep.yml try/catch fallback pattern never parsed, so the entropy rules silently did not run. Rewritten in parseable form and verified under the pinned Semgrep 1.171.0: fires on hostile code, exits 0 on the clean tree. Lows: NIP-07 and NIP-46 verify returned signed events (signature, pinned session identity, field equality with the request); Nip46Client.close() wipes the client and conversation keys (§11.10); passkey labels carry a short suffix so multiple accounts are distinguishable; postcss bumped to 8.5.25 (GHSA-fxqj-rqcc-2cmp); GitHub Actions pinned to commit SHAs. Deferred as interop (recorded in TODO): NIP-46 protocol logout and switch_relays. 12 new adversarial tests; 256 total. Co-Authored-By: Claude Fable 5 <[email protected]>
64 lines
2.2 KiB
YAML
64 lines
2.2 KiB
YAML
# Local semgrep rules, run alongside `--config auto` in
|
|
# .github/workflows/security.yml.
|
|
#
|
|
# Checklist §13 of docs/entropy-audit-2026-07-31.md: make the randomness rules
|
|
# machine-enforced rather than review-enforced. Every rule here is currently
|
|
# clean across packages/ — they exist to keep it that way, not to flag a
|
|
# backlog.
|
|
rules:
|
|
- id: bitlogin-no-math-random
|
|
languages: [typescript, javascript]
|
|
severity: ERROR
|
|
message: >-
|
|
Math.random() is not a CSPRNG and must not be used anywhere in this
|
|
package, including for values that are not secrets. Use randomBytes or
|
|
randomUniformInt from @bitlogin/core/crypto. A ban with a standing
|
|
exception is where the next real misuse hides -- if you believe this
|
|
specific call is safe, the correct move is still to use the CSPRNG, which
|
|
costs nothing here.
|
|
paths:
|
|
include:
|
|
- /packages/*/src/**
|
|
pattern: Math.random(...)
|
|
|
|
- id: bitlogin-no-crypto-fallback
|
|
languages: [typescript, javascript]
|
|
severity: ERROR
|
|
message: >-
|
|
Do not fall back to another source when getRandomValues is unavailable.
|
|
Key generation must fail closed -- "continue with reduced security" is the
|
|
COLDCARD defect class. crypto/random.ts throws by design; keep it that way.
|
|
paths:
|
|
include:
|
|
- /packages/*/src/**
|
|
patterns:
|
|
- pattern-either:
|
|
- pattern: $C.getRandomValues(...) ?? $FALLBACK
|
|
- pattern: $C.getRandomValues(...) || $FALLBACK
|
|
- pattern: |
|
|
try {
|
|
...
|
|
$C.getRandomValues(...)
|
|
...
|
|
} catch ($E) {
|
|
...
|
|
return $FALLBACK;
|
|
}
|
|
|
|
- id: bitlogin-no-time-or-id-seeded-secrets
|
|
languages: [typescript, javascript]
|
|
severity: ERROR
|
|
message: >-
|
|
Timestamps, counters and identifiers are not entropy. A secret derived
|
|
from Date.now() or performance.now() is predictable to anyone who knows
|
|
roughly when it was created.
|
|
paths:
|
|
include:
|
|
- /packages/*/src/**
|
|
patterns:
|
|
- pattern-either:
|
|
- pattern: |
|
|
$KEY = $HASH(Date.now(), ...)
|
|
- pattern: |
|
|
$KEY = $HASH(performance.now(), ...)
|