From b5c1b972df7ccd8f48f96d5bbf3245615e65690c Mon Sep 17 00:00:00 2001 From: Grant Cox Date: Thu, 3 Sep 2026 06:06:02 +1000 Subject: [PATCH 1/2] Add Socket Basics security scanning Adds the standard CI wrapper calling ynab-sast-scanner, matching the migrated setup already in place across other repos. Co-Authored-By: Marguerite Martinez Co-Authored-By: Claude Sonnet 5 --- .github/workflows/socket-basics.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/socket-basics.yml diff --git a/.github/workflows/socket-basics.yml b/.github/workflows/socket-basics.yml new file mode 100644 index 000000000..5ddf328a3 --- /dev/null +++ b/.github/workflows/socket-basics.yml @@ -0,0 +1,16 @@ +name: Socket Basics Security Scan + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + socket-basics-security-scan: + # We intentionally run this shared action from @main, not from a pinned sha + # this is because we control the ynab-sast-scanner repo, so there is not a significant risk of malicious changes being pushed. + # Plus, the shared action does use pinned dependencies, and so will be updated fairly often. When we do that, we do not + # want to have to update the sha in every repo that uses this shared action, before such updates apply. + uses: ynab/ynab-sast-scanner/.github/workflows/socket-basics.yml@main + secrets: + SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} + SAST_SUPPRESSIONS_APP_PRIVATE_KEY: ${{ secrets.SAST_SUPPRESSIONS_APP_PRIVATE_KEY }} From c588e534bba5e6171cdc422cb0887029ac044efe Mon Sep 17 00:00:00 2001 From: Grant Cox Date: Thu, 3 Sep 2026 06:40:19 +1000 Subject: [PATCH 2/2] Suppress ruby-unsafe-deserialization on spec Marshal round-trips These marshal specs round-trip our own objects to assert dump/load symmetry; there is no untrusted input to deserialize. --- spec/recurly_v2/adjustment_spec.rb | 2 ++ spec/recurly_v2/billing_info_spec.rb | 2 ++ spec/recurly_v2/credit_payment_spec.rb | 2 ++ spec/recurly_v2/transaction_spec.rb | 2 ++ 4 files changed, 8 insertions(+) diff --git a/spec/recurly_v2/adjustment_spec.rb b/spec/recurly_v2/adjustment_spec.rb index 0c1c531d6..6b26e677a 100644 --- a/spec/recurly_v2/adjustment_spec.rb +++ b/spec/recurly_v2/adjustment_spec.rb @@ -115,6 +115,7 @@ stub_api_request :get, 'adjustments/abcdef1234567890', 'adjustments/show-200-nosub' adjustment = Adjustment.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization adjustment_from_dump = Marshal.load(Marshal.dump(adjustment)) adjustment.instance_variables.must_equal adjustment_from_dump.instance_variables @@ -124,6 +125,7 @@ stub_api_request :get, 'adjustments/abcdef1234567890', 'adjustments/show-200-nosub' adjustment = Adjustment.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization adjustment_from_dump = Marshal.load(Marshal.dump(adjustment)) adjustment.type.must_equal adjustment_from_dump.type diff --git a/spec/recurly_v2/billing_info_spec.rb b/spec/recurly_v2/billing_info_spec.rb index 394cf986f..0cc1d4c5a 100644 --- a/spec/recurly_v2/billing_info_spec.rb +++ b/spec/recurly_v2/billing_info_spec.rb @@ -227,6 +227,7 @@ :get, 'accounts/abcdef1234567890/billing_info', 'billing_info/show-200-bank-account' ) billing_info = BillingInfo.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization billing_info_from_dump = Marshal.load(Marshal.dump(billing_info)) billing_info.instance_variables.must_equal billing_info_from_dump.instance_variables @@ -237,6 +238,7 @@ :get, 'accounts/abcdef1234567890/billing_info', 'billing_info/show-200-bank-account' ) billing_info = BillingInfo.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization billing_info_from_dump = Marshal.load(Marshal.dump(billing_info)) billing_info.type.must_equal billing_info_from_dump.type diff --git a/spec/recurly_v2/credit_payment_spec.rb b/spec/recurly_v2/credit_payment_spec.rb index fb795cb64..1bc3ad198 100644 --- a/spec/recurly_v2/credit_payment_spec.rb +++ b/spec/recurly_v2/credit_payment_spec.rb @@ -33,6 +33,7 @@ stub_api_request :get, 'credit_payments/12345', 'credit_payments/show-200' credit_payment = CreditPayment.find('12345') + # nosemgrep: ruby-unsafe-deserialization credit_payment_from_dump = Marshal.load(Marshal.dump(credit_payment)) credit_payment.instance_variables.must_equal credit_payment_from_dump.instance_variables end @@ -41,6 +42,7 @@ stub_api_request :get, 'credit_payments/12345', 'credit_payments/show-200' credit_payment = CreditPayment.find('12345') + # nosemgrep: ruby-unsafe-deserialization credit_payment_from_dump = Marshal.load(Marshal.dump(credit_payment)) credit_payment.type.must_equal credit_payment_from_dump.type end diff --git a/spec/recurly_v2/transaction_spec.rb b/spec/recurly_v2/transaction_spec.rb index dea2a1bf1..390bcec58 100644 --- a/spec/recurly_v2/transaction_spec.rb +++ b/spec/recurly_v2/transaction_spec.rb @@ -60,6 +60,7 @@ it 'must return the same instance variables' do stub_api_request(:get, 'transactions/abcdef1234567890', 'transactions/show-200') transaction = Transaction.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization transaction_from_dump = Marshal.load(Marshal.dump(transaction)) transaction.instance_variables.must_equal transaction_from_dump.instance_variables @@ -68,6 +69,7 @@ it 'must return the same values' do stub_api_request(:get, 'transactions/abcdef1234567890', 'transactions/show-200') transaction = Transaction.find 'abcdef1234567890' + # nosemgrep: ruby-unsafe-deserialization transaction_from_dump = Marshal.load(Marshal.dump(transaction)) transaction.type.must_equal transaction_from_dump.type