Skip to content

fix(security): resolve open CodeQL code-scanning alerts#1016

Merged
oskarszoon merged 1 commit into
bsv-blockchain:mainfrom
oskarszoon:fix/codeql-alerts
Jun 4, 2026
Merged

fix(security): resolve open CodeQL code-scanning alerts#1016
oskarszoon merged 1 commit into
bsv-blockchain:mainfrom
oskarszoon:fix/codeql-alerts

Conversation

@oskarszoon

@oskarszoon oskarszoon commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

What

Resolves the 11 open CodeQL code-scanning alerts.

Alert(s) File Fix
#90 #91 #117 services/asset/httpimpl/{GetBlocks,GetNearestForkHeights}.go Bound-check the intuint32 conversion before casting (reject out-of-range offset/range with HTTP 400). Prevents silent truncation/wrap-around.
#113 daemon/daemon_memlimit.go formatBytes now takes uint64, removing the unchecked int64(limit) narrowing of the cgroup memory limit. Log output unchanged.
#79 #81 #83 ui/dashboard/src/internal/stores/p2pStore.ts Reject __proto__/constructor/prototype as peer_id keys before any plain-object write; guard the for…in with hasOwnProperty. Prevents prototype pollution from WebSocket data.
#2 #4 ui/dashboard/src/internal/utils/urlUtils.ts Removed the dead sanitizeUrl function entirely (no callers, no tests). Its broken script-tag regex was the source of both alerts; validateUrl (the function actually in use) is untouched.
#1 services/asset/centrifuge_impl/client/index.html innerHTMLtextContent in drawText — real DOM XSS from server-controlled push data. white-space: pre preserves rendering.
#42 util/grpc_helper.go No behaviour change. InsecureSkipVerify is reached only via the explicit, operator-opted-in SecurityLevel==1 (default is 0). Added godoc/comment warning that level 1 leaves the server certificate unverified (MITM). Alert dismissed on GitHub as intentional/config-gated.

Verification

  • go build + go vet on affected packages (daemon, services/asset/httpimpl, util) — clean
  • go test (targeted: TestFormatBytes, TestParseCgroupMemoryValue, GetBlocks, LimitOffset, NearestForkHeights) — pass
  • svelte-check — 0 errors (798 files; 14 pre-existing warnings, none in changed files)
  • gofmt -l — clean

Notes

  • Behaviour changes are limited to rejecting previously-unsound inputs: negative/oversized range/offset now return HTTP 400 instead of silently wrapping; WS messages with a __proto__-style peer_id are dropped. No legitimate request is affected.
  • [TEST] Chaos testing - Scenario 02 Kafka Broker Failure #42 is documentation-only plus a GitHub dismissal; the weak-TLS mode itself is intentional and gated behind explicit operator config.
  • 32-bit nit (non-blocking): the x > math.MaxUint32 guards won't compile on 32-bit (untyped-const overflow). Moot — Teranode builds only amd64/arm64 and the asset pkg requires 64-bit cgo.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Status: Complete


Security Fixes Analysis:

All 11 CodeQL alerts have been properly addressed. The fixes are correct, minimal, and well-documented:

