Sessions and access tokens have a bounded, server-enforced lifetime, and the session identifier is regenerated on login and on privilege change. No AI engine is involved: the verdict is reproducible from the source alone.
Inputs
Non-test code files of the checkout (JavaScript, TypeScript, Python, PHP) plus framework settings (Django settings, Laravel config/session, auth, sanctum, jwt), analysed statically with the static analysis kit: tokens, function units, calls with their arguments, imports and route registrations of Next, Express, Fastify, Koa, Hono, Nest, Lambda, Django, Flask, FastAPI and Laravel. The unit of analysis for expiry is the CALL that issues a session or token (jwt.sign, SignJWT, jwt.encode, JWT::encode, express-session/cookie-session options, iron-session, Flask permanent sessions, SESSION_COOKIE_AGE, Laravel session lifetime) and its parsed arguments (option keys, payload keys, a variable resolved to its assignment in the same file). The unit for rotation is the login FUNCTION of the application's own (a function or route that verifies a password and writes the session or issues the token, following its calls through local functions, middleware and imported modules up to 2 hops) and every password-change or role-change function. Paths listed in excludes (test, spec and tmp files, __tests__, __mocks__, fixtures, test, tests and audit-scripts folders) are never analysed. Nothing of the checkout is executed.
Decision rule
Not applicable when no session or token mechanism is referenced. FAIL (HIGH, with the call line) when an issuance call has no bounded lifetime: jwt.sign without expiresIn and without an exp claim in the payload, SignJWT without setExpirationTime, jwt.encode or JWT::encode without exp, session()/cookieSession() options without maxAge, expires or a store ttl, iron-session with ttl 0, or a permanent Flask session with no PERMANENT_SESSION_LIFETIME anywhere. A lifetime above 30 days is MEDIUM (blocks in Extended suites); an access token above 7 days is LOW. An issuance whose options or payload come from outside the file (an import or a parameter) is LOW, informative (lifetime-unresolved). FAIL (HIGH, with the function line) when a login function of the application's own — it verifies a password (bcrypt.compare, argon2.verify, password_verify, Hash::check, check_password, authenticate(request…), Auth::attempt…) and writes the session or issues a token, itself or through the functions it calls within 2 module hops — neither regenerates the identifier (session.regenerate, cycle_key(), session()->regenerate(), session_regenerate_id, session.clear, a fresh token issued after the check) nor uses a framework login that rotates by default (Django login(), Laravel Auth::login/Auth::attempt under the session guard, Passport req.login, NextAuth, Lucia createSession, Clerk, Auth0). A password-change or role-change function that neither regenerates nor invalidates the other sessions (update_session_auth_hash, regenerate, invalidate, logoutOtherDevices, a session or token version bump, a fresh token) is MEDIUM. PASS when every issuance bounds its lifetime and every own login rotates; the summary names each. Not judged by this check (declared): rotation and expiry performed by an external identity provider, the lifetime of a raw session cookie whose value is not issued by a recognised call, whether the server enforces the lifetime it declares, and rotation on login when the checkout has no own login function (authentication delegated or living elsewhere: the verdict then rests on expiry alone).
Type
deterministic
1.1.1: a callee whose root is a name that `Object.prototype` also carries (`build().toString()` tokenizes to the bare callee `toString`; also `constructor`, `valueOf`, `hasOwnProperty`) was looked up in the plain object that holds the imported names, so it resolved to the INHERITED FUNCTION instead of to nothing and the whole check died with "name.includes is not a function". Only a real binding counts now, and the name of a unit is always read as a string. Found on a 1 319-file checkout (2fa-available and session-expiry-rotation, 2026-09-24); the same line was in the 15 scripts that walk the call graph, so all fifteen ship the fix. (1.1.0: deterministic: the rule runs over the static analysis kit (tokens, function units, calls, imports, routes) with no AI engine; exact decisionRule and languages published; not-applicable with the reason when the checkout gives nothing to evaluate. The unit is the issuance CALL (jwt.sign, SignJWT, jwt.encode, JWT::encode, session(), iron-session) with its arguments parsed as tokens (option and payload keys, variables resolved in the file): no bounded lifetime is HIGH, more than 30 days is MEDIUM, unresolved options are LOW; rotation is required on every own login unit (verifies a password AND writes the session within 2 module hops) unless a framework login rotates by default; a password or role change without invalidation is MEDIUM. Not judged: rotation by an external identity provider, raw cookie lifetimes, enforcement, rotation when no own login exists. (1.0.2: never analyses temporary files (*.tmp.*; spec.excludes follows AUDITOR_ANALYSIS_EXCLUDES). (1.0.1: never analyses test, spec, fixture and mock paths nor the auditor's own scripts (spec.excludes = AUDITOR_ANALYSIS_EXCLUDES); a fixture-looking secret (sk_test_, example, dummy) in real code is LOW, informative; every model call stays under the engine prompt cap (spec.promptMaxChars = AUDITOR_AI_PROMPT_MAX_CHARS): assess mode sends the candidate set in parts and aggregates the verdicts (a HIGH in any part is a FAIL, an unsatisfied part is a FAIL).)))
// the unit of analysis is the CALL that issues a session or token, with its arguments parsed as tokens
const LIFETIME_KEY = /^(?:expiresIn|exp|maxAge|expires|ttl|lifetime|expiry|expiration)$/i; // option or payload key that bounds the lifetime
// jwt.sign(payload, secret, options): exp in the payload keys or expiresIn in the options keys (a variable is resolved to its assignment in the file) -> bounded; neither -> HIGH
// SignJWT: setExpirationTime in the builder chain or on the assigned variable -> bounded; session({...}) without maxAge/expires/ttl -> HIGH; lifetime > 30 days -> MEDIUM
// a login unit (verifies a password AND writes the session, itself or through <= 2 module hops) without ROTATION and without a framework login that rotates -> HIGH; a password/role change without invalidation -> MEDIUM
The full script is disclosed on request in a read-only viewer (never published on GitHub); the attestation binds to this exact hash.