Back to skill

Security audit

Agent Network

Security checks for vulnerabilities and agentic risk

Overview

The skill’s social-network purpose is coherent, but it exposes powerful unauthenticated local/network APIs, persists and discloses agent data, and makes stronger security claims than the implementation supports.

Review before installing. Run only in an isolated test environment unless the HTTP/WebSocket services are bound to loopback, authenticated, and hardened; disable or gate EvoMap/Nostr broadcasting and automatic handshakes; sanitize UI rendering; validate publish paths; and update vulnerable dependencies.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.js:104
Finding
Unauthenticated Network-Accessible HTTP API Exposes and Mutates Agent Data<![CDATA[ ## Vulnerability Details **File Location**: `index.js:104-112, 121-159, 188-320, 377-379` **Vulnerability Type**: Missing authentication and authorization; permissive CORS; insecure network binding **Risk Level**: High ### Vulnerable Code ```javascript this.httpServer = http.createServer(async (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Content-Type', 'application/json'); const sendError = (msg) => { res.end(JSON.stringify({ error: msg })); }; const sendSuccess = (data) => { res.end(JSON.stringify(data)); }; ``` Representative sensitive read operation: ```javascript else if (req.url.startsWith('/api/messages') && req.method === 'GET') { const urlObj = require('url').parse(req.url, true); const peerId = urlObj.query.peer; const messages = this.db.all(` SELECT * FROM messages WHERE (from_agent = ? AND to_agent = ?) OR (from_agent = ? AND to_agent = ?) ORDER BY created_at ASC `, [this.nodeId, peerId, peerId, this.nodeId]); sendSuccess(messages); } ``` Representative state-changing operations: ```javascript else if (req.url === '/api/send' && req.method === 'POST') { let body = ''; req.on('data', chunk => body += chunk); req.on('end', async () => { const { to, message } = JSON.parse(body); await this.core.sendMessage(to, message); sendSuccess({ success: true }); }); } else if (req.url === '/api/publish' && req.method === 'POST') { let body = ''; req.on('data', chunk => body += chunk); req.on('end', async () => { const { skillPath, price, metadata } = JSON.parse(body); const skillId = await this.skills.publish(skillPath, price, metadata); await this.core.shareSkill( skillId, metadata.name || skillPath, metadata.description, price ); sendSuccess({ success: true, skillId }); }); } ``` The server is started without restricting it to the loopback interface: ```javascript this.httpServer.listen(thi ...[truncated 2622 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bind the management API explicitly to loopback unless remote administration is required: ```javascript this.httpServer.listen(this.config.port + 1, '127.0.0.1', callback); ``` - Require a cryptographically random authentication token for every route. Store it with restrictive file permissions and compare it using a timing-safe operation. - Prefer authenticated Electron IPC over an HTTP management API for desktop-only operations. - Implement route-level authorization, particularly for messaging, skill publication, sharing, rating, and point-changing operations. - Replace wildcard CORS with a strict origin allowlist. Reject requests with missing or unexpected `Origin` headers where appropriate. - Implement CSRF protection if browser-originated state-changing requests remain supported. - Set explicit body-size limits and return HTTP `413` when exceeded. - Add rate limits and audit logging for sensitive operations. - Return appropriate status codes and avoid exposing internal exception messages. - Require explicit user confirmation for outbound messages, publication, downloads, and sharing of memory-like content. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
lib/skills.js:22
Finding
Path Traversal in Skill Publication Reads Files Outside the Skills Directory<![CDATA[ ## Vulnerability Details **File Location**: `lib/skills.js:22-39` **Vulnerability Type**: Directory traversal and unauthorized local file read **Risk Level**: High ### Vulnerable Code ```javascript async publish(skillPath, price = 0, metadata = {}) { const skillDir = path.join(this.skillsDir, skillPath); if (!fs.existsSync(skillDir)) { throw new Error('Skill not found: ' + skillPath); } const skillMdPath = path.join(skillDir, 'SKILL.md'); let description = ''; if (fs.existsSync(skillMdPath)) { const content = fs.readFileSync(skillMdPath, 'utf-8'); // Extract first 200 chars as description description = content.substring(0, 200); } ``` The method is remotely reachable through: ```javascript const { skillPath, price, metadata } = JSON.parse(body); const skillId = await this.skills.publish(skillPath, price, metadata); ``` ### Technical Analysis `skillPath` is attacker-controlled and passed directly to `path.join(this.skillsDir, skillPath)`. The result is not canonicalized and checked against `this.skillsDir`. Values containing `../` components can escape the intended OpenClaw skills directory. If the resulting external directory exists and contains a file named `SKILL.md`, the application reads the file and places its first 200 characters into the persistent `skills.description` field. That field is exposed through the unauthenticated `/api/skills` route and rendered by the Electron interface. This is not a fully arbitrary filename read because the final filename is fixed as `SKILL.md`; however, it is an unauthorized read of any accessible directory containing a file with that name. It can expose private skill instructions or other sensitive content stored in similarly named files. ### Attack Path 1. The attacker gains access to the unauthenticated `/api/publish` endpoint. 2. The attacker submits a traversal value such as a relative path containing one or more `../` components. 3. `path.join` resolves the path ou ...[truncated 906 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Accept a validated skill identifier rather than an arbitrary filesystem path. - Resolve and verify the canonical path before accessing it: ```javascript const root = fs.realpathSync(this.skillsDir); const candidate = fs.realpathSync(path.resolve(root, skillPath)); const relative = path.relative(root, candidate); if (relative.startsWith('..') || path.isAbsolute(relative)) { throw new Error('Invalid skill path'); } ``` - Reject absolute paths, `..` components, null bytes, and unexpected path separators. - Recheck containment after resolving symbolic links with `realpathSync`. - Verify that the candidate is a direct child or otherwise conforms to the expected skill layout. - Do not expose file content automatically. Require explicit user selection and confirmation before publishing a description extracted from disk. - Escape or sanitize all extracted content before presenting it in HTML. - Add regression tests for traversal through `../`, absolute paths, symbolic links, and platform-specific path syntax. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
ui/index.html:299
Finding
Stored HTML Injection in Electron Renderer Enables Access to Privileged Agent APIs<![CDATA[ ## Vulnerability Details **File Location**: `ui/index.html:299-316, 391-437`; related configuration in `electron.js:18-29` and bridge capabilities in `preload.js:4-89` **Vulnerability Type**: Stored cross-site scripting in an Electron renderer **Risk Level**: High ### Vulnerable Code Remote or database-controlled skill fields are inserted directly into HTML: ```javascript container.innerHTML = skills.map(s => ` <div class="card"> <div class="card-header"> <span class="card-title">${s.name}</span> <span class="card-badge">${s.price || 0}积分</span> </div> <div class="card-desc">${s.description || '暂无描述'}</div> <div class="card-meta"> <span class="rating">⭐ ${(s.avg_rating || 0).toFixed(1)}</span> <span>📥 ${s.downloads || 0}</span> </div> <div class="action-row" style="margin-top:8px;"> <button class="btn btn-primary btn-small" onclick="downloadSkill('${s.id}')">下载</button> <button class="btn btn-secondary btn-small" onclick="openRateModal('${s.id}', '${s.name}')">评分</button> </div> </div> `).join(''); ``` Stored message content is also inserted directly: ```javascript container.innerHTML = messages.map(m => { const isSent = m.from_agent === myNodeId; return ` <div style="margin:5px 0;text-align:${isSent ? 'right' : 'left'};"> <span style="background:${isSent ? '#667eea' : '#4a5568'};color:white;padding:6px 10px;border-radius:12px;display:inline-block;max-width:80%;word-break:break-word;"> ${m.content} </span> <div style="font-size:9px;color:#666;margin-top:2px;">${new Date(m.created_at).toLocaleString()}</div> </div> `; }).join(''); ``` Electron enables context isolation but exposes a broad privileged API: ```javascript webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } ``` ```javascript contextBridge.exposeInMainWorld('api', { getMessages: (peerId) => fetch(`http://lo ...[truncated 2974 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never insert untrusted data using `innerHTML`. - Construct DOM nodes with `document.createElement` and assign untrusted values through `textContent`. - Remove inline `onclick` handlers. Register event listeners programmatically and retain identifiers in safe data structures. - If rich HTML is a required feature, sanitize it with a well-maintained sanitizer configured to forbid scripts, event attributes, dangerous URL schemes, SVG, MathML, and other active content. - Deploy a restrictive Content Security Policy, for example one that permits scripts only from packaged files and disallows inline scripts. - Minimize the preload bridge. Expose narrowly scoped methods, validate every argument, and require explicit user confirmation for high-impact actions. - Treat the preload/API boundary as a security boundary even with context isolation enabled. - Add automated tests using payloads in every peer, message, skill, review, version, and path field. - Consider using Electron's sandbox mode and disabling navigation or new-window creation to untrusted locations. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
lib/network.js:157
Finding
Unauthenticated Plaintext WebSocket Protocol Permits Peer Impersonation and Persistent State Forgery<![CDATA[ ## Vulnerability Details **File Location**: `lib/network.js:43-60, 157-224`; persistent handling in `lib/core.js:80-125` **Vulnerability Type**: Missing peer authentication, plaintext transport, and identity binding **Risk Level**: High ### Vulnerable Code The service accepts network connections without authentication: ```javascript async start() { return new Promise((resolve, reject) => { this.wss = new WebSocket.Server({ port: this.port }); this.wss.on('listening', () => { console.log(`P2P server listening on port ${this.port}`); this.startHTTPAgentDiscovery(); resolve(); }); this.wss.on('error', (err) => { console.error('P2P server error:', err); reject(err); }); this.wss.on('connection', (ws, req) => { this.handleConnection(ws, req); }); }); } ``` Peer identity is accepted directly from an untrusted message: ```javascript handleMessage(ws, message) { const { type, peerId, payload } = message; switch (type) { case 'handshake': this.connections.set(peerId, { ws, info: payload, type: 'websocket' }); this.emit('peer_connected', peerId, payload); console.log(`Peer connected: ${peerId}`); if (this.config.autoGreet && payload.name) { setTimeout(() => { this.sendGreeting(peerId); }, 1000); } break; case 'message': this.handlePeerMessage(peerId, payload); break; case 'discover_request': this.handleDiscoverRequest(ws, peerId); break; case 'skill_share': this.handleSkillShare(peerId, payload); break; default: if (this.messageHandlers.has(type)) { this.messageHandlers.get(type)(payload, peerId); } } } ``` The core trusts identity fields inside the payload rather than the authenticated connection: ```javascript handleMessage(payload, fromPeerId) { const { from, to, content, messageType } = payload; this ...[truncated 3051 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use `wss://` with a properly validated TLS certificate for all non-loopback communication. - Authenticate every peer with a cryptographic challenge-response protocol. - Derive the peer identifier from a verified public key instead of accepting an arbitrary string. - Sign messages over all security-relevant fields, including type, sender, recipient, content, timestamp, and a unique nonce. - Reject stale timestamps and replayed nonces. - Bind each accepted message to the authenticated WebSocket connection. Ignore or reject payload `from` values that differ from the verified connection identity. - Authorize state transitions. An appreciation acceptance must correspond to a real pending request and must be signed by the intended peer. - Validate message schemas, field lengths, types, and allowed state transitions. - Rate-limit handshakes, discovery requests, messages, and malformed payloads. - Restrict the listener interface when public P2P connectivity is not required. ]]>

T02 · Agent Memory Poisoning

Error
Location
index.js:233
Finding
Unauthenticated Persistent Shared-Memory Creation and Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `index.js:233-256`; persistence implementation in `lib/sharing.js:36-49` **Vulnerability Type**: Persistent state poisoning and unauthorized disclosure **Risk Level**: High ### Vulnerable Code The HTTP API exposes all sharing records and accepts memory content without authentication: ```javascript else if (req.url === '/api/shares/mine' && req.method === 'GET') { const balance = await this.skills.getBalance(this.p2p.peerId); if (!this.sharing) { this.sharing = new SharingManager(this.db, this.p2p.peerId); } const shares = this.sharing.getMyShares(); sendSuccess({ ...shares, myLevel: this.sharing.getCreditLevel(balance) }); } else if (req.url === '/api/share' && req.method === 'POST') { let body = ''; req.on('data', chunk => body += chunk); req.on('end', async () => { try { const { shareType, title, content, tags, skillId, skillName, description, version } = JSON.parse(body); if (!this.sharing) { this.sharing = new SharingManager(this.db, this.p2p.peerId); } let result; if (shareType === 'experience') { result = this.sharing.shareExperience(title, content, tags); } else if (shareType === 'skill') { result = this.sharing.shareSkill( skillId, skillName, description, version ); } else if (shareType === 'memory') { result = this.sharing.shareMemory(title, content, tags); } sendSuccess(result); } catch (e) { sendError(e.message); } }); } ``` The supplied memory is written to persistent storage under the local node identity: ```javascript shareMemory(title, content, tags = []) { const id = 'mem_' + crypto.randomBytes(6).toString('hex'); const level = this.getCreditLevel(); this.db.run( `INSERT INTO shared_memories (id, node_id, title, content, ...[truncated 2492 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require authentication and per-record authorization for all sharing endpoints. - Do not expose all records through a route named `mine` without proving the caller's identity. - Require explicit user confirmation before persisting memory-like content. - Track provenance for every memory, including creator identity, creation channel, signature, and trust status. - Store externally supplied content as untrusted data and never automatically insert it into system or developer prompts. - If memory is used as model context, delimit and label it as untrusted, apply content-policy checks, and provide a review or deletion interface. - Add field-length limits, schema validation, rate limits, and storage quotas. - Encrypt sensitive memory content at rest when appropriate and apply restrictive filesystem permissions to the database. - Add audit logs for creation, reading, modification, and deletion of persistent memory records. ]]>

other

Warning
Location
index.js:45
Finding
Automatic Third-Party Agent Registration and Presence Broadcasting<![CDATA[ ## Vulnerability Details **File Location**: `index.js:45-73`; external communication in `lib/evomap.js:4-65` and `lib/nostr.js:5-15, 28-51, 94-119` **Vulnerability Type**: Unprompted external identity and capability disclosure **Risk Level**: Medium ### Vulnerable Code Startup automatically connects and registers with external services: ```javascript try { this.nostr = new NostrClient(); await this.nostr.connect(); await this.nostr.broadcast(); console.log( `✓ Nostr connected, pubkey: ${this.nostr.getPublicKey().substring(0, 8)}...` ); } catch (e) { console.log(` Nostr error: ${e.message}`); } try { this.evomap = new EvoMapClient(this.nodeId); await this.evomap.hello( ['chat', 'skills', 'p2p'], { services: ['p2p', 'chat', 'skills'] } ); const agents = await this.evomap.discoverAgents(); for (const agent of agents.slice(0, 3)) { setTimeout(async () => { try { await this.evomap.handshake(agent.node_id); this.core.db.run( `INSERT OR IGNORE INTO connections (peer_id, status, connected_at) VALUES (?, 'accepted', ?)`, [agent.node_id, Date.now()] ); } catch (e) {} }, Math.random() * 3000 + 1000); } } catch (e) { console.log(` EvoMap error: ${e.message}`); } ``` EvoMap registration includes identity and capability metadata: ```javascript async hello(capabilities = [], metadata = {}) { const envelope = this.buildEnvelope('hello', { capabilities, metadata: { ...metadata, version: '1.0.9', protocol: 'agent-network' } }); return this.request('/a2a/hello', 'POST', envelope); } ``` Nostr connects to five hardcoded relays: ```javascript const DEFAULT_RELAYS = [ 'wss://relay.doctormcfly.com', 'wss://relay.olas.app', 'wss://nos.lol', 'wss://eden.nostr.land', 'wss://relay.nostr.band' ]; ``` Presence content is broadcast automatically: ```javascript content: JSON.stringify({ nodeId: this.no ...[truncated 2083 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Make EvoMap and Nostr connectivity opt-in during first-run configuration. - Clearly disclose each external destination and the exact metadata transmitted. - Provide independent switches for directory registration, relay broadcasting, discovery, and automatic handshakes. - Disable automatic handshakes by default and require user approval for new external peers. - Minimize transmitted metadata and avoid exposing local service ports unless necessary. - Allow users to configure or remove relays and directory providers. - Implement standards-compliant Nostr event identifiers, public keys, and cryptographic signatures using a reviewed library. - Persist private keys securely if a stable Nostr identity is required; otherwise clearly describe identities as ephemeral. - Add connection timeouts, response-size limits, certificate validation controls, and transparent network logging. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (109)

Ae1

High
Category
analysis-evasion
Content
### Skills 管理模块 (lib/skills.js)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
const skillMdPath = path.join(skillDir, 'SKILL.md');
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The skill’s security claims materially misrepresent the actual protections in the code. The implementation uses grpc.ServerCredentials.createInsecure()/grpc.credentials.createInsecure() and HMAC-SHA256 with a shared or default key, so peers may trust plaintext transport and weak identity guarantees that enable interception, spoofing, and impersonation.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The documentation says all messages are signed with Ed25519, but the code signs only message content with HMAC-SHA256 using a shared secret obtained from an environment variable or a hardcoded default. This defeats non-repudiation and enables any party with the shared/default key to forge messages as other agents.

Exfiltration Commands

High
Category
Prompt Injection
Content
return true;
  }
  
  // Send message to a peer
  async sendMessage(to, content, type = 'text') {
    const message = {
      from: this.nodeId,
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill can send message content to a hard-coded external endpoint at evomap.ai, causing user or peer-supplied data to leave the local trust boundary without clear authorization or destination validation. Because the message body is forwarded off-host, sensitive content could be exfiltrated to an external service and users may not realize their communications are being relayed there.

Missing User Warnings

High
Confidence
98% confidence
Finding
Messages are transmitted to an external HTTPS endpoint without explicit warning, so users may unknowingly send potentially sensitive content outside the local system. The hard-coded endpoint and lack of consent make this especially dangerous because the skill context does not justify silent off-platform message delivery.

Missing User Warnings

High
Confidence
93% confidence
Finding
The function stores memory title, content, and tags in persistent storage under shared_memories, which can affect sensitive user data or privacy. No confirmation prompt, user-visible log, or explanatory documentation is present in this file despite the potentially sensitive nature of memory sharing.

Self-Modification

High
Category
Rogue Agent
Content
// Update download count
    this.db.run(
      'UPDATE skills SET downloads = downloads + 1 WHERE id = ?',
      [skillId]
    );
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
// Update download count
    this.db.run(
      'UPDATE skills SET downloads = downloads + 1 WHERE id = ?',
      [skillId]
    );
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
// Update download count
    this.db.run(
      'UPDATE skills SET downloads = downloads + 1 WHERE id = ?',
      [skillId]
    );
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
// Update download count
    this.db.run(
      'UPDATE skills SET downloads = downloads + 1 WHERE id = ?',
      [skillId]
    );
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Known Vulnerable Dependency: brace-expansion==1.1.12 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
brace-expansion 1.1.12 is flagged with multiple DoS advisories and appears in the dependency tree through Electron packaging-related tooling. While this is in dev/build paths rather than obvious runtime logic, vulnerable pattern expansion can still be abused during local builds, CI, or any workflow that processes attacker-controlled patterns.

Known Vulnerable Dependency: minimatch==3.1.3 — 1 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu)

High
Category
Supply Chain
Confidence
95% confidence
Finding
minimatch 3.1.3 has a ReDoS advisory and is pulled in transitively by build tooling. If attacker-controlled glob expressions are processed during build, packaging, or file enumeration, catastrophic backtracking can cause CPU exhaustion and pipeline disruption.

Known Vulnerable Dependency: @grpc/grpc-js==1.14.3 — 2 advisory(ies): CVE-2026-48068 (@grpc/grpc-js: A malformed request can cause a server crash); CVE-2026-48069 (@grpc/grpc-js: An incoming malformed compressed message can cause a client or se)

High
Category
Supply Chain
Confidence
98% confidence
Finding
@grpc/grpc-js 1.14.3 is a runtime dependency and the advisories indicate malformed requests or compressed messages can crash client or server processes. Because this skill appears network-oriented and explicitly depends on gRPC, the context makes the issue more dangerous than a dormant dev-only package.

Known Vulnerable Dependency: @xmldom/xmldom==0.8.11 — 15 advisory(ies): CVE-2026-83608 (xmldom: DocType `name` Injection Bypasses requireWellFormed); CVE-2026-41673 (xmldom: Uncontrolled recursion in XML serialization leads to DoS); CVE-2026-83605 (xmldom: Attribute name injection via setAttribute() bypasses requireWellFormed) +12 more

High
Category
Supply Chain
Confidence
93% confidence
Finding
@xmldom/xmldom 0.8.11 has numerous XML parsing and serialization advisories. In this case it is part of dev/build packaging paths via plist handling, so exposure is lower than a runtime XML service, but malformed XML/plist input in build or packaging workflows could still trigger denial of service or malformed output issues.

Known Vulnerable Dependency: app-builder-lib==24.13.3 — 1 advisory(ies): CVE-2026-54672 (electron-updater: Uncontrolled search path elements within `AppImage` built by `)

High
Category
Supply Chain
Confidence
88% confidence
Finding
app-builder-lib 24.13.3 is flagged due to an electron-updater-related advisory affecting produced AppImage artifacts. This is a real supply-chain and release engineering risk: even though it is dev/build tooling, vulnerable packaging can produce downstream distributables with unsafe update/search-path behavior.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
94% confidence
Finding
brace-expansion 2.0.2 carries multiple DoS advisories and is used in transitive build tooling. If fed attacker-controlled brace patterns in CI or packaging contexts, it can consume excessive CPU or memory and disrupt automation.

Known Vulnerable Dependency: builder-util-runtime==9.2.4 — 1 advisory(ies): CVE-2026-54673 (electron-updater: Cross-origin redirect leaks `PRIVATE-TOKEN` and mixed-case `Au)

High
Category
Supply Chain
Confidence
89% confidence
Finding
builder-util-runtime 9.2.4 is affected by a token leakage advisory in redirect handling associated with updater functionality. In the context of Electron distribution tooling, this may expose sensitive authentication headers or private tokens during publishing/update flows, which is meaningful even if not exercised by end-user runtime paths here.

Known Vulnerable Dependency: brace-expansion==5.0.3 — 5 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-45149 (brace-expansion: Large numeric range defeats documented `max` DoS protection) +2 more

High
Category
Supply Chain
Confidence
94% confidence
Finding
brace-expansion 5.0.3 is also flagged for multiple DoS conditions. Although present in newer tooling chains, it still presents a resource exhaustion risk when handling attacker-influenced expansion expressions.

Known Vulnerable Dependency: minimatch==9.0.6 — 2 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
95% confidence
Finding
minimatch 9.0.6 has multiple ReDoS advisories, making pattern matching on hostile input expensive. In this lockfile it appears in tooling, but if any build, packaging, or config-loading path accepts untrusted glob expressions, CPU exhaustion is plausible.

Known Vulnerable Dependency: electron==28.3.3 — 16 advisory(ies): CVE-2026-34776 (Electron: Out-of-bounds read in second-instance IPC on macOS and Linux); CVE-2026-70609 (Electron: DevTools JavaScript Injection via Unsanitized Dock State Parameter); CVE-2026-34767 (Electron: HTTP Response Header Injection in custom protocol handlers and webRequ) +13 more

High
Category
Supply Chain
Confidence
92% confidence
Finding
electron 28.3.3 is a dev dependency with many advisories, several of which affect IPC, protocol handling, and JavaScript injection. Even though this is not necessarily shipped as part of a server runtime, Electron materially expands attack surface for any desktop build or local tooling based on it.

Known Vulnerable Dependency: extract-zip==2.0.1 — 2 advisory(ies): CVE-2026-19693 (extract-zip allows arbitrary file writes through symlink archive entries); CVE-2026-56876 (extract-zip unvalidated symlink path traversal)

High
Category
Supply Chain
Confidence
91% confidence
Finding
extract-zip 2.0.1 has arbitrary file write and symlink traversal advisories. In this dependency tree it is used by Electron download/install tooling, so malicious archives processed in build or install contexts could write outside intended extraction directories.

Known Vulnerable Dependency: minimatch==10.2.2 — 2 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
95% confidence
Finding
minimatch 10.2.2 remains affected by ReDoS advisories despite being newer than 3.x/5.x. If untrusted glob patterns are matched in development or packaging workflows, they can trigger high CPU consumption and denial of service.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
86% confidence
Finding
form-data 4.0.5 is affected by CRLF injection when field names or filenames are not safely escaped. Here it appears in publishing/build tooling, so exploitability depends on whether attacker-controlled metadata is sent in multipart requests, but header/body smuggling in automated release flows is still a legitimate risk.

Static analysis

No suspicious patterns detected.