Add length validations for SHA columns to composer packages related tables
🎯 What does this MR do and why?
Add length validations for composer metadata SHA columns to prevent storing arbitrarily large data.
- Add a 64-character length limit validation to
target_shaand a 255-character length limit validation toversion_cache_shacolumns - Protect both
Packages::Composer::MetadatumandPackages::Composer::Packagemodels - Include both application-level validations and database-level check constraints
Changelog: changed
🗄️ Database migrations
This MR adds database-level check constraints to two tables:
packages_composer_metadata
⬆️ Up
> gdk rails db:migrate:up:main VERSION=20260203174943
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 43260
main: == 20260203174943 AddCheckConstraintToPackagesComposerMetadata: migrating =====
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute("ALTER TABLE packages_composer_metadata\nADD CONSTRAINT check_packages_composer_metadata_target_sha_max_length\nCHECK ( octet_length(target_sha) <= 64 )\nNOT VALID;\n")
main: -> 0.0030s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute("ALTER TABLE packages_composer_metadata\nADD CONSTRAINT check_packages_composer_metadata_version_cache_sha_max_length\nCHECK ( octet_length(version_cache_sha) <= 255 )\nNOT VALID;\n")
main: -> 0.0011s
main: == 20260203174943 AddCheckConstraintToPackagesComposerMetadata: migrated (0.0917s)
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 43260
⬇️ Down
> gdk rails db:migrate:down:main VERSION=20260203174943
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 42335
main: == 20260203174943 AddCheckConstraintToPackagesComposerMetadata: reverting =====
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute(" ALTER TABLE packages_composer_metadata\n DROP CONSTRAINT IF EXISTS check_packages_composer_metadata_target_sha_max_length\n")
main: -> 0.0007s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute(" ALTER TABLE packages_composer_metadata\n DROP CONSTRAINT IF EXISTS check_packages_composer_metadata_version_cache_sha_max_length\n")
main: -> 0.0005s
main: == 20260203174943 AddCheckConstraintToPackagesComposerMetadata: reverted (0.0437s)
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 42335
packages_composer_packages
⬆️ Up
> gdk rails db:migrate:up:main VERSION=20260203174944
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 43926
main: == 20260203174944 AddCheckConstraintToPackagesComposerPackages: migrating =====
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute("ALTER TABLE packages_composer_packages\nADD CONSTRAINT check_packages_composer_packages_target_sha_max_length\nCHECK ( octet_length(target_sha) <= 64 )\nNOT VALID;\n")
main: -> 0.0013s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute("ALTER TABLE packages_composer_packages\nADD CONSTRAINT check_packages_composer_packages_version_cache_sha_max_length\nCHECK ( octet_length(version_cache_sha) <= 255 )\nNOT VALID;\n")
main: -> 0.0011s
main: == 20260203174944 AddCheckConstraintToPackagesComposerPackages: migrated (0.1193s)
main: == [advisory_lock_connection] object_id: 134200, pg_backend_pid: 43926
⬇️ Down
> gdk rails db:migrate:down:main VERSION=20260203174944
main: == [advisory_lock_connection] object_id: 134180, pg_backend_pid: 41324
main: == 20260203174944 AddCheckConstraintToPackagesComposerPackages: reverting =====
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute(" ALTER TABLE packages_composer_packages\n DROP CONSTRAINT IF EXISTS check_packages_composer_packages_target_sha_max_length\n")
main: -> 0.0059s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute(" ALTER TABLE packages_composer_packages\n DROP CONSTRAINT IF EXISTS check_packages_composer_packages_version_cache_sha_max_length\n")
main: -> 0.0011s
main: == 20260203174944 AddCheckConstraintToPackagesComposerPackages: reverted (0.0736s)
main: == [advisory_lock_connection] object_id: 134180, pg_backend_pid: 41324
📚 References
- #585485
- Related to #368465
📸 Screenshots or screen recordings
N/A
🧪 How to set up and validate locally
-
Open Rails console:
gdk rails c -
Test
Packages::Composer::Metadatumvalidation:package_sti = FactoryBot.create(:composer_package_sti) metadatum = FactoryBot.create(:composer_metadatum, package: package_sti) metadatum.target_sha = 'A' * 65 metadatum.valid? # Should be false metadatum.reload metadatum.version_cache_sha = 'B' * 256 metadatum.valid? # Should be false -
Test
Packages::Composer::Packagevalidation:package = Packages::Composer::Package.first package.target_sha = 'C' * 65 package.valid? # Should be false package.reload package.version_cache_sha = 'D' * 256 package.valid? # Should be false
✅ MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Edited by Sylvia Shen