Security: explorer URL builder interpolates tx hash and address directly with no sanitization tests [SEC-E10] #430
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#430
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
terraExplorer.tsimplementsgetExplorerTxUrl(txHash: string)andgetExplorerAddressUrl(address: string). Both functions interpolate their string argument directly into URL templates: line 44-47 returns${base}${txHash}and line 62-64 returns${base}${address}. No sanitization, encoding, or validation is applied to either argument. The tests interraExplorer.test.tsonly exercise valid well-formed inputs. No test passes adversarial inputs such as ajavascript:prefix,<script>characters, or a path-traversal sequence. If an attacker can influence the displayed tx hash or address (e.g., through a spoofed indexer response), the builder would produce a misleading or potentially injectable URL.What Was Checked
frontend-dapp/src/utils/terraExplorer.ts(read directly):getExplorerTxUrlat line 44-47 returns${base}${txHash}.getExplorerAddressUrlat line 62-64 returns${base}${address}. No validation applied to either argument.frontend-dapp/src/utils/__tests__/terraExplorer.test.ts: all tests useSAMPLE_TX = 'C8845E73934EC9016F751B65F722DBCFBF167C7C5FC4238E5DF39437451412DB'andSAMPLE_ADDRESS = 'terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v'. Valid inputs only. No adversarial input tested.AddressRow.test.tsxorTerraBroadcastPendingLink.test.tsxasserts that renderedhrefattributes are free of unencoded dangerous characters.Expected (per checklist)
Unit tests must verify that malicious or malformed inputs do not produce injectable or misleading explorer URLs. At minimum: a
javascript:prefix in the hash must not produce ajavascript:URL; special characters must be encoded or the function must return null.Actual
The builder accepts any string and interpolates it without change. No test confirms safe behavior under adversarial input. If indexer-sourced data contains a crafted value, the resulting URL is passed unmodified to the renderer.
Evidence
frontend-dapp/src/utils/terraExplorer.tslines 44-47:${base}${txHash}with no sanitizationfrontend-dapp/src/utils/terraExplorer.tslines 62-64:${base}${address}with no sanitizationfrontend-dapp/src/utils/__tests__/terraExplorer.test.ts: SAMPLE_TX and SAMPLE_ADDRESS are valid inputs onlySuggested Fix
Add tests to
frontend-dapp/src/utils/__tests__/terraExplorer.test.tscovering: a txHash prefixed withjavascript:alert(1)asserting the result does not start withjavascript:; a txHash containing<script>characters asserting they are encoded or the function returns null; an empty string asserting a null or clearly invalid result. If React's JSX renderer already blocksjavascript:href values at render time, document this in the test with a comment explaining the defense layer and add a link-rendering assertion inAddressRow.test.tsxorTerraBroadcastPendingLink.test.tsx.Verification Checklist
terraExplorer.test.tshas a test forjavascript:prefix input asserting the output is not ajavascript:URLterraExplorer.test.tshas a test for HTML-special characters in tx hash or addresshrefis safe under adversarial input, or a comment documents the React-layer defenseLabels
security,pre-launchCc: @PlasticDigits
mentioned in commit
7e28b26b96mentioned in merge request !958
mentioned in commit
8a7e7adda1Verified the merged fix (!958, main at
8a7e7add). SEC-E10 is properly closed — the builders now allowlist-validate before interpolating:So a crafted/unvalidated arg never reaches the URL template — no interpolation of attacker input. The adversarial-input tests (#430 / SEC-E10) all pass for both builders: javascript: prefix -> null, HTML-special chars -> null, empty string -> null, path-traversal segments -> null.
One caveat so it's not misread: running the file on a host whose LCD env is 127.0.0.1 shows 2 failing tests, but they're the pre-existing terraExplorer localhost-vs-127.0.0.1 env artifact — the local LCD-fallback URL tests hardcode
localhostwhile the env resolves127.0.0.1. Nothing to do with #430. Proved it: re-run with VITE_TERRA_LCD_URL=http://localhost:1317 -> 15/15 green. The sanitization cases pass regardless of that env var.Good to close from my side. @PlasticDigits — the MR's merged but the issue is still open.
Verification — SEC-E10 / #430
Verified merged fix on
main(MR !958). All acceptance criteria PASS.Checklist
terraExplorer.test.tsrejectsjavascript:prefix (not ajavascript:URL)adversarial input (#430 / SEC-E10)cases forgetExplorerTxUrlandgetExplorerAddressUrlasserttoBeNull()forjavascript:alert(1)and prefixed variantsterraExplorer.test.tsrejects HTML-special characters in tx hash / address<script>-containing hash and address stringsTerraBroadcastPendingLink.test.tsxrenders<span>(no anchor) forjavascript:alert(1)tx hash; comment notes builder returns null before React href sanitization.AddressRow.test.tsxomits explorer link whengetExplorerAddressUrlreturns nullterraExplorer.ts:isSafeExplorerTxHash(/^[0-9a-fA-F]{64}$/) andisSafeExplorerAddress(isValidTerraBech32Address); adversarial suites also cover empty string and path-traversal (../etc/passwd) for tx hashCommands
Result: 3 files, 23 tests — all green (15 in
terraExplorer.test.ts).Implementation review
getExplorerTxUrl/getExplorerAddressUrlvalidate before interpolating into URL templates; crafted input never reaches${base}${…}.mentioned in issue #381
mentioned in issue #424
mentioned in issue #478
mentioned in issue #541
mentioned in issue #570
mentioned in issue #656
mentioned in issue #664