Skip to content

[E2E-SEC-001]: feat(e2e)/SKY-108 Security E2E: 403s, rate-limit 429s, injection attempts, cross-tenant isolation, token-reuse revocation - #144

Open
dennisjoseph2025 wants to merge 10 commits into
nkswalih:devfrom
dennisjoseph2025:feat/SKY-108-Security-E2E-403s-and-rate-limit-429s-and-injection-attempts-and-cross-tenant-isolation-and-token-reuse-revocation
Open

dennisjoseph2025 wants to merge 10 commits into
nkswalih:devfrom
dennisjoseph2025:feat/SKY-108-Security-E2E-403s-and-rate-limit-429s-and-injection-attempts-and-cross-tenant-isolation-and-token-reuse-revocation

Conversation

@dennisjoseph2025

Copy link
Copy Markdown
Collaborator

feat(SKY-108): Security E2E suite — 403s, rate limits, injection, tenant isolation, token-reuse revocation

Implements [E2E-SEC-001]: a comprehensive security E2E suite executing the full
stack through the BFF against a hardened compose bootstrap, running in a
dedicated CI phase.

Coverage

Denial / RBAC — e2e/security/denial-403.spec.ts

  • Finance viewer can read finance data (authorized content is 200)
  • Payroll read/update denied with 403 (not 401, no data leak)
  • Anonymous caller rejected with 401

Rate limiting — e2e/security/rate-limit.spec.ts

  • Login returns 429 on the 5th attempt with a Retry-After header
  • AI inventory search returns 429 with Retry-After at 2 req/min

Injection — e2e/security/injection.spec.ts

  • SQLi boolean tautology → fails closed
  • SQLi comment injection → fails closed
  • Reflected XSS payload → fails closed
  • Encoded path traversal through a UUID route slot → fails closed

Tenant isolation — e2e/security/tenant-isolation.spec.ts

  • Admin token works on its own tenant
  • Foreign tenant slug is rejected, never silently routed

Refresh-token reuse — e2e/security/token-reuse.spec.ts

  • Replaying a rotated refresh token returns 401 and revokes the session family

Backend changes

Retry-After (seconds) is now emitted on rate-limit 429s and relayed through
the stack to the client:

Layer Change
libs/skyrict-common RateLimitExceededError carries retry_after_seconds
services/identity Emits Retry-After on rate-limit 429
services/ai-agent Emits Retry-After on rate-limit 429
services/core Relays Retry-After through the AI proxy
apps/web BFF relays Retry-After to the client

Test infra

  • Tightened compose override: IDENTITY_RATE_LIMIT_LOGIN=5,
    IDENTITY_REFRESH_REUSE_GRACE_SECONDS=0
  • CI security phase: down -v → merged-compose boot → re-seed →
    --project=security --workers=1 --retries=0
  • security.ts helper aligned to the BFF's underscore mfa statuses
    (mfa_setup / mfa_challenge)

Design note

The token-reuse attacker replays the rotated token directly against identity
(/api/v1/auth/refresh), not through the BFF. The BFF single-flights refresh
rotations in-process (rotateRefreshToken memo keyed by tenant+token), so a
same-process replay returns the cached rotated pair and never arms identity's
reuse detector. Hitting identity directly is the true replay boundary and
validates the 401 + family-kill behavior.

Verification

  • 14/14 security specs pass locally against the e2e stack
  • identity 665 / ai-agent 1276 / core 1446 unit tests pass
  • ruff check + tsc --noEmit + eslint clean

…y directly for reuse replay

- apiSignIn matches the BFF login route's underscore statuses
  (mfa_setup/mfa_challenge) instead of dotted ones.
- token-reuse attacker replays the rotated token straight at identity
  (/api/v1/auth/refresh) instead of through the BFF: the BFF memoizes
  in-process refresh rotations, so a replayed token would return the cached
  rotated pair and never arm identity's reuse detector.
- compose security override raises the login limit to 5 so the admin's own
  budget (setup + worker fixture + self-login = 3) isn't consumed.
@dennisjoseph2025 dennisjoseph2025 added bug Something isn't working area: web Next.js frontend area: ci/cd workflows, releases area: tests tests files fix fixed any errors/bugs labels Sep 18, 2026
@dennisjoseph2025 dennisjoseph2025 changed the title [E2E-SEC-001]: feat(e2e)/SKY108 Security E2E: 403s, rate-limit 429s, injection attempts, cross-tenant isolation, token-reuse revocation [E2E-SEC-001]: feat(e2e)/SKY-108 Security E2E: 403s, rate-limit 429s, injection attempts, cross-tenant isolation, token-reuse revocation Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci/cd workflows, releases area: tests tests files area: web Next.js frontend bug Something isn't working fix fixed any errors/bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant