From 4b32bd044ece834d4c3f618f0ca3d0430718296f Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 28 Aug 2023 15:32:19 +0400 Subject: [PATCH 1/2] Fix: security issue #21 --- internal/postgres/domains/storage.go | 118 ++++++++++++--------------- 1 file changed, 54 insertions(+), 64 deletions(-) diff --git a/internal/postgres/domains/storage.go b/internal/postgres/domains/storage.go index 76482d569..7ea7dae66 100644 --- a/internal/postgres/domains/storage.go +++ b/internal/postgres/domains/storage.go @@ -2,8 +2,6 @@ package domains import ( "errors" - "html/template" - "strings" "github.com/baking-bad/bcdhub/internal/models/bigmapdiff" "github.com/baking-bad/bcdhub/internal/models/contract" @@ -44,29 +42,6 @@ func (storage *Storage) BigMapDiffs(lastID, size int64) (result []domains.BigMap return } -var sameTemplate = template.Must( - template.New("same").Parse( - `select * from ( - select * from ( - {{- range $index, $network := .Networks }} - {{- if (gt $index 0) }} - union all - {{- end}} - select '{{ $network }}' as network, contracts.*, accounts.address as account__address from {{ $network }}.contracts - join {{ $network }}.accounts on contracts.account_id = accounts.id - left join {{$network}}.scripts as alpha on alpha.id = contracts.alpha_id - left join {{$network}}.scripts as babylon on babylon.id = contracts.babylon_id - left join {{$network}}.scripts as jakarta on jakarta.id = contracts.jakarta_id - where (alpha.hash = '{{$.Hash}}' or babylon.hash = '{{$.Hash}}' or jakarta.hash = '{{$.Hash}}') - {{end}} - ) as q - where NOT (network = '{{.network}}' and id = {{.ID}}) - ) as same - limit {{.limit}} - offset {{.offset}}`, - ), -) - // Same - func (storage *Storage) Same(network string, c contract.Contract, limit, offset int, availiableNetworks ...string) ([]domains.Same, error) { if limit < 1 || limit > 10 { @@ -86,62 +61,77 @@ func (storage *Storage) Same(network string, c contract.Contract, limit, offset return nil, errors.New("invalid contract script") } - data := map[string]any{ - "ID": c.ID, - "Hash": script.Hash, - "limit": limit, - "offset": offset, - "network": network, - "Networks": availiableNetworks, - } + var union *pg.Query + for i, value := range availiableNetworks { + schema := pg.Safe(value) + + query := storage.DB.Model(). + TableExpr("?.contracts", schema). + ColumnExpr("? as network", value). + ColumnExpr("contracts.*"). + ColumnExpr("accounts.address as account__address"). + Join("LEFT JOIN ?.accounts on contracts.account_id = accounts.id", schema). + Join("LEFT JOIN ?.scripts as alpha on alpha.id = contracts.alpha_id", schema). + Join("LEFT JOIN ?.scripts as babylon on babylon.id = contracts.babylon_id", schema). + Join("LEFT JOIN ?.scripts as jakarta on jakarta.id = contracts.jakarta_id", schema). + Where("alpha.hash = ?", script.Hash). + WhereOr("babylon.hash = ?", script.Hash). + WhereOr("jakarta.hash = ?", script.Hash) + + if value == network { + query.Where("contracts.id != ?", c.ID) + } - var buffer strings.Builder - if err := sameTemplate.Execute(&buffer, data); err != nil { - return nil, err + if i == 0 { + union = query + } else { + union = union.UnionAll(query) + } } var same []domains.Same - _, err := storage.DB.Query(&same, buffer.String()) + err := storage.DB.Model(). + TableExpr("(?) as same", union). + Limit(limit). + Offset(offset). + Select(&same) return same, err } -var sameCountTemplate = template.Must( - template.New("sameCount").Parse( - `select sum(c) from ( - {{- range $index, $network := .Networks }} - {{- if (gt $index 0) }} - union all - {{- end}} - select count(*) as c from {{$network}}.contracts - left join {{$network}}.scripts as alpha on alpha.id = contracts.alpha_id - left join {{$network}}.scripts as babylon on babylon.id = contracts.babylon_id - left join {{$network}}.scripts as jakarta on jakarta.id = contracts.jakarta_id - where (alpha.hash = '{{$.Hash}}' or babylon.hash = '{{$.Hash}}' or jakarta.hash = '{{$.Hash}}') - {{end}} - ) as same`, - ), -) - // SameCount - func (storage *Storage) SameCount(c contract.Contract, availiableNetworks ...string) (int, error) { + if len(availiableNetworks) == 0 { + return 0, nil + } + script := c.CurrentScript() if script == nil { return 0, errors.New("invalid contract script") } - data := map[string]any{ - "ID": c.ID, - "Hash": script.Hash, - "Networks": availiableNetworks, - } - - var buffer strings.Builder - if err := sameCountTemplate.Execute(&buffer, data); err != nil { - return 0, err + var union *pg.Query + for i, value := range availiableNetworks { + schema := pg.Safe(value) + + query := storage.DB.Model(). + TableExpr("?.contracts", schema). + ColumnExpr("count(*) as c"). + Join("LEFT JOIN ?.scripts as alpha on alpha.id = contracts.alpha_id", schema). + Join("LEFT JOIN ?.scripts as babylon on babylon.id = contracts.babylon_id", schema). + Join("LEFT JOIN ?.scripts as jakarta on jakarta.id = contracts.jakarta_id", schema). + Where("alpha.hash = ?", script.Hash). + WhereOr("babylon.hash = ?", script.Hash). + WhereOr("jakarta.hash = ?", script.Hash) + + if i == 0 { + union = query + } else { + union = union.UnionAll(query) + } } var count int - if _, err := storage.DB.QueryOne(pg.Scan(&count), buffer.String()); err != nil { + if err := storage.DB.Model().ColumnExpr("sum(c)").TableExpr("(?) as same", union).Select(&count); err != nil { if errors.Is(err, pg.ErrNoRows) { return 0, nil } From 17c0ee7858f22e7ae4d9d5d93e31553a5fab2708 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 28 Aug 2023 15:42:30 +0400 Subject: [PATCH 2/2] Remove security scan from actions --- .github/workflows/tests_master.yml | 18 ------------------ .github/workflows/tests_pr.yml | 18 ------------------ 2 files changed, 36 deletions(-) diff --git a/.github/workflows/tests_master.yml b/.github/workflows/tests_master.yml index f8522deaa..7b220ef05 100644 --- a/.github/workflows/tests_master.yml +++ b/.github/workflows/tests_master.yml @@ -41,21 +41,3 @@ jobs: run: | go mod download go test ./... - security: - name: CodeQL security analyzer - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: 'go' - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/tests_pr.yml b/.github/workflows/tests_pr.yml index a8682e9b5..aa203426b 100644 --- a/.github/workflows/tests_pr.yml +++ b/.github/workflows/tests_pr.yml @@ -40,22 +40,4 @@ jobs: run: | go mod download go test ./... - security: - name: CodeQL security analyzer - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: 'go' - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2