Skip to content

deep-review: sprayshed — TST: test_rate_limit_enforced is tautological and masks the missing rate limit #10

Description

@5h4d0wn1k

Severity

Medium — the only test guarding a safety property (rate limiting) can never fail, giving false confidence; mutation-proven.

Location

  • tests/test_spray.py:60-73:
def test_rate_limit_enforced(self):
    ...
    cfg["spray"]["delay_between_attempts"] = 0.1
    ...
    elapsed = time.monotonic() - start
    self.assertGreaterEqual(elapsed, 0.0)

elapsed >= 0.0 holds for every possible time.monotonic() delta, including 0.

Repro (mutation proof, executed against live lab)

python3 -c "
import time
from sprayshed.spray import spray_password
from sprayshed.config import get_config
from tests.fixtures import get_shared_lab
mgr = get_shared_lab()
cfg = get_config(); cfg['spray']['delay_between_attempts'] = 100.0  # absurd: 100s spacing
from sprayshed.lab.http_sim import try_auth as http_try_auth
t0 = time.monotonic()
spray_password('Summer2024', ['jane.doe'], http_try_auth, mgr.host, cfg['lab']['http_port'], cfg, dry_run=False)
elapsed = time.monotonic()-t0
print('elapsed with 100s configured spacing:', round(elapsed,3), 's; test assertion (>= 0.0):', elapsed >= 0.0)
from tests.fixtures import stop_shared_lab; stop_shared_lab()
"
# observed: elapsed ~0.001s with 100s configured spacing, yet the test's assertion still passes
# companion PRF issue proves the underlying enforcement gap (burst bypass)

Observed vs expected

  • Observed: test passes with rate limiting effectively absent (100s spacing honored for 1ms).
  • Expected: test asserts a real bound, e.g. elapsed >= (len(users)-1) * delay with ≥2 users, and fails when pacing is removed.

Safe remediation

Rewrite the test with 3+ users and assert elapsed >= (n-1)*delay*0.9; verify it fails on the current code (red) then fix the limiter (burst=1, see companion PRF issue) to green. No product behavior change from the test edit itself.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions