openai / openai/codex-security
TypeScript contract loader accepts reversed finding line ranges
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 10.8k
- Forks
- 801
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 257
Description
Summary
The canonical TypeScript contract loader accepts a finding location whose endLine is less than its startLine, even though the bundled Python producer rejects that same location before sealing.
This creates a producer/consumer validation mismatch: an externally constructed, correctly resealed completed-scan bundle can load through loadContract() with a line range that Codex Security itself would never finalize.
Reproduction / evidence
Current upstream main at 37bf87a692fc72d41f7312cc48808d699d204fba validates ordinary finding locations in two different ways.
The Python finalizer uses _validate_location() and requires:
end = location.get("endLine", start)
...
if not isinstance(end, int) or end < start:
raise ContractError(...)
The shared JSON schema only constrains startLine and endLine independently to positive integers. The TypeScript validateCanonicalContract() then validates each location path but does not compare the two line numbers.
A deterministic sealed-contract reproduction is:
- copy the bundled
examples/completed-scanfixture; - change the first finding location to
startLine: 41, endLine: 40; - recompute the sealed
findings.jsonSHA-256 inscan-manifest.json; - call
loadContract().
Current behavior: the bundle loads successfully.
Expected behavior: the SDK loader rejects the same reversed line range the producer rejects.
Root cause
The relational endLine >= startLine invariant lives in Python finalization but was not mirrored in the TypeScript canonical-validation pass. JSON Schema Draft 2020-12 does not express this sibling-value comparison in the existing schema without a nonstandard extension.
Suggested fix
During validateCanonicalContract(), reject any ordinary finding location whose defined endLine is less than startLine.
Add a focused regression that mutates and reseals the real bundled completed-scan fixture, verifies the reversed range is rejected, and retains a valid multi-line range control.
Impact
This is contract-integrity correctness. Invalid ranges can reach SDK consumers and downstream source-link/reporting logic even though the canonical producer rejects them, so producer and consumer disagree about what constitutes a valid sealed finding.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with validateCanonicalContract() and loadContract(), then inspect the bundled examples/completed-scan fixture and the existing canonical-validation tests. Reseal a copy with a reversed finding range and verify loading rejects it, while retaining a valid multi-line range control.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100