Integer Conversion Safety (alerts #90, #91, #117, #113)

  • GetBlocks.go:131: Added math.MaxUint32 check before casting int→uint32
  • GetNearestForkHeights.go:58: Added range validation for range parameter
  • daemon_memlimit.go:143: Changed formatBytes to accept uint64, eliminating unsafe narrowing
  • All conversions now reject out-of-range values with HTTP 400

Prototype Pollution (alerts #79, #81, #83)

  • p2pStore.ts:30-35: Added isSafeKey() guard rejecting proto, constructor, prototype
  • Applied at all three peer_id write points (lines 186, 257, 315)
  • Added hasOwnProperty check in for...in loop (line 57)

Dead Code Removal (alerts #2, #4)

  • urlUtils.ts: Removed unused sanitizeUrl function (no callers, no tests)
  • Only validateUrl is used in production code (login page)

XSS Fix (alert #1)

  • index.html:107: Changed innerHTML → textContent
  • white-space: pre CSS preserves formatting

Documentation-Only (alert #42)

  • grpc_helper.go:72,385-387,421-426: Enhanced comments explaining SecurityLevel 1 MITM vulnerability
  • Behavior unchanged; alert dismissed on GitHub as intentional

No Issues Found

The PR demonstrates careful security engineering. Fixes are minimal, behavior changes are limited to rejecting invalid input, and documentation is thorough.

Address the open CodeQL code-scanning alerts:

- httpimpl: bound-check int->uint32 conversions before casting in
  GetBlocks (offset) and GetNearestForkHeights (range) to prevent
  truncation/wrap-around (go/incorrect-integer-conversion, bsv-blockchain#90 bsv-blockchain#91 bsv-blockchain#117)
- daemon: change formatBytes to take uint64, removing the unchecked
  int64(limit) narrowing of the cgroup memory limit (bsv-blockchain#113)
- dashboard p2pStore: reject __proto__/constructor/prototype peer_id
  keys before any plain-object write to prevent prototype pollution
  from WebSocket data (bsv-blockchain#79 bsv-blockchain#81 bsv-blockchain#83)
- dashboard urlUtils: remove the dead sanitizeUrl function entirely
  (no callers, no tests); its broken script-tag regex was the source
  of the alerts (js/bad-tag-filter, js/incomplete-multi-character-sanitization, bsv-blockchain#2 bsv-blockchain#4)
- centrifuge client: use textContent instead of innerHTML in drawText
  to fix DOM XSS from server-controlled push data (bsv-blockchain#1)
- grpc_helper: document that SecurityLevel 1 leaves the server cert
  unverified (MITM); behaviour unchanged, bsv-blockchain#42 is an intentional
  config-gated mode dismissed on GitHub
@oskarszoon oskarszoon force-pushed the fix/codeql-alerts branch from 8e22229 to e4cb84f Compare June 2, 2026 10:19
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Benchmark Comparison Report

Baseline: main (unknown)

Current: PR-1016 (421da60)

Summary

  • Regressions: 0
  • Improvements: 0
  • Unchanged: 144
  • Significance level: p < 0.05
All benchmark results (sec/op)
Benchmark Baseline Current Change p-value
_NewBlockFromBytes-4 1.700µ 1.614µ ~ 0.100
SplitSyncedParentMap_SetIfNotExists/256_buckets-4 71.31n 71.10n ~ 0.200
SplitSyncedParentMap_SetIfNotExists/16_buckets-4 71.35n 71.25n ~ 1.000
SplitSyncedParentMap_SetIfNotExists/1_bucket-4 71.24n 71.15n ~ 0.700
SplitSyncedParentMap_ConcurrentSetIfNotExists/256_buckets... 33.15n 32.58n ~ 0.600
SplitSyncedParentMap_ConcurrentSetIfNotExists/16_buckets_... 55.59n 56.43n ~ 0.400
SplitSyncedParentMap_ConcurrentSetIfNotExists/1_bucket_pa... 127.7n 135.7n ~ 0.100
MiningCandidate_Stringify_Short-4 219.3n 218.4n ~ 0.700
MiningCandidate_Stringify_Long-4 1.625µ 1.618µ ~ 0.100
MiningSolution_Stringify-4 857.4n 849.6n ~ 0.100
BlockInfo_MarshalJSON-4 1.749µ 1.782µ ~ 0.100
NewFromBytes-4 144.8n 126.0n ~ 0.100
AddTxBatchColumnar_Validation-4 2.560µ 2.500µ ~ 0.400
OffsetValidationLoop-4 545.0n 554.8n ~ 0.400
Mine_EasyDifficulty-4 67.01µ 66.92µ ~ 1.000
Mine_WithAddress-4 6.973µ 7.626µ ~ 0.700
BlockAssembler_AddTx-4 0.02709n 0.02674n ~ 1.000
AddNode-4 10.76 10.68 ~ 0.400
AddNodeWithMap-4 11.21 11.25 ~ 0.700
DirectSubtreeAdd/4_per_subtree-4 60.44n 59.25n ~ 0.400
DirectSubtreeAdd/64_per_subtree-4 31.87n 31.38n ~ 0.700
DirectSubtreeAdd/256_per_subtree-4 30.59n 30.42n ~ 0.700
DirectSubtreeAdd/1024_per_subtree-4 29.38n 29.16n ~ 0.100
DirectSubtreeAdd/2048_per_subtree-4 28.89n 28.75n ~ 0.100
SubtreeProcessorAdd/4_per_subtree-4 293.4n 284.7n ~ 0.100
SubtreeProcessorAdd/64_per_subtree-4 280.5n 281.5n ~ 0.400
SubtreeProcessorAdd/256_per_subtree-4 282.3n 282.1n ~ 1.000
SubtreeProcessorAdd/1024_per_subtree-4 277.5n 277.7n ~ 0.700
SubtreeProcessorAdd/2048_per_subtree-4 274.4n 278.5n ~ 0.200
SubtreeProcessorRotate/4_per_subtree-4 280.5n 275.8n ~ 0.700
SubtreeProcessorRotate/64_per_subtree-4 276.9n 276.2n ~ 0.400
SubtreeProcessorRotate/256_per_subtree-4 273.9n 277.4n ~ 0.400
SubtreeProcessorRotate/1024_per_subtree-4 277.4n 281.2n ~ 0.200
SubtreeNodeAddOnly/4_per_subtree-4 54.64n 54.70n ~ 0.400
SubtreeNodeAddOnly/64_per_subtree-4 34.35n 34.43n ~ 0.400
SubtreeNodeAddOnly/256_per_subtree-4 33.29n 33.54n ~ 0.100
SubtreeNodeAddOnly/1024_per_subtree-4 32.60n 32.80n ~ 0.100
SubtreeCreationOnly/4_per_subtree-4 116.0n 115.1n ~ 0.200
SubtreeCreationOnly/64_per_subtree-4 404.5n 407.7n ~ 0.400
SubtreeCreationOnly/256_per_subtree-4 1.356µ 1.372µ ~ 0.200
SubtreeCreationOnly/1024_per_subtree-4 4.441µ 4.477µ ~ 0.400
SubtreeCreationOnly/2048_per_subtree-4 8.202µ 8.276µ ~ 1.000
SubtreeProcessorOverheadBreakdown/64_per_subtree-4 279.5n 272.7n ~ 0.100
SubtreeProcessorOverheadBreakdown/1024_per_subtree-4 278.3n 277.9n ~ 0.700
ParallelGetAndSetIfNotExists/1k_nodes-4 2.203m 2.283m ~ 0.100
ParallelGetAndSetIfNotExists/10k_nodes-4 5.397m 5.690m ~ 0.100
ParallelGetAndSetIfNotExists/50k_nodes-4 7.581m 8.248m ~ 0.100
ParallelGetAndSetIfNotExists/100k_nodes-4 10.53m 10.99m ~ 0.100
SequentialGetAndSetIfNotExists/1k_nodes-4 1.962m 1.919m ~ 0.100
SequentialGetAndSetIfNotExists/10k_nodes-4 4.807m 4.433m ~ 0.100
SequentialGetAndSetIfNotExists/50k_nodes-4 12.74m 12.40m ~ 0.200
SequentialGetAndSetIfNotExists/100k_nodes-4 23.13m 22.29m ~ 0.400
ProcessOwnBlockSubtreeNodesParallel/1k_nodes-4 2.281m 2.276m ~ 0.700
ProcessOwnBlockSubtreeNodesParallel/10k_nodes-4 8.504m 8.364m ~ 0.100
ProcessOwnBlockSubtreeNodesParallel/100k_nodes-4 13.74m 13.84m ~ 1.000
ProcessOwnBlockSubtreeNodesSequential/1k_nodes-4 1.988m 2.013m ~ 0.700
ProcessOwnBlockSubtreeNodesSequential/10k_nodes-4 8.169m 8.364m ~ 0.400
ProcessOwnBlockSubtreeNodesSequential/100k_nodes-4 44.09m 44.70m ~ 1.000
DiskTxMap_SetIfNotExists-4 3.638µ 3.815µ ~ 0.200
DiskTxMap_SetIfNotExists_Parallel-4 3.345µ 3.424µ ~ 0.100
DiskTxMap_ExistenceOnly-4 319.5n 319.0n ~ 1.000
Queue-4 186.2n 186.2n ~ 1.000
AtomicPointer-4 3.251n 3.253n ~ 0.700
ReorgOptimizations/DedupFilterPipeline/Old/10K-4 815.8µ 819.3µ ~ 1.000
ReorgOptimizations/DedupFilterPipeline/New/10K-4 778.9µ 804.8µ ~ 0.100
ReorgOptimizations/AllMarkFalse/Old/10K-4 112.5µ 102.7µ ~ 0.100
ReorgOptimizations/AllMarkFalse/New/10K-4 64.12µ 64.19µ ~ 1.000
ReorgOptimizations/HashSlicePool/Old/10K-4 52.54µ 61.48µ ~ 0.700
ReorgOptimizations/HashSlicePool/New/10K-4 10.96µ 11.24µ ~ 0.300
ReorgOptimizations/NodeFlags/Old/10K-4 4.475µ 5.230µ ~ 0.100
ReorgOptimizations/NodeFlags/New/10K-4 1.468µ 2.350µ ~ 0.100
ReorgOptimizations/DedupFilterPipeline/Old/100K-4 9.291m 9.387m ~ 0.700
ReorgOptimizations/DedupFilterPipeline/New/100K-4 9.298m 9.146m ~ 0.200
ReorgOptimizations/AllMarkFalse/Old/100K-4 1.089m 1.139m ~ 0.100
ReorgOptimizations/AllMarkFalse/New/100K-4 706.3µ 705.1µ ~ 0.700
ReorgOptimizations/HashSlicePool/Old/100K-4 600.4µ 471.4µ ~ 0.200
ReorgOptimizations/HashSlicePool/New/100K-4 214.4µ 212.0µ ~ 0.400
ReorgOptimizations/NodeFlags/Old/100K-4 47.88µ 46.39µ ~ 0.400
ReorgOptimizations/NodeFlags/New/100K-4 16.70µ 16.95µ ~ 0.700
TxMapSetIfNotExists-4 49.31n 49.24n ~ 0.800
TxMapSetIfNotExistsDuplicate-4 41.49n 41.37n ~ 0.100
ChannelSendReceive-4 605.3n 595.3n ~ 1.000
CalcBlockWork-4 526.7n 498.7n ~ 1.000
CalculateWork-4 664.5n 656.6n ~ 0.200
BuildBlockLocatorString_Helpers/Size_10-4 1.358µ 1.353µ ~ 0.700
BuildBlockLocatorString_Helpers/Size_100-4 13.03µ 12.87µ ~ 0.100
BuildBlockLocatorString_Helpers/Size_1000-4 150.3µ 129.4µ ~ 0.400
CatchupWithHeaderCache-4 104.6m 105.1m ~ 0.200
_prepareTxsPerLevel-4 408.1m 408.7m ~ 0.700
_prepareTxsPerLevelOrdered-4 4.095m 4.277m ~ 0.700
_prepareTxsPerLevel_Comparison/Original-4 411.3m 413.1m ~ 1.000
_prepareTxsPerLevel_Comparison/Optimized-4 3.936m 4.130m ~ 0.200
SubtreeSizes/10k_tx_4_per_subtree-4 1.350m 1.342m ~ 0.700
SubtreeSizes/10k_tx_16_per_subtree-4 322.5µ 324.8µ ~ 1.000
SubtreeSizes/10k_tx_64_per_subtree-4 79.05µ 74.87µ ~ 0.100
SubtreeSizes/10k_tx_256_per_subtree-4 18.96µ 18.76µ ~ 0.100
SubtreeSizes/10k_tx_512_per_subtree-4 9.620µ 9.333µ ~ 0.200
SubtreeSizes/10k_tx_1024_per_subtree-4 4.693µ 4.598µ ~ 0.200
SubtreeSizes/10k_tx_2k_per_subtree-4 2.367µ 2.307µ ~ 0.100
BlockSizeScaling/10k_tx_64_per_subtree-4 74.81µ 73.69µ ~ 0.700
BlockSizeScaling/10k_tx_256_per_subtree-4 18.93µ 18.55µ ~ 0.200
BlockSizeScaling/10k_tx_1024_per_subtree-4 4.689µ 4.621µ ~ 0.100
BlockSizeScaling/50k_tx_64_per_subtree-4 400.1µ 390.7µ ~ 0.700
BlockSizeScaling/50k_tx_256_per_subtree-4 94.59µ 93.32µ ~ 0.100
BlockSizeScaling/50k_tx_1024_per_subtree-4 23.27µ 23.25µ ~ 1.000
SubtreeAllocations/small_subtrees_exists_check-4 160.0µ 158.5µ ~ 0.400
SubtreeAllocations/small_subtrees_data_fetch-4 163.5µ 161.9µ ~ 1.000
SubtreeAllocations/small_subtrees_full_validation-4 326.6µ 324.8µ ~ 0.700
SubtreeAllocations/medium_subtrees_exists_check-4 9.570µ 9.608µ ~ 0.700
SubtreeAllocations/medium_subtrees_data_fetch-4 9.657µ 9.734µ ~ 0.400
SubtreeAllocations/medium_subtrees_full_validation-4 19.12µ 18.90µ ~ 0.100
SubtreeAllocations/large_subtrees_exists_check-4 2.281µ 2.271µ ~ 1.000
SubtreeAllocations/large_subtrees_data_fetch-4 2.358µ 2.359µ ~ 0.700
SubtreeAllocations/large_subtrees_full_validation-4 4.760µ 4.739µ ~ 0.700
_BufferPoolAllocation/16KB-4 3.887µ 4.379µ ~ 1.000
_BufferPoolAllocation/32KB-4 8.596µ 8.710µ ~ 1.000
_BufferPoolAllocation/64KB-4 16.52µ 16.69µ ~ 0.700
_BufferPoolAllocation/128KB-4 32.99µ 33.40µ ~ 0.100
_BufferPoolAllocation/512KB-4 126.6µ 122.6µ ~ 1.000
_BufferPoolConcurrent/32KB-4 19.36µ 20.04µ ~ 0.700
_BufferPoolConcurrent/64KB-4 30.34µ 29.86µ ~ 0.400
_BufferPoolConcurrent/512KB-4 158.7µ 147.6µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/16KB-4 663.1µ 639.2µ ~ 0.700
_SubtreeDeserializationWithBufferSizes/32KB-4 654.4µ 703.0µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/64KB-4 658.4µ 693.9µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/128KB-4 666.0µ 701.7µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/512KB-4 662.5µ 631.5µ ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/16KB-4 37.74m 37.33m ~ 0.700
_SubtreeDataDeserializationWithBufferSizes/32KB-4 37.63m 37.12m ~ 0.200
_SubtreeDataDeserializationWithBufferSizes/64KB-4 37.49m 37.07m ~ 0.100
_SubtreeDataDeserializationWithBufferSizes/128KB-4 37.33m 36.83m ~ 0.400
_SubtreeDataDeserializationWithBufferSizes/512KB-4 37.28m 36.83m ~ 0.400
_PooledVsNonPooled/Pooled-4 842.4n 670.1n ~ 0.100
_PooledVsNonPooled/NonPooled-4 8.354µ 7.667µ ~ 0.100
_MemoryFootprint/Current_512KB_32concurrent-4 8.037µ 7.752µ ~ 0.700
_MemoryFootprint/Proposed_32KB_32concurrent-4 13.254µ 9.890µ ~ 0.100
_MemoryFootprint/Alternative_64KB_32concurrent-4 11.090µ 9.721µ ~ 0.100
StoreBlock_Sequential/BelowCSVHeight-4 330.4µ 331.0µ ~ 0.100
StoreBlock_Sequential/AboveCSVHeight-4 331.7µ 332.0µ ~ 0.700
GetUtxoHashes-4 281.0n 282.3n ~ 1.000
GetUtxoHashes_ManyOutputs-4 47.01µ 45.75µ ~ 0.100
_NewMetaDataFromBytes-4 214.9n 217.1n ~ 0.700
_Bytes-4 401.9n 394.4n ~ 0.200
_MetaBytes-4 141.0n 141.1n ~ 0.600

Threshold: >10% with p < 0.05 | Generated: 2026-06-02 10:33 UTC

@sonarqubecloud

sonarqubecloud Bot commented Jun 2, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
63.6% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@oskarszoon oskarszoon self-assigned this Jun 2, 2026

@ordishs ordishs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped security PR. Each CodeQL alert is fixed with a minimal, correct change and no collateral refactoring:

  • GetBlocks/GetNearestForkHeights int→uint32 bound checks compose correctly with existing non-negative validation.
  • formatBytes(uint64) removes all narrowing; upstream guards keep every cast safe.
  • p2pStore proto/constructor/prototype denylist + hasOwnProperty guard; no false positives on base58 peer IDs.
  • Dead sanitizeUrl removal and innerHTML→textContent are strictly correct.
  • grpc_helper is doc-only; InsecureSkipVerify stays gated behind opt-in SecurityLevel==1.

Verified go vet clean on daemon, services/asset/httpimpl, util. 32-bit compile caveat is moot (amd64/arm64 only) and was self-flagged. Approve.

@oskarszoon oskarszoon merged commit ea29739 into bsv-blockchain:main Jun 4, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants