Skip to content

fix(descriptor): bound LIMIT to prevent unbounded SELECT (v0.2.3) - #13

Merged
eleven-by-clodocapeo[bot] merged 3 commits into
mainfrom
forge/queryme-v0.2.3-limit-bound
Aug 15, 2026
Merged

fix(descriptor): bound LIMIT to prevent unbounded SELECT (v0.2.3)#13
eleven-by-clodocapeo[bot] merged 3 commits into
mainfrom
forge/queryme-v0.2.3-limit-bound

Conversation

@forge-by-clodocapeo

@forge-by-clodocapeo forge-by-clodocapeo Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

limit on QueryDescriptor had no upper bound and, when omitted, produced
no LIMIT clause at all — a security fix for that is the point of this PR
(v0.2.3, v0.2.2 untouched — RC-40 of ADR 001 is frozen).

Per Bastion review, limit is now a required field (not optional with a
silent default) — every caller must state its own bound explicitly, capped
at MAX_LIMIT = 1000. An out-of-bounds limit is rejected
(ValidationError), never silently clamped or defaulted, matching ADR 001
§3.3 (a truncated result is worse than a refusal). The compiler re-checks
the bound as a defense-in-depth gate against model_construct() bypass.

An earlier revision of this PR briefly included agent-protocol staging
files that named affected consumers and exploitation detail — removed;
.gitignore updated to prevent recurrence.

Tests

Ran inside the branch worktree (uv sync && uv run ruff check . && uv run mypy src && uv run pytest):

  • ruff check . → All checks passed!
  • mypy src (strict) → Success: no issues found in 5 source files
  • pytest → 46 passed

Écarts / hypothèses

  • Ceiling value (MAX_LIMIT = 1000) is a judgment call, not a documented
    QueryMe convention — Bastion clearance requested on this choice.
  • limit becoming required is a breaking change for every call site;
    migrating consumers is separate follow-up work, out of scope here.
  • v0.2.3 tag not created yet — left for Keeper/Vigil once this PR merges
    (v0.2.2 must never move).

Refs #6

A descriptor with limit=None emitted no LIMIT clause at all, letting
any of the 6 consuming services run an unbounded SELECT against
production through the nominal query path (mass exfiltration / DoS).

limit now has an upper bound (DEFAULT_MAX_LIMIT=1000) enforced by
pydantic (le=), and the compiler applies that same ceiling whenever
limit is omitted instead of emitting no clause.

Refs #6

Agent-Role: forge
Agent-Thread: queryme-v023-limit-bound
Work-Unit: QUERYME-V023-LIMIT-BOUND
Issue: 6
Persist the current work unit before returning control to Eleven.

Agent-Role: Forge
Agent-Thread: queryme-v023-limit-bound
Work-Unit: QUERYME-V023-LIMIT-BOUND
Issue: 6
Evidence: checkpoint-pre-standby
Bastion review of the LIMIT-bound patch (PR #13) found the original fix
still allowed silent truncation: limit=None fell back to a default
ceiling with no error, the same failure mode ADR 001 SS3.3 already
rejects for descriptors that exceed the plafond (cancel entirely,
never return a partial/truncated result — a truncated read looks
complete, e.g. a grants/revocation enumeration cut at the ceiling
reads as 'this right doesn't exist').

limit is now a required field (was: optional with a silent default).
DEFAULT_MAX_LIMIT renamed MAX_LIMIT since there is no default anymore.
Every caller must state its own bound at v0.2.3 bump time ; mypy
strict + pydantic make the omission a compile-time/validation error,
not a runtime surprise.

compiler.py also re-checks the bound directly (model_construct()
bypasses field validators, so this is the last real gate before SQL
is emitted).

Removed 3 agent-protocol staging files (.checkpoint-comment.md,
.pr-body.md, .report.md) that leaked into this public repo's history
via an earlier auto-checkpoint — one of them named the 6 affected
production services in a vulnerability write-up before any were
patched. Added matching .gitignore entries to prevent recurrence.

Refs #6

Agent-Role: forge
Agent-Thread: queryme-v023-limit-bound
Work-Unit: QUERYME-V023-LIMIT-BOUND
Issue: 6
@eleven-by-clodocapeo
eleven-by-clodocapeo Bot merged commit a08a0a4 into main Aug 15, 2026
7 checks passed
@eleven-by-clodocapeo
eleven-by-clodocapeo Bot deleted the forge/queryme-v0.2.3-limit-bound branch August 15, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant