Commit 50a9974
fix(security): resolve the target database identically in authorization and handlers
`verifyPerms` resolved the database an operation targets as
`requestJson.schema ?? requestJson.database`. The handlers resolve it in
`commonUtils.transformReq`, which runs AFTER authorization. The two disagreed in
three ways, each of which let a request be authorized against one target and
executed against another:
1. Neither key present. `operationSchema` was undefined, so `schemaTableMap`
stayed empty; `hasPermissions` iterates that map, so it authorized by vacuous
truth, and `getAttributePermissions` returned an empty map so attribute
permissions went unchecked too. `transformReq` meanwhile defaults to the
default database, and the handler wrote there. Any non-empty role therefore had
unconditional read/write/delete on `data`: verified for insert/update/upsert,
delete, csv_data_load, create_attribute, and all three search_* operations. A
role scoped exclusively to another database read, updated and deleted records in
`data`.
2. `database: 0` (or any falsy-but-present value). `??` kept the `0`, which is not
a database, so the map stayed empty as in (1) — while `transformReq`, which
tests falsy, defaulted to `data` and wrote there. `Joi.number()` is an accepted
type for the field, so `0` arrives validated.
3. Opposite precedence. `verifyPerms` preferred `schema`; `transformReq` prefers
`database`. So `{schema:'data', database:'elsewhere'}` was authorized against
`data` and written to `elsewhere`. This one reaches any named database, not just
the default.
Fix: one resolver, `commonUtils.resolveTargetDatabase`, which `transformReq` now
delegates to, so authorization and the handlers cannot drift again. Falsy rather
than nullish, and `database` over `schema`, matching what the handlers have always
done.
Plus a fail-closed backstop in `verifyPerms`: a named table with an empty
`schemaTableMap` is denied rather than authorized. That is the shape of this whole
bug class, and of the SQL path's GHSA-5c29-q62v-jrwf, whose fix carries the same
guard. With the shared resolver it is unreachable by construction, so no test
covers it; it is there so a future change to target resolution fails safe.
Affected 4.2.0 through 5.2.6. `transformReq`'s default arrived in 4.2.0
(5d5e58f); 4.1 declared `schema` required, so earlier versions are not
exploitable. The vacuous-map behaviour itself dates to ~4.0.8 (76ce6a2) but was
inert until that default existed. 5da23c3 only carried the expression into the
5.x file.
Not affected: REST, MQTT/WebSocket and GraphQL bind the database on the resource
class at path-match time and never take it from the request body. The SQL path is
the same bug class but a separate, already-fixed code path.
Regression coverage in integrationTests/database/full-record-write.test.ts asserts
all three cases, and asserts them in both directions — a denial alone does not
prove resolution, since the backstop also denies an unresolved target, so the role
that DOES hold rights on the default database must still be allowed and its write
must land there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 4c8fa90 commit 50a9974
3 files changed
Lines changed: 180 additions & 7 deletions
File tree
- integrationTests/database
- utility
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| |||
551 | 551 | | |
552 | 552 | | |
553 | 553 | | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
554 | 695 | | |
555 | 696 | | |
556 | 697 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
828 | 828 | | |
829 | 829 | | |
830 | 830 | | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
831 | 849 | | |
832 | 850 | | |
833 | 851 | | |
834 | 852 | | |
835 | 853 | | |
836 | | - | |
837 | | - | |
838 | | - | |
839 | | - | |
840 | | - | |
| 854 | + | |
841 | 855 | | |
842 | 856 | | |
843 | 857 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
674 | 674 | | |
675 | 675 | | |
676 | 676 | | |
677 | | - | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
678 | 686 | | |
679 | 687 | | |
680 | 688 | | |
| |||
801 | 809 | | |
802 | 810 | | |
803 | 811 | | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
804 | 822 | | |
805 | 823 | | |
806 | 824 | | |
| |||
0 commit comments