security(http): revoke object URL after downloadRequest click#29
Merged
Goosterhof merged 3 commits intomainfrom Apr 16, 2026
Merged
security(http): revoke object URL after downloadRequest click#29Goosterhof merged 3 commits intomainfrom
Goosterhof merged 3 commits intomainfrom
Conversation
Deploying fs-packages with
|
| Latest commit: |
058eeb0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://160e46cc.fs-packages.pages.dev |
| Branch Preview URL: | https://security-download-request-re.fs-packages.pages.dev |
jasperboerhof
previously approved these changes
Apr 13, 2026
Addresses Sapper M1 finding L7a (downloadRequest object URL not revoked).
Previously downloadRequest created a blob object URL for the download
link but never called URL.revokeObjectURL(), holding a blob reference
until page navigation. In long-running SPAs that trigger many downloads,
this accumulates memory. Not a security issue (classified Low by Sapper),
but a resource leak with a trivial, non-breaking fix.
Fix: call window.URL.revokeObjectURL(link.href) immediately after
link.click(). The download itself captures its own reference during the
synchronous click, so revoking here does not interrupt it.
Not fixing in this PR: previewRequest has the same issue, but its
remediation requires changing the return type from `string` to
{ url, revoke } — a breaking API change deferred to a separate API
design decision.
Bumps fs-http to 0.1.1 (triggers publish workflow on merge). If
security/stream-request-honors-credentials (also 0.1.1) merges first,
this PR will rebase to 0.1.2.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR #28 (streamRequest credentials) merged first and took 0.1.1. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d75d1bc to
c4ccb61
Compare
Resolves GHSA-r4q5-vmmm-2653 (moderate — auth header leak on cross-domain redirects). Transitive dep via axios. Lockfile-only change. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 tasks
jasperboerhof
approved these changes
Apr 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes Sapper M1 finding L7a —
downloadRequestdoesn't revoke the object URL.The bug
downloadRequestcreates a blob URL for the anchor'shrefbut never callsURL.revokeObjectURL(). The browser holds the blob reference until the page navigates away. In long-running SPAs that trigger many downloads, this accumulates memory — not a security issue (classified Low by Sapper), but a resource leak with a one-line fix.The fix
The download itself captures its own blob reference during the synchronous
click(), so revoking immediately after does not interrupt it.Scope note — previewRequest not fixed here
previewRequesthas the same issue, but its remediation requires changing the return type fromPromise<string>toPromise<{ url: string; revoke: () => void }>— a breaking API change for every consumer rendering a preview. That's an API design decision, not a security fix. Deferred to a separate issue.Tests
New case in
downloadRequest:window.URL.revokeObjectURLis called exactly once with the same URL that was assigned tolink.href.Module-level test setup updated: added
revokeObjectURL: vi.fn()to thewindow.URLstub so the new method is callable in all tests.All 8 local gates pass: format, lint, build, typecheck, lint:pkg, 100% coverage, 95.45% mutation (threshold 90%).
Release
Bumps
@script-development/fs-httpto0.1.2.PR #28 (streamRequest credentials) merged first and took
0.1.1.Test plan
checkjob passes🤖 Generated with Claude Code