Impulse Info
Every ticker in your timeline becomes a buy button. Research it, chart it and buy it inside the post, on Robinhood Chain, Ethereum, Base or Solana.
TrustNet Score
The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.
Real-Time Threat Detection
Real-time threat detection, powered by Cyvers.io,
is currently not
activated
for this project.
This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks.
For more information, click here.
Security Assessments
Summary and Final Words
No crucial issues found
The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.
Contract is upgradeable
The contract uses a proxy pattern or similar mechanism, enabling future upgrades. This can introduce risks if the upgrade mechanism is not securely managed.
Scope of Work
This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.
The auditing process consists of the following systematic steps:
- Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
- Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
- Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
- Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
- Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
- Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
- Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.
A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.
Final Words
The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.
Security Analysis Statement
Application Analysis
Impulse Wallet 2.5.0 is a Chrome Manifest V3 browser extension that operates as a non-custodial wallet: it generates and stores private keys on the user's own device, encrypts them at rest under a password the user chooses, signs transactions locally, and builds its own swap transactions across four supported chains without depending on a backend service. Around that core it ships a trading interface, a token safety panel, holder and market data screens, and a content script that injects wallet controls into a social media site.
This engagement was a re-audit of the 2.5.0 source against the findings raised on 2.4.0. Every issue from the previous report was re-examined against the new code, the changed and new files were read in full, and the parts of the codebase that the fixes touched were re-traced across call boundaries. The work was carried out by reading the source directly, supported by a review of the dependency manifest and its lock file and a pattern review of the source tree driven by rules written specifically for wallet anti-patterns. Each conclusion was confirmed by reading the code at the cited location, and the delivered remediation notes were treated as claims to be checked rather than as evidence.
The picture has improved substantially and it is worth stating plainly. The boundary between the user's intent and the transaction that is actually signed, which did not exist in 2.4.0, now exists: all signing passes through a single validation step, and both trade surfaces show the user the expected output, the minimum they will accept and the network before anything is signed. Twenty-two of the thirty-seven earlier issues are fully resolved and verified in the code, including all three of the critical items in the sense that each has been addressed at its root. Two matters hold the verdict short of a clean pass. The trade guard for the Solana path still measures only the change in the user's native balance, so a routing service that turned hostile could still move the user's entire token position while spending only fees and pass every check. And the dependency lock file was not regenerated after the manifest was changed, so the version pins added for the signing and derivation packages are not actually in force and a clean install from the delivered files does not succeed. The verdict is a conditional pass, subject to closing those two items.
Ownership Privileges
Custody of the keys rests entirely with the user. No key material leaves the device, no handler in the extension returns a key to a caller, no key or password is ever written to a log, and no party other than the user can authorise a transaction. What that guarantee does not describe is how much authority the extension itself holds over those keys and funds once a session is unlocked. The extension retains full privileges including:
- Decryption of every private key and recovery phrase in the vault for the duration of an unlocked session, with the decrypted material held in the browser's memory-backed session area rather than written to disk, and cleared when the wallet locks.
- Signature and broadcast of any transaction on any supported chain, now preceded by a validation step that refuses a bundle whose approval names an untrusted spender or whose call targets an untrusted contract, and by a confirmation screen that shows the destination, the expected and minimum output and the chain before anything is signed.
- Grant of spending allowances over the user's tokens in favour of the router contracts the trade engine selects, now scoped to the amount the trade requires and time-boxed to the life of the trade rather than issued as an unlimited and long-lived grant, and surfaced to the user through the confirmation step.
- Acceptance of a transaction body constructed by a third-party routing service on the Solana path and signature of it as received. The check now refuses the trade when it cannot be simulated, but it still measures only the change in the user's native balance, so a response that moves the user's whole token position while spending only fees is not detected.
- No ability to move funds while the wallet is locked, because the keys exist only as ciphertext until the password derives the decryption key, and the lock is enforced in the background service worker on the paths that spend money rather than only in the interface.
- No ability to be driven by a web page, because the extension declares no external connectability, its background handlers reject any message that does not originate from the extension itself and now also reject any message that does not come from the extension's own page or a secure origin, and the injected interface is mounted in closed shadow roots that the host page cannot reach.
- No ability to contact hosts outside a fixed allowlist for the market and safety data it displays. The third-party font contact on every popup open that the previous report flagged has been removed, and the extension page policy now names a default that keeps anything undeclared from loading.
- No ability to recover a key once the user removes an account, and no copy of that key held anywhere off the device, which is why the removal action now requires the wallet password and an explicit in-app confirmation before it deletes an imported key.
Security Features
The extension implements several positive security features. Each was independently verified during this analysis rather than accepted from the project's own documentation:
- Keys are encrypted at rest with an authenticated cipher under a key derived by a memory-hard function whose parameters are stored inside each encrypted blob, so the work factor can be raised in future without locking existing users out, and an older vault is transparently re-wrapped under the stronger scheme on the next unlock. The minimum password length is enforced in the key store on every path that sets a password, and decrypted material is confined to a memory-backed session area that no handler returns to a caller.
- The boundary against hostile web pages is properly constructed. The injected interfaces are mounted in closed shadow roots, every control that can reach a signing handler requires a genuine user gesture, no cross-document messaging is used anywhere, remote strings are escaped before they are placed in the page, and the background handlers now check the sending origin as well as the extension identity.
- Every transaction bundle is validated before the key is touched, so an approval may only ever name a trusted spender and a call may only target a contract the wallet resolved for this trade, and the minimum-output helper now stops a trade it cannot price rather than sending an order that accepts any output. A reverted transaction on the Ethereum-family chains now raises rather than being reported as a success.
- Outbound requests are restricted by exact hostname matching against a fixed allowlist, addresses arriving from external links are pattern-validated before use, recipient addresses entered by the user are checksum-validated in strict mode, the signing client is bound to the chain the transaction was built for, and a render failure is now caught by an application-level boundary that tells the user no on-chain state was changed rather than leaving a blank screen.
Note - This report is a security re-audit of the Impulse Wallet browser extension, version 2.5.0, as delivered to us in source form, measured against the findings of the 2.4.0 audit. This analysis did not include economic analysis of the trading strategies or the routing decisions the extension implements, nor of the third-party contracts and services it transacts with. Moreover, we only audited the extension source provided for the Impulse Wallet team. The backend service, the compiled build output and the repository history were absent from the delivery and were therefore not audited by our team, so this statement is not a clean result for those components. We recommend users do their own research before entrusting assets to any wallet.
Files and details
Findings and Audit result
critical Issues | 3 findings
Resolved
#1 critical Issue
Transactions are signed and broadcast with no confirmation screen and no instruction-level validation
The signing function took the destination, the call data and the value of an unsigned transaction and handed them to the wallet client without inspecting any of them, and there was no screen anywhere between the button the user pressed and the broadcast. The trade orchestration and the bundle runner both iterated a bundle and signed each entry in turn, so an unlimited approval and the swap that followed it were signed with a single tap and neither was described to the user first. For a non-custodial wallet this is the central control, because the whole security of the wallet rests on the user seeing and approving what leaves the device.
Acknowledged
#2 critical Issue
The Solana trade guard measures only native lamports, so a hostile routing response can take the whole token position
On Solana the extension does not build its own transaction. It asks an external routing service for a finished transaction and signs it, and this guard is the control that stands between that response and the user's key. It enforces that the transaction needs exactly one signature and that the fee payer is the user, then simulates the transaction and compares the change in the user's balance against a ceiling. The simulation reads only the native balance, so the ceiling measures native SOL and nothing else, and a transaction that moves the user's entire token balance to an attacker costs only fees, comes in below the ceiling, and passes. The structural checks that hold are real but they only constrain who pays, not what the transaction does.
Resolved
#3 critical Issue
Swap builders send with a zero minimum output when the quoter does not answer
The minimum-output helper returned zero when handed a missing quote, and a swap whose minimum output is zero accepts any output at all, including effectively nothing. Several builders derived a minimum from an unchecked quote or ran no guard at all, so a routine transient condition such as a quoter call that reverts or times out produced an order sitting in a public queue that any automated sandwich could fill for almost nothing. The condition that most reliably makes a quoter revert is a token that cannot be sold, which is the loudest honeypot signal there is, so the failure mode was worst exactly where it mattered most.
high Issues | 5 findings
Resolved
#1 high Issue
The safety panel renders a green verdict when the response carries none of the fields it checks
The verdict was computed by asking whether any check was bad, then whether any was warning, and otherwise concluding the token was clean. Each check degraded to a not-applicable level when its field was missing, and several rows were dropped when their data was absent, so a response that parsed to an object but carried none of the expected field names yielded a list with nothing bad and nothing warning and the panel rendered the green verdict. This is the screen whose entire purpose is to warn a user about a token they cannot sell, and its failure mode was to reassure them.
Resolved
#2 high Issue
The trade details shown to the user are unrelated to the transaction that is signed
Every transaction builder computed the expected output from the on-chain quoter and returned it on the bundle, and nothing read it. What the popup showed instead was an estimate calculated from two market-feed prices multiplied together, so the number the user read and the bytes the user signed came from different sources and could differ by any amount. In particular a swap whose minimum output was zero displayed a perfectly ordinary estimate, so a dangerous trade was invisible at the moment of signing.
Acknowledged
#3 high Issue
A reverted transaction is reported to the user as a success
The receipt wait returned the receipt and never looked at its status, and the underlying library does not raise on a reverted receipt, so a transaction that reverted on chain flowed through as though it had succeeded. Many call sites inherited this. The send screen awaited the confirmation, discarded it, and then unconditionally showed a success message, and the trade path did the same, catching the Solana confirmation to a false value and then returning the signature as a success. The application could not distinguish a completed state change from a failed one and reported both as completed, which also hid the symptoms of the trade-guard findings.
Resolved
#4 high Issue
The vault is exposed to unthrottled offline brute force with a short password and a work factor that cannot be raised
Key material was wrapped under a key derived by a fast hash at a work factor below current guidance, and the encrypted blob carried no work factor, so raising it in a future release would have made every existing vault undecryptable. The minimum password length was eight characters and enforced only in the onboarding form, and nothing counted or delayed failed unlock attempts. The vault lives in the browser's local storage, so anyone who obtains the profile directory gets an offline target with a low work factor and no rate limit, and the rest of the key handling being sound is what made the derivation parameters the load-bearing part.
Acknowledged
#5 high Issue
The trade guards skip rather than block when the data they need is unavailable
The depth floor, the fair-price guards on both sides of a trade, and the sell-side pool guard all followed the same shape: they fetched a market price or a pool figure, degraded a failed fetch to nothing, and then returned without raising when the value was missing. The most striking case was the sell guard that caught a failed balance read and returned cleanly, because that is the guard the code's own comment describes as the one that stops a thin or fabricated pool from taking a whole position for dust. In every case the outcome that reached the user was indistinguishable from a trade that passed all its checks, so a market-data outage silently converted a guarded wallet into an unguarded one.
medium Issues | 9 findings
Resolved
#1 medium Issue
A shared third-party credential ships inside the extension and makes every key-absence branch unreachable
A working API key for the token-analytics provider was compiled into the extension as a string literal. It was readable by anyone who unpacked the published build and was the same key for every installation, so one abusive user could get it rate-limited or revoked for everyone. It also made five key-absence branches dead code, because the key accessor fell back to the literal and the presence check could never return false, which contradicted both the module header and the settings screen that presented key entry as the switch turning these features on.
Resolved
#2 medium Issue
Every token approval is unlimited, and the user is never shown one
Three approval paths all granted the maximum: the plain token approval, the permit approval, and the permit itself, the last with a thirty-day expiry. The spenders are the well-known routers rather than arbitrary addresses, but the user was never shown that an approval was happening at all, because the approval and the swap were two entries in a bundle a single tap signed in sequence. If a router is ever compromised or upgraded to hostile code, the loss is bounded by the user's entire balance of every token they have ever traded rather than by the size of any trade.
Acknowledged
#3 medium Issue
The Solana signing primitive comes from two dependencies the project never declared
The Solana module imports the elliptic-curve library that performs signing and the encoding library that handles base58 addresses, and the manifest declared neither. Both were reached only because the package manager hoisted them from a transitive dependency, and the copy the signing code received was selected by that hoisting decision rather than by the project. Bumping or removing the key-derivation library could silently move it to a different version or remove it entirely, with nothing for a reviewer to notice in a dependency diff.
Acknowledged
#4 medium Issue
Third-party frames inside the wallet are granted clipboard write and are not sandboxed
The chart screen embedded a market-data site inside the wallet popup with clipboard write granted and no sandbox, and the bubble map page embedded an analytics site on the same terms. Granting clipboard write to a third-party frame inside a wallet is the address-substitution vector in its most direct form: the user copies their receiving address, the framed origin overwrites the clipboard, and the user pastes an attacker's address into a withdrawal field. Neither embed needs the permission for the read-only display it provides, and the absence of a sandbox also let the framed origin attempt to navigate the page that hosts it.
Resolved
#5 medium Issue
The copy control reports success without checking whether the clipboard was written
The shared copy control called the clipboard write and immediately showed a success message. The write returns a promise that was neither waited on nor caught, so a rejection produced a message that still said the value was copied. This is the control the user taps to obtain their own receiving address, and it is also used to copy the recovery phrase and the private key. A user told an address was copied, whose clipboard in fact still held whatever was there before, could paste a stale or planted address into a withdrawal field.
Resolved
#6 medium Issue
Removing an account destroys an imported private key with no re-authentication
Removing an account took an identifier and no password, and the screen called it after a single native confirmation, while importing an account required the password. For an imported account the encrypted key was deleted from the vault and, unless the user held that key elsewhere, the funds behind it became permanently unreachable. Anyone with momentary access to an unlocked popup could destroy every imported key except the last one, and the confirmation text understated the outcome for a user who imported a key they do not have a copy of.
Resolved
#7 medium Issue
A text input nested inside the account-switch button changes the active account when clicked
Each account row was a button whose click handler switched the active account, and when the user tapped Rename a text input was rendered inside that button. Clicking into the field to position the cursor produced a click that bubbled to the parent and switched the active account, with nothing stopping the propagation. The user believed they renamed an account and had also changed which account the next send or trade would draw from, and sending funds from the wrong account is not recoverable.
Resolved
#8 medium Issue
The popup contacts a font provider on every open, which the privacy policy denies
The popup loaded two font families from a third-party font service with two preconnect hints and a stylesheet link, so every time the user opened the wallet a request carrying their address and user agent reached a third party, and the timing of those requests was a record of when this person opened their wallet. The privacy policy stated the extension has no analytics and lists the services it contacts in a table that did not include the font hosts, and the reviewer notes told store reviewers the manifest host list was the complete set of servers the extension can contact.
Pending
#9 medium Issue
The lock file was not regenerated, so it disagrees with the project manifest
The delivered lock file is byte-for-byte the one from the previous release. Its root dependency ranges are still the old open ranges, it does not list the two Solana signing packages that the manifest now declares, and it still carries an older project name and version. The manifest, meanwhile, now declares two new direct dependencies and pins six packages exactly. Because the two files disagree, a clean lock-based install fails outright, and a plain install regenerates the lock file and re-resolves versions, which is exactly the unattended-move risk the new pins were meant to remove. The declaration and pinning work is therefore not in force in the delivered artefact, which undercuts the two dependency findings that were reported as addressed.
low Issues | 13 findings
Acknowledged
#1 low Issue
The header-stripping rule covers hosts that are not framed and strips more than framing requires
A static network rule removes the frame-options header, the content security policy and the cross-origin opener policy from sub-frame responses matching three subdomains of the analytics host. Only one of those subdomains is ever framed by the extension. Stripping the frame-options header is what makes the embed work and is defensible, but stripping the embedded origin's own content security policy removes that origin's script restrictions for a page rendered inside the wallet's own surface, which means a script-injection flaw on the vendor's site would execute unconstrained in a frame that also holds clipboard write. The rule should grant the minimum the embed needs.
Resolved
#2 low Issue
Remote tag strings are used as plain-object keys and can reach inherited properties
Wallet tags are read from the analytics response with no allowlist and used directly as keys into two plain object literals. Inherited property names satisfy the truthiness filter the render relies on, so a tag whose value is the name of a prototype member resolves to a function or the prototype object and throws when rendered as a child. With no error boundary in place at the time, that throw blanked the whole popup. Triggering it needs the service to return such a value, so this is a robustness issue rather than a route to funds.
Resolved
#3 low Issue
The application has no error boundary, so any render failure leaves a blank popup
There is no error boundary anywhere in the source tree. The root renders the provider and the application directly with nothing above them to catch a failure, so any uncaught error thrown during render unmounts the entire tree and leaves the user with a blank popup and no message. At least two reachable paths produce such a throw. A blank popup is a poor outcome generally and a bad one specifically in the middle of a trade, when the user cannot tell whether a transaction was broadcast.
Acknowledged
#4 low Issue
Every Solana account renders the same avatar, seeded from a shared placeholder
The account avatar hashes the account's Ethereum address to pick a colour. A Solana account stores a zero placeholder in that field, so every Solana account hashes the identical placeholder and receives the identical colour. The same defect appears on the home balance card. The avatar is the primary at-a-glance account identity in this interface, and making it non-unique for an entire account kind removes the only quick way to tell two Solana accounts apart, which invites sending from the wrong one.
Resolved
#5 low Issue
Solana accounts display a zero placeholder labelled as the private key
A Solana-only account stores a zero private key and a zero address as placeholders so the account record keeps a uniform shape, and nothing ever signs with them. The reveal path returned that placeholder as the key without checking the account kind, and the settings screen rendered it under the heading that names it as the Ethereum private key, in the same danger-styled block used for real key material. A user revealing a Solana account was shown a string of zeros presented as their private key, so a user who copied it as a backup had backed up nothing.
Acknowledged
#6 low Issue
A failed balance read is presented to the user as a zero balance
Every balance read in the portfolio loader was wrapped so that a failure became a zero balance rather than an error. A network outage or an unreachable node therefore produced a portfolio of zeroes rather than a message, and the home screen's empty state then told a funded user they had no balance yet and should tap Receive. The wallet could not distinguish the user holding nothing from the wallet being unable to find out, and presented the second as the first, which is the state phishing and fake-recovery sites are built to exploit.
Resolved
#7 low Issue
A slow response can overwrite a newer one because the shared async hook has no cancellation
The shared async hook ran its function and set state with no cancellation and no run tracking. Switching the chain picker while a portfolio load was still running let the late response set state after the new load had started. The home screen keyed the hook on the address and the chain, so the header and send buttons could be on one network while the balance list showed another network's holdings, which is a correctness problem with direct consequences for what the user does next.
Resolved
#8 low Issue
The image proxy accepts a type the avatar renderers reject and reads an unbounded body
The image proxy in the background worker validated the URL scheme and host against an allowlist, then accepted a content type that included scalable vector graphics, which the avatar modules reject. The response body was also read in full with no size check, and two of the allowlisted hosts serve user-uploaded content, so an oversized file could be aimed at it. A vector image rendered through an image element does not execute script, so this was an unnecessary divergence from the project's own policy in the component that handles the least trusted input.
Resolved
#9 low Issue
The background listener authorises by extension identifier and never checks the sending origin
The listener rejected any message whose sender identifier was not the extension's own, which is the right first step, but it never read the sending origin, so it could not distinguish a message from the popup from a message from a content script running on an arbitrary site. Because the manifest requested optional host permissions covering every origin including plaintext ones, a page on a plaintext origin whose content the panel reads to find contract addresses was under the control of anyone on the network path.
Resolved
#10 low Issue
The extension page policy omits a default directive, so everything it does not name is unrestricted
The extension page policy set a script source, an object source and a frame source and nothing else. With no default directive, every directive it did not name fell back to being unrestricted, which is what let a remote stylesheet and remote fonts load and what allowed the logo component to fetch images from remote hosts on every popup open. Adding the missing directives makes the declared host list an accurate description of what the extension can reach.
Acknowledged
#11 low Issue
The build toolchain carries four advisories that the documented dependency scope hides
A dependency scan against the delivered lock file reports four advisories against the bundler, its transitive compiler, the stylesheet processor and that processor's identifier library. All four are development-only and none ships inside the built extension, so the vendor's production-scoped claim is literally true. The gap is one of framing, because for a project whose build output is a wallet holding user keys the integrity of the machine that produces that output is in scope, and the named advisories describe developer-machine and build-time exposures.
Resolved
#12 low Issue
Remote strings are rendered as identity labels with no length or character bounds
The holders list rendered a name taken from the analytics response in place of the wallet address, with no length cap and no character filter. Token metadata was handled the same way, arriving from a market-data response and persisted verbatim, then rendered as labels throughout the interface including next to balances. A symbol containing direction-changing characters is a display-spoofing primitive, and in a wallet the labels next to amounts are precisely what a user reads before deciding to act.
Resolved
#13 low Issue
The chart frame URL is built from an unvalidated remote value
The chart screen built the frame URL by interpolating a pair identifier taken straight from a market-data response, with no validation and no encoding. The origin prefix is a fixed literal, so this was not an open redirect, but a crafted value could steer the URL within that origin because characters that terminate the path or start a query or fragment were not filtered. The practical impact was low, but the fix was already known elsewhere in the codebase and simply had not been applied here.
optimization Issues | 3 findings
Acknowledged
#1 optimization Issue
A module that is no longer on the runtime path still hardcodes a live backend address
The trade engine now runs entirely on the device, but the older backend client module is still present in the source tree and still hardcodes a hosted address as its default, alongside a request helper and several endpoint methods. Nothing reaches any of it at runtime, and the two importers take only its type declarations, so the compiler erases the module and the address does not appear in the built output. It is still live source that a single value import would reactivate, and a reader has no way to know this without tracing every import, which the delivered documentation reinforces by describing the backend as a required component.
Resolved
#2 optimization Issue
An explorer link is rebuilt by hand where a helper already handles the per-chain difference
The asset screen built an explorer link by interpolating a fixed path segment after the chain's explorer base, duplicating logic that a helper in the chain module already handles, and the helper selects a different path segment for Solana because the Solana explorer does not serve the segment hardcoded here. The result was a duplicated piece of logic that was also wrong on one of the supported chains, so the explorer link for a Solana asset pointed at a path that does not resolve.
Resolved
#3 optimization Issue
The wrapped-native address is declared in two live modules
The wrapped-native token address for the primary chain was declared twice, once as an exported constant in the older single-chain module and once as a field on the per-chain configuration object, and both were consumed by the trade engine. The values agreed, so there was no defect at the time, but this address is encoded into pool keys and swap paths, so an update applied to one declaration and not the other would produce either a revert or a trade routed through the wrong pool, and neither symptom points back at the cause.
informational Issues | 5 findings
Pending
#1 informational Issue
Strict typing stops at the boundary where untrusted data enters
Strict mode is enabled and the project compiles cleanly under it, which rules out a whole class of null and undefined defects. The observation is that strictness buys nothing where the untrusted data actually enters, because every third-party response is typed as the escape-hatch type, so the parsers that handle the least trusted input are not checked. Several strictness options that would help are also off, and the compilation scope excludes the build and packaging scripts.
Acknowledged
#2 informational Issue
The cryptographic dependencies are range-pinned, so an unattended install can move them
Every dependency used a compatible-version range, which meant an install performed without the lock file could pick up new minor versions of the packages that touch key material and transaction construction without any reviewed change. The lock file was present and pinned exact versions, so a normal clean install was reproducible, and for a wallet exact pinning of the signing and derivation dependencies is the appropriate posture.
Pending
#3 informational Issue
The image-host comment asserts a manifest property that does not hold
The comment above the image host allowlist states that every host in it is already present in the manifest host permissions, and two of the hosts are not. The practical effect is that requests to those two fail rather than succeed, which is a safe direction, but the comment asserts a property a reviewer will rely on when reviewing the allowlist and that property is false. It also matters for the store submission, because the reviewer notes tell store reviewers the manifest host list is the complete set of servers the extension can contact.
Acknowledged
#4 informational Issue
Different version numbers describe the same release
The store listing document, the extension manifest and the package manifest recorded three different version numbers for the same delivered tree. Nothing is exploitable here, but version identity is what a user, a reviewer and an incident responder use to establish which code they are looking at, and more than one answer to that question is a release-integrity gap that can cause a store submission to be rejected or to succeed while labelled as the wrong release.
Pending
#5 informational Issue
The amount parser returns zero for input it could not parse
The amount parser tests its input against a numeric pattern and returns zero when the test fails or the string is empty or a bare decimal point, so callers cannot tell the difference between the user typing zero and the parser being unable to interpret what was typed. In the amount field this is benign, because a zero-value transaction is harmless and the interface disables the action on an empty amount. It is recorded because it is the same return-a-sentinel-on-failure shape that is dangerous in the minimum-output helper, and consistency in how this codebase handles unparseable input is worth having before the pattern is copied into a path where it matters.