Skip to main content

Overview

PassAgent runs a multi-layered threat detection system that analyzes authentication events, access patterns, and network behavior in real time. Detections are backed by Redis for sliding-window analysis and produce one of four response actions: block the request, require step-up authentication, warn the user, or send an alert. All detections are logged to the audit trail and trigger security webhook alerts.

Anomaly types

TypeTriggerDefault action
brute_force5+ failed auth attempts in 5 minutesblock
impossible_travelLogin from a geographically impossible location given elapsed timestep_up_auth
suspicious_travelLogin from an unusual but not impossible locationwarn
new_deviceUnrecognized device fingerprintstep_up_auth
revoked_deviceDevice previously revoked by the userblock
bulk_operation50+ vault operations (reads, shares, exports) in 60 secondsstep_up_auth
ip_spraySingle IP targeting multiple accountsblock or challenge
password_spraySame password hash attempted across multiple accountsblock or challenge
subnet_sprayMultiple IPs in the same /16 subnet targeting many accountsblock
access_anomalyBehavioral profiling score exceeds thresholdblock or step_up_auth

Response actions

ActionEffect
blockRequest is denied. The user cannot proceed.
step_up_authThe user must re-authenticate or complete an additional verification step.
warnThe request proceeds but a warning is logged and the user is notified.
alertA security alert is sent via webhook. The request may proceed.

Brute force detection

Tracks failed authentication attempts per user using Redis rate limiting.
ParameterValue
Threshold5 failures
Window300 seconds (5 minutes)
TTL600 seconds (10 minutes)
Actionblock
After every failed login, recordAuthEvent() increments the failure counter. When the threshold is exceeded, the system blocks further attempts and fires a brute_force security alert.

Credential spray detection

The spray detector identifies distributed attacks where an adversary targets multiple accounts from the same infrastructure.

IP spray

Tracks the number of distinct accounts targeted from a single IP address.
TierThresholdWindowActionBlock duration
Challenge3 accounts1 hourchallenge
Block6 accounts6 hoursblock2 hours
Hard block10 accounts24 hoursblock24 hours

Password spray

Tracks the same password hash being used against multiple accounts.
TierThresholdWindowActionBlock duration
Challenge3 accounts1 hourchallenge
Block5 accounts6 hoursblock2 hours

Subnet spray

Detects distributed spray attacks across a /16 subnet (first two octets).
TierThresholdWindowActionBlock duration
Block15 accounts1 hourblock2 hours

Redis key structure

Key patternData stored
spray:ip_attempts:{ip}Array of { email, timestamp } entries
spray:pw_hash:{hashPrefix}Array of { emailPrefix, ip, timestamp } entries
spray:subnet:{octet1}.{octet2}Array of { email, timestamp } entries
spray:blocklist:{ip}{ reason, expiresAt, type }
Email addresses are hashed before storage in spray detection records to protect user privacy. The hash is not cryptographic — it is used for deduplication only.

Block durations

LevelDuration
challenge30 minutes
block2 hours
hard_block24 hours
When an IP is blocked, a BlocklistEntry is written to Redis with an expiration timestamp. All subsequent requests from that IP are rejected until the block expires.

Impossible travel detection

When you log in from a new IP address, the system geolocates both the current and previous access locations, then calculates the travel speed required to move between them in the elapsed time.
1

Resolve IP location

Calls resolveIpLocation() to geolocate the current IP. Returns city, country, and coordinates.
2

Compare with last access

Retrieves the previous access location from Redis. If the IP is the same, no analysis is performed.
3

Analyze travel feasibility

Calculates distance (km), elapsed time, and resulting speed (km/h). Compares against known locations to determine confidence.
4

Classify the result

Returns one of three verdicts: normal, suspicious, or impossible. Only results with confidence >= 0.5 trigger a detection.
The anomaly result includes a travelAnalysis object:
FieldDescription
distanceKmDistance between the two locations in kilometers
speedKmhImplied travel speed in km/h
verdictnormal, suspicious, or impossible
confidenceConfidence score from 0 to 1
A user logs in from New York at 2:00 PM, then from London at 2:30 PM. The distance is ~5,500 km and the elapsed time is 30 minutes, implying a speed of 11,000 km/h. This exceeds any commercial flight speed and is classified as impossible travel.The system responds with step_up_auth and sends a security alert webhook.

Bulk operation detection

Monitors the volume of sensitive vault operations (password reveals, shares, exports) per user.
ParameterValue
Threshold50 operations
Window60 seconds
Actionstep_up_auth
This protects against automated exfiltration by a compromised session.

Device trust

The checkDeviceTrust() function evaluates device status and returns an appropriate anomaly result:
Device statusResult
Known and trustedNo detection
Unknown / new devicenew_device — requires step-up auth
Revoked devicerevoked_device — blocked

Behavioral profiling

The checkAccessBehavior() function uses the behavioral profiling system to score access events. It evaluates:
  • IP reputation and history
  • User agent consistency
  • Device fingerprint
  • Resource access patterns
  • Session characteristics
The profiling system returns a composite score out of 100 with detailed breakdowns. High scores trigger either block or step_up_auth depending on severity.

Audit and alerting

All detected anomalies produce two outputs:
Audit log entry
  • action: anomaly_detected
  • resource: auth or vault
  • metadata: anomaly type, reason, thresholds
  • Includes IP address and user agent
Security alert webhook
  • Fired for brute_force, impossible_travel, bulk_operation, and all spray detections
  • Includes user ID, IP address, and a description
  • Fire-and-forget (does not block the request)
All detectors fail open: if Redis is unavailable or geo-IP resolution fails, the request is allowed through rather than blocked. This prevents availability issues from locking users out of their vaults.