Back to skill

Security audit

Desktop Sandbox

Security checks for vulnerabilities and agentic risk

Overview

This skill is a native installer that mostly does what it says, but it downloads and runs mutable GitHub release installers with weak safeguards, so users should review it carefully before use.

Only install this if you trust the AtlasCore GitHub release process and are comfortable running a native installer on your machine. Prefer a pinned version, verify the downloaded installer through an independent checksum or platform signature, and review the repository/release before allowing the skill to execute it.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/run_installer.js:296
Finding
Remote Installer Is Downloaded and Executed Without Integrity or Authenticity Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_installer.js:157-159, 192-211, 227-265, 296-315` **Vulnerability Type**: Unverified remote payload retrieval and execution **Risk Level**: High ### Vulnerable Code ```javascript const apiUrl = specificVersion ? `https://api.github.com/repos/${owner}/${repo}/releases/tags/${specificVersion}` : `https://api.github.com/repos/${owner}/${repo}/releases/latest`; ``` ```javascript function findInstaller(assets) { const platformMap = { darwin: { pattern: /\.pkg$/i, name: 'macOS' }, win32: { pattern: /\.exe$/i, name: 'Windows' } }; const config = platformMap[platform]; if (!config) { throw new Error(`Unsupported platform: ${platform}`); } for (const asset of assets) { const name = asset.name || ''; if (config.pattern.test(name)) { return asset; } } return null; } ``` ```javascript if (platform === 'darwin') { (async () => { writeLog(`Running installer with open -W...`); const proc = spawn('open', ['-n', '-W', installerPath], { stdio: 'inherit' }); proc.on('error', err => { resolve({ success: false, exitCode: -1, message: `Failed to execute installer: ${err.message}` }); }); proc.on('close', code => { const duration = (Date.now() - startTime) / 1000; const success = code === 0; resolve({ success, exitCode: code, message: success ? 'Installation completed successfully' : `Installer exited with code: ${code}`, duration }); }); })().catch(err => { resolve({ success: false, exitCode: -1, message: `Installer flow failed: ${err.message}` }); }); } else { const psScript = `Start-Process -FilePath '${installerPath}' -ArgumentList '/S', '/D=C:\\Program Files\\' -WindowStyle Hidden -Wait`; const proc = spawn('po ...[truncated 2652 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin an immutable installer version rather than using `latest` by default. 2. Store an independently reviewed SHA-256 digest for each supported platform and version within the Skill. 3. Calculate the downloaded file's digest before execution and abort on any mismatch. 4. Verify platform-native signatures: - On Windows, validate Authenticode status and require the expected publisher certificate. - On macOS, validate the package signature, expected Developer ID, and notarization status. 5. Match an exact expected asset name instead of accepting the first file with a suitable extension. 6. Require explicit user confirmation that identifies the version, publisher, digest, and source before execution. 7. Treat verification failure as fatal and delete the untrusted artifact without invoking it. 8. Publish and verify a signed release manifest that binds version, platform, asset name, size, and digest. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/run_installer.js:107
Finding
Unrestricted Redirect Handling Permits Host Changes and HTTPS Downgrade<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_installer.js:107-118` **Vulnerability Type**: Unrestricted and potentially insecure download redirects **Risk Level**: High ### Vulnerable Code ```javascript const file = fs.createWriteStream(dest); const protocol = url.startsWith('https') ? https : http; let downloadedBytes = 0; let totalBytes = 0; let lastTime = Date.now(); let lastBytes = 0; const request = protocol.get(url, { headers: { 'User-Agent': 'Desktop-Sandbox-Installer/1.0' } }, (response) => { if (response.statusCode === 302 || response.statusCode === 301) { file.close(); downloadFile(response.headers.location, dest).then(resolve).catch(reject); return; } ``` ### Technical Analysis The downloader recursively follows HTTP 301 and 302 responses without validating the redirect destination. The protocol is selected from the redirected URL, and both `https` and `http` are supported. Therefore, an initially trusted HTTPS request may be redirected to: - An untrusted external hostname. - A plain HTTP URL. - An internal or otherwise unintended endpoint. - Another redirect, with no maximum redirect count. TLS protects only each HTTPS connection; it does not establish that an unrestricted redirect destination is authorized to provide the executable. If the flow is downgraded to HTTP, an on-path attacker can alter the installer bytes. Because the downloaded file is subsequently executed without digest or signature verification, payload substitution becomes code execution. The lack of a redirect limit also allows an attacker-controlled endpoint to create an unbounded recursive redirect chain, consuming resources or causing the installer operation to fail. ### Attack Path 1. An attacker gains control of a release asset URL, redirect response, or destination in the download chain. 2. The server returns a 301 or 302 response whose `Location` header points to an attacker-controlled host or an HTTP URL. 3. `d ...[truncated 963 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit only HTTPS for the initial URL and every redirect destination. 2. Parse URLs with the standard `URL` class and reject malformed or unsupported schemes. 3. Enforce an explicit hostname allowlist covering only required GitHub and GitHub release-asset domains. 4. Validate every redirect hop rather than only the initial URL. 5. Set a low maximum redirect count, such as three to five hops, and fail closed when exceeded. 6. Correctly resolve relative `Location` headers against the current URL. 7. Reject redirects containing unexpected credentials, ports, or destination hosts. 8. Verify the final downloaded artifact using a pinned cryptographic digest and expected publisher signature before execution. 9. Use request timeouts and response-size limits to reduce denial-of-service exposure. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_installer.js:253
Finding
Remote Asset Name Is Interpolated into a PowerShell Command<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_installer.js:253-254` **Vulnerability Type**: PowerShell command injection **Risk Level**: High ### Vulnerable Code ```javascript const psScript = `Start-Process -FilePath '${installerPath}' -ArgumentList '/S', '/D=C:\\Program Files\\' -WindowStyle Hidden -Wait`; const proc = spawn('powershell.exe', ['-Command', psScript], { stdio: 'inherit' }); ``` The interpolated path is derived from the remotely supplied release asset name: ```javascript const downloadPath = path.join(targetDir, asset.name); await downloadFile(asset.browser_download_url, downloadPath); ``` ### Technical Analysis The Windows execution path builds PowerShell source code by directly interpolating `installerPath` inside a single-quoted PowerShell string. The path includes `asset.name`, which comes from remote GitHub release metadata. The script neither constrains the asset name to a safe basename nor escapes PowerShell single quotes. An asset name containing a quote and PowerShell syntax could terminate the `-FilePath` string and inject additional commands into the script passed to `powershell.exe -Command`. Using an argument array for `powershell.exe` does not prevent this vulnerability because the untrusted value is embedded inside PowerShell program text. PowerShell parses that program after process creation. ### Attack Path 1. An attacker obtains the ability to publish or modify assets in the configured GitHub release. 2. The attacker creates an `.exe` asset whose name contains PowerShell quoting or command-separation syntax while still ending in `.exe`. 3. `findInstaller()` accepts the asset because validation checks only the `.exe` suffix. 4. The remote asset name becomes part of `downloadPath` and then `installerPath`. 5. `runInstaller()` inserts the path directly into the `Start-Process` command string. 6. PowerShell parses the attacker-controlled characters as part of the command language. 7. The injected Power ...[truncated 880 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not construct PowerShell source code from an untrusted path. 2. Prefer direct process execution without a shell, for example by invoking the validated executable path through `spawn(installerPath, arguments, { shell: false })`. 3. If PowerShell is strictly required, pass the installer path as a separately encoded or bound parameter rather than interpolating it into `-Command`. 4. Enforce an exact allowlisted asset filename for each platform and version. 5. Reject asset names containing path separators, quotes, control characters, shell metacharacters, or non-basename components. 6. Resolve the destination path and verify that it remains inside the newly created temporary directory. 7. Apply cryptographic integrity and publisher-signature verification before executing the file. 8. Add security tests using filenames containing quotes, semicolons, backticks, whitespace, and PowerShell expression syntax. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to install software from GitHub releases via a Node-based installer that invokes platform-native package installation mechanisms, but it does not warn the user that this performs system-level changes. Because the described behavior includes executing .exe and .pkg installers into privileged locations, users may be exposed to unexpected software installation, privilege prompts, or persistence risks without informed consent.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The conversation triggers are very broad and generic, especially phrases like 'Install desktop sandbox' and 'Download and install AtlasCore sandbox'. In an agent environment, broad activation phrases can cause this skill to be selected for ordinary install-related requests and lead to unexpected execution of a system-level installer, increasing the chance of unintended software installation.

External Transmission

Medium
Category
Data Exfiltration
Content
async function fetchGitHubRelease(owner, repo, specificVersion = '') {
    const apiUrl = specificVersion
        ? `https://api.github.com/repos/${owner}/${repo}/releases/tags/${specificVersion}`
        : `https://api.github.com/repos/${owner}/${repo}/releases/latest`;

    writeLog(`Fetching from: ${apiUrl}`);
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async function fetchGitHubRelease(owner, repo, specificVersion = '') {
    const apiUrl = specificVersion
        ? `https://api.github.com/repos/${owner}/${repo}/releases/tags/${specificVersion}`
        : `https://api.github.com/repos/${owner}/${repo}/releases/latest`;

    writeLog(`Fetching from: ${apiUrl}`);
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/run_installer.js:53