mirror of
https://github.com/nimbold/Firelink.git
synced 2026-09-09 17:25:42 +00:00
fix(deps): make update and advisory checks complete
- resolve FFmpeg against complete cross-platform stable provider tuples - report Cargo lock drift through isolated resolver metadata - gate vulnerabilities and document upstream informational advisories
This commit is contained in:
@@ -9,6 +9,18 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
rust-security:
|
||||
name: Rust advisory audit
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Install locked cargo-audit
|
||||
run: cargo install cargo-audit --version 0.22.2 --locked
|
||||
- name: Reject vulnerable resolved dependencies
|
||||
working-directory: src-tauri
|
||||
run: cargo audit
|
||||
|
||||
frontend:
|
||||
name: Frontend checks
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
+148
-45
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
@@ -9,6 +10,7 @@ const repoRoot = path.resolve(__dirname, '..');
|
||||
const userAgent = 'firelink-update-check';
|
||||
const fetchRetryDelaysMs = [250, 1_000];
|
||||
const fetchTimeoutMs = 30_000;
|
||||
const cargoOutputLimit = 64 * 1024 * 1024;
|
||||
const retryableHttpStatuses = new Set([408, 425, 429, 500, 502, 503, 504]);
|
||||
|
||||
function httpResponseError(response, url) {
|
||||
@@ -158,32 +160,39 @@ async function latestFfmpegStable() {
|
||||
async function latestMartinRiedlMacArm64Release() {
|
||||
const html = await fetchText('https://ffmpeg.martin-riedl.de/');
|
||||
const releaseSection = html.split('Download Release Build')[1] || '';
|
||||
const match =
|
||||
releaseSection.match(/macOS \(Apple Silicon\/arm64\)[\s\S]*?<b>Release:\s*<\/b>\s*([0-9.]+)/) ||
|
||||
releaseSection.match(/macOS \(Apple Silicon\/arm64\)[\s\S]*?Release:\s*([0-9.]+)/);
|
||||
return match?.[1];
|
||||
const card = releaseSection.match(/<h3>macOS \(Apple Silicon\/arm64\)<\/h3>[\s\S]*?<\/div>/)?.[0] || '';
|
||||
const version =
|
||||
card.match(/<b>Release:\s*<\/b>\s*([0-9.]+)/)?.[1] ||
|
||||
card.match(/Release:\s*([0-9.]+)/)?.[1];
|
||||
const relativeUrl = card.match(/href="([^"]+\/ffmpeg\.zip)"/)?.[1];
|
||||
if (!version || !relativeUrl) return undefined;
|
||||
const url = new URL(relativeUrl, 'https://ffmpeg.martin-riedl.de').href;
|
||||
const checksum = await fetchText(`${url}.sha256`);
|
||||
const sha256 = checksum.match(/\b([0-9a-f]{64})\b/i)?.[1]?.toLowerCase();
|
||||
return sha256 ? { version, url, sha256 } : undefined;
|
||||
}
|
||||
|
||||
async function latestMartinRiedlMacArm64Snapshot() {
|
||||
const html = await fetchText('https://ffmpeg.martin-riedl.de/');
|
||||
const snapshotSection = html.split('Download Snapshot Build')[1]?.split('Download Release Build')[0] || '';
|
||||
const card = snapshotSection.match(/<h3>macOS \(Apple Silicon\/arm64\)<\/h3>[\s\S]*?<\/div>/)?.[0] || '';
|
||||
const match =
|
||||
card.match(/<b>Release:\s*<\/b>\s*([A-Za-z0-9.-]+)/) ||
|
||||
card.match(/Release:\s*([A-Za-z0-9.-]+)/);
|
||||
const url = card.match(/href="([^"]+\/ffmpeg\.zip)"/)?.[1];
|
||||
return match?.[1]
|
||||
? { version: match[1], url: url ? new URL(url, 'https://ffmpeg.martin-riedl.de').href : undefined }
|
||||
: undefined;
|
||||
function escapeRegExp(value) {
|
||||
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
async function latestBtbnFfmpegN81Build() {
|
||||
async function latestBtbnFfmpegStableBuild(stableVersion) {
|
||||
if (!/^\d+\.\d+\.\d+$/.test(stableVersion)) {
|
||||
throw new Error(`unsupported FFmpeg stable version: ${stableVersion}`);
|
||||
}
|
||||
const stableSeries = stableVersion.split('.').slice(0, 2).join('.');
|
||||
const versionPattern = escapeRegExp(stableVersion);
|
||||
const seriesPattern = escapeRegExp(stableSeries);
|
||||
const assetPattern = new RegExp(
|
||||
`^ffmpeg-n(${versionPattern}-\\d+-g[0-9a-f]+)-(win64|linux64)-gpl-${seriesPattern}\\.(?:zip|tar\\.xz)$`
|
||||
);
|
||||
const releases = await fetchJson('https://api.github.com/repos/BtbN/FFmpeg-Builds/releases?per_page=10');
|
||||
if (!Array.isArray(releases)) throw new Error('BtbN releases response is not an array');
|
||||
for (const release of releases) {
|
||||
if (release.tag_name === 'latest') continue;
|
||||
const assets = (release.assets || [])
|
||||
.map(asset => {
|
||||
const match = asset.name.match(/^ffmpeg-n(8\.1\.\d+-\d+-g[0-9a-f]+)-(win64|linux64)-gpl-8\.1\.(?:zip|tar\.xz)$/);
|
||||
const match = asset.name.match(assetPattern);
|
||||
if (!match) return undefined;
|
||||
return {
|
||||
target: match[2] === 'win64' ? 'windows' : 'linux',
|
||||
@@ -210,6 +219,94 @@ async function latestBtbnFfmpegN81Build() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function cargoPackages(metadata) {
|
||||
if (!metadata || !Array.isArray(metadata.packages)) {
|
||||
throw new Error('Cargo metadata contained no package list');
|
||||
}
|
||||
return metadata.packages.map(pkg => ({
|
||||
name: pkg.name,
|
||||
version: pkg.version,
|
||||
source: pkg.source || 'path',
|
||||
}));
|
||||
}
|
||||
|
||||
function diffCargoMetadata(currentMetadata, updatedMetadata) {
|
||||
const current = cargoPackages(currentMetadata);
|
||||
const updated = cargoPackages(updatedMetadata);
|
||||
const groups = new Map();
|
||||
for (const [side, packages] of [['current', current], ['updated', updated]]) {
|
||||
for (const pkg of packages) {
|
||||
const key = `${pkg.name}\0${pkg.source}`;
|
||||
const group = groups.get(key) || { name: pkg.name, source: pkg.source, current: [], updated: [] };
|
||||
group[side].push(pkg.version);
|
||||
groups.set(key, group);
|
||||
}
|
||||
}
|
||||
|
||||
const changes = [];
|
||||
for (const group of groups.values()) {
|
||||
const oldVersions = [...group.current];
|
||||
const newVersions = [...group.updated];
|
||||
for (let index = oldVersions.length - 1; index >= 0; index -= 1) {
|
||||
const unchangedIndex = newVersions.indexOf(oldVersions[index]);
|
||||
if (unchangedIndex >= 0) {
|
||||
oldVersions.splice(index, 1);
|
||||
newVersions.splice(unchangedIndex, 1);
|
||||
}
|
||||
}
|
||||
oldVersions.sort(compareVersions);
|
||||
newVersions.sort(compareVersions);
|
||||
for (let index = 0; index < Math.min(oldVersions.length, newVersions.length); index += 1) {
|
||||
changes.push({
|
||||
name: group.name,
|
||||
version: oldVersions[index],
|
||||
latest: newVersions[index],
|
||||
source: group.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
return changes.sort((left, right) => left.name.localeCompare(right.name));
|
||||
}
|
||||
|
||||
function cargoMetadata(manifestPath) {
|
||||
return JSON.parse(execFileSync('cargo', [
|
||||
'metadata', '--format-version', '1', '--locked', '--manifest-path', manifestPath,
|
||||
], { encoding: 'utf8', maxBuffer: cargoOutputLimit, stdio: ['ignore', 'pipe', 'pipe'] }));
|
||||
}
|
||||
|
||||
function cargoCompatibleUpdates() {
|
||||
const sourceDir = path.join(repoRoot, 'src-tauri');
|
||||
const temporaryRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'firelink-cargo-update-'));
|
||||
try {
|
||||
fs.copyFileSync(path.join(sourceDir, 'Cargo.toml'), path.join(temporaryRoot, 'Cargo.toml'));
|
||||
fs.copyFileSync(path.join(sourceDir, 'Cargo.lock'), path.join(temporaryRoot, 'Cargo.lock'));
|
||||
fs.mkdirSync(path.join(temporaryRoot, 'src'));
|
||||
fs.writeFileSync(path.join(temporaryRoot, 'src', 'lib.rs'), '');
|
||||
const manifestPath = path.join(temporaryRoot, 'Cargo.toml');
|
||||
const current = cargoMetadata(path.join(sourceDir, 'Cargo.toml'));
|
||||
execFileSync('cargo', ['update', '--manifest-path', manifestPath], {
|
||||
encoding: 'utf8',
|
||||
maxBuffer: cargoOutputLimit,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
return diffCargoMetadata(current, cargoMetadata(manifestPath));
|
||||
} finally {
|
||||
fs.rmSync(temporaryRoot, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
function printCargoReport(updates) {
|
||||
if (!updates.length) {
|
||||
console.log('Rust Cargo: current');
|
||||
return 0;
|
||||
}
|
||||
console.log(`Rust Cargo: ${updates.length} compatible locked package update(s)`);
|
||||
for (const update of updates) {
|
||||
console.log(` ${update.name}: ${update.version} -> ${update.latest}`);
|
||||
}
|
||||
return updates.length;
|
||||
}
|
||||
|
||||
function printNpmReport(label, outdated) {
|
||||
const entries = Object.entries(outdated);
|
||||
if (!entries.length) {
|
||||
@@ -301,7 +398,9 @@ async function main() {
|
||||
'Browser extension npm',
|
||||
npmOutdated(path.join(repoRoot, 'Extensions', 'Browser'))
|
||||
);
|
||||
outdatedCount += printCargoReport(cargoCompatibleUpdates());
|
||||
|
||||
const ffmpegStablePromise = latestFfmpegStable();
|
||||
const providerChecks = [
|
||||
['yt-dlp latest release', () => githubLatest('yt-dlp/yt-dlp')],
|
||||
['Deno latest release', () => githubLatest('denoland/deno')],
|
||||
@@ -309,7 +408,7 @@ async function main() {
|
||||
[
|
||||
'FFmpeg stable release',
|
||||
async () => {
|
||||
const version = await latestFfmpegStable();
|
||||
const version = await ffmpegStablePromise;
|
||||
if (!version) throw new Error('FFmpeg release provider response has no usable version');
|
||||
return version;
|
||||
},
|
||||
@@ -317,17 +416,10 @@ async function main() {
|
||||
[
|
||||
'Martin Riedl macOS release',
|
||||
async () => {
|
||||
const version = await latestMartinRiedlMacArm64Release();
|
||||
if (!version) throw new Error('Martin Riedl macOS release provider response has no usable version');
|
||||
return version;
|
||||
},
|
||||
],
|
||||
[
|
||||
'Martin Riedl macOS snapshot',
|
||||
async () => {
|
||||
const build = await latestMartinRiedlMacArm64Snapshot();
|
||||
if (!build?.version || !build.url) {
|
||||
throw new Error('Martin Riedl FFmpeg provider response has no complete macOS arm64 snapshot');
|
||||
const build = await latestMartinRiedlMacArm64Release();
|
||||
const stableVersion = await ffmpegStablePromise;
|
||||
if (!build?.version || !build.url || !build.sha256 || build.version !== stableVersion) {
|
||||
throw new Error('Martin Riedl FFmpeg provider response has no complete matching macOS arm64 stable build');
|
||||
}
|
||||
return build;
|
||||
},
|
||||
@@ -335,7 +427,7 @@ async function main() {
|
||||
[
|
||||
'BtbN FFmpeg Windows/Linux build',
|
||||
async () => {
|
||||
const build = await latestBtbnFfmpegN81Build();
|
||||
const build = await latestBtbnFfmpegStableBuild(await ffmpegStablePromise);
|
||||
if (
|
||||
!build?.version ||
|
||||
!build.urls?.windows ||
|
||||
@@ -365,8 +457,8 @@ async function main() {
|
||||
const deno = providerValue(1);
|
||||
const aria2 = providerValue(2);
|
||||
const ffmpeg = providerValue(3);
|
||||
const martinRiedlMacArm64Snapshot = providerValue(5);
|
||||
const btbnFfmpegN81Build = providerValue(6);
|
||||
const martinRiedlMacArm64Release = providerValue(4);
|
||||
const btbnFfmpegStableBuild = providerValue(5);
|
||||
const latestByEngine = {
|
||||
'yt-dlp': ytDlp?.tag_name,
|
||||
deno: deno?.tag_name,
|
||||
@@ -377,17 +469,18 @@ async function main() {
|
||||
const latestUrlsByTargetEngine = {};
|
||||
const latestHashesByTargetEngine = {};
|
||||
const latestHashesByUrl = providerAssetHashes({ ytDlp, deno, aria2 });
|
||||
if (btbnFfmpegN81Build?.version && btbnFfmpegN81Build.urls?.windows && btbnFfmpegN81Build.urls?.linux) {
|
||||
latestByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegN81Build.version;
|
||||
latestByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegN81Build.version;
|
||||
latestUrlsByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegN81Build.urls.windows;
|
||||
latestUrlsByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegN81Build.urls.linux;
|
||||
latestHashesByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegN81Build.hashes?.windows;
|
||||
latestHashesByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegN81Build.hashes?.linux;
|
||||
if (btbnFfmpegStableBuild?.version && btbnFfmpegStableBuild.urls?.windows && btbnFfmpegStableBuild.urls?.linux) {
|
||||
latestByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegStableBuild.version;
|
||||
latestByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegStableBuild.version;
|
||||
latestUrlsByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegStableBuild.urls.windows;
|
||||
latestUrlsByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegStableBuild.urls.linux;
|
||||
latestHashesByTargetEngine['x86_64-pc-windows-msvc:ffmpeg'] = btbnFfmpegStableBuild.hashes?.windows;
|
||||
latestHashesByTargetEngine['x86_64-unknown-linux-gnu:ffmpeg'] = btbnFfmpegStableBuild.hashes?.linux;
|
||||
}
|
||||
if (martinRiedlMacArm64Snapshot?.version && martinRiedlMacArm64Snapshot.url) {
|
||||
latestByTargetEngine['aarch64-apple-darwin:ffmpeg'] = martinRiedlMacArm64Snapshot.version;
|
||||
latestUrlsByTargetEngine['aarch64-apple-darwin:ffmpeg'] = martinRiedlMacArm64Snapshot.url;
|
||||
if (martinRiedlMacArm64Release?.version && martinRiedlMacArm64Release.url) {
|
||||
latestByTargetEngine['aarch64-apple-darwin:ffmpeg'] = martinRiedlMacArm64Release.version;
|
||||
latestUrlsByTargetEngine['aarch64-apple-darwin:ffmpeg'] = martinRiedlMacArm64Release.url;
|
||||
latestHashesByTargetEngine['aarch64-apple-darwin:ffmpeg'] = martinRiedlMacArm64Release.sha256;
|
||||
}
|
||||
const displayVersion = value => (value ? normalizeVersion(value) : 'unavailable');
|
||||
|
||||
@@ -396,8 +489,8 @@ async function main() {
|
||||
console.log(` ${engine}: ${displayVersion(version)}`);
|
||||
}
|
||||
console.log('\nlatest engine provider builds:');
|
||||
console.log(` BtbN FFmpeg n8.1 Windows/Linux: ${displayVersion(btbnFfmpegN81Build?.version)}`);
|
||||
console.log(` Martin Riedl FFmpeg macOS arm64 snapshot: ${displayVersion(martinRiedlMacArm64Snapshot?.version)}`);
|
||||
console.log(` BtbN FFmpeg stable Windows/Linux: ${displayVersion(btbnFfmpegStableBuild?.version)}`);
|
||||
console.log(` Martin Riedl FFmpeg macOS arm64 stable: ${displayVersion(martinRiedlMacArm64Release?.version)}`);
|
||||
|
||||
const targetSpecificEngines = new Set(['ffmpeg']);
|
||||
const engineCheckFailures = [];
|
||||
@@ -456,4 +549,14 @@ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.me
|
||||
});
|
||||
}
|
||||
|
||||
export { checkRows, fetchJson, fetchText, fetchWithContext, npmExecutable, providerAssetHashes };
|
||||
export {
|
||||
checkRows,
|
||||
diffCargoMetadata,
|
||||
fetchJson,
|
||||
fetchText,
|
||||
fetchWithContext,
|
||||
latestBtbnFfmpegStableBuild,
|
||||
latestMartinRiedlMacArm64Release,
|
||||
npmExecutable,
|
||||
providerAssetHashes,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'node:test';
|
||||
|
||||
import { checkRows, fetchJson, fetchText, npmExecutable, providerAssetHashes } from './check-updates.js';
|
||||
import {
|
||||
checkRows,
|
||||
diffCargoMetadata,
|
||||
fetchJson,
|
||||
fetchText,
|
||||
latestBtbnFfmpegStableBuild,
|
||||
latestMartinRiedlMacArm64Release,
|
||||
npmExecutable,
|
||||
providerAssetHashes,
|
||||
} from './check-updates.js';
|
||||
|
||||
async function withMockFetch(mockFetch, callback) {
|
||||
const originalFetch = globalThis.fetch;
|
||||
@@ -117,3 +126,93 @@ test('npm executable selection uses the Windows command shim when needed', () =>
|
||||
assert.equal(npmExecutable('darwin'), 'npm');
|
||||
assert.equal(npmExecutable('linux'), 'npm');
|
||||
});
|
||||
|
||||
test('selects a complete BtbN build for the current stable series', async () => {
|
||||
const digest = value => `sha256:${value.repeat(64)}`;
|
||||
const release = {
|
||||
tag_name: 'autobuild-test',
|
||||
assets: [
|
||||
{
|
||||
name: 'ffmpeg-n9.0.1-11-ge47273f4d9-win64-gpl-9.0.zip',
|
||||
browser_download_url: 'https://example.test/windows.zip',
|
||||
digest: digest('a'),
|
||||
},
|
||||
{
|
||||
name: 'ffmpeg-n9.0.1-11-ge47273f4d9-linux64-gpl-9.0.tar.xz',
|
||||
browser_download_url: 'https://example.test/linux.tar.xz',
|
||||
digest: digest('b'),
|
||||
},
|
||||
{
|
||||
name: 'ffmpeg-n8.1.2-50-g1a748fe2cd-win64-gpl-8.1.zip',
|
||||
browser_download_url: 'https://example.test/old.zip',
|
||||
digest: digest('c'),
|
||||
},
|
||||
],
|
||||
};
|
||||
const result = await withMockFetch(
|
||||
async () => new Response(JSON.stringify([release]), { status: 200 }),
|
||||
() => latestBtbnFfmpegStableBuild('9.0.1'),
|
||||
);
|
||||
|
||||
assert.equal(result.version, '9.0.1-11-ge47273f4d9');
|
||||
assert.equal(result.urls.windows, 'https://example.test/windows.zip');
|
||||
assert.equal(result.hashes.linux, 'b'.repeat(64));
|
||||
});
|
||||
|
||||
test('rejects an incomplete BtbN stable target tuple', async () => {
|
||||
const release = {
|
||||
tag_name: 'autobuild-test',
|
||||
assets: [{
|
||||
name: 'ffmpeg-n9.0.1-11-ge47273f4d9-win64-gpl-9.0.zip',
|
||||
browser_download_url: 'https://example.test/windows.zip',
|
||||
digest: `sha256:${'a'.repeat(64)}`,
|
||||
}],
|
||||
};
|
||||
const result = await withMockFetch(
|
||||
async () => new Response(JSON.stringify([release]), { status: 200 }),
|
||||
() => latestBtbnFfmpegStableBuild('9.0.1'),
|
||||
);
|
||||
assert.equal(result, undefined);
|
||||
});
|
||||
|
||||
test('requires a complete Martin Riedl stable artifact and digest', async () => {
|
||||
const html = `
|
||||
<h2>Download Release Build</h2>
|
||||
<div><h3>macOS (Apple Silicon/arm64)</h3>
|
||||
<p><b>Release: </b>9.0.1</p>
|
||||
<a href="/download/macos/arm64/build/ffmpeg.zip">FFmpeg (ZIP)</a></div>`;
|
||||
const result = await withMockFetch(
|
||||
async url => new Response(
|
||||
String(url).endsWith('.sha256') ? `${'d'.repeat(64)} ffmpeg.zip\n` : html,
|
||||
{ status: 200 },
|
||||
),
|
||||
() => latestMartinRiedlMacArm64Release(),
|
||||
);
|
||||
assert.deepEqual(result, {
|
||||
version: '9.0.1',
|
||||
url: 'https://ffmpeg.martin-riedl.de/download/macos/arm64/build/ffmpeg.zip',
|
||||
sha256: 'd'.repeat(64),
|
||||
});
|
||||
});
|
||||
|
||||
test('reports compatible Cargo resolution drift from structured metadata', () => {
|
||||
const metadata = versions => ({
|
||||
packages: Object.entries(versions).map(([name, version]) => ({
|
||||
name,
|
||||
version,
|
||||
source: 'registry+https://github.com/rust-lang/crates.io-index',
|
||||
})),
|
||||
});
|
||||
assert.deepEqual(
|
||||
diffCargoMetadata(metadata({ indexmap: '2.14.1', serde: '1.0.229' }), metadata({
|
||||
indexmap: '2.14.2',
|
||||
serde: '1.0.229',
|
||||
})),
|
||||
[{
|
||||
name: 'indexmap',
|
||||
version: '2.14.1',
|
||||
latest: '2.14.2',
|
||||
source: 'registry+https://github.com/rust-lang/crates.io-index',
|
||||
}],
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Rust dependency advisory policy
|
||||
|
||||
`cargo audit` is a required CI gate. Vulnerability advisories must be resolved;
|
||||
the gate must not be bypassed with a broad ignore list.
|
||||
|
||||
As of 2026-09-05, Cargo reports no vulnerability advisories. It does report
|
||||
the following informational warnings, which remain visible in CI output:
|
||||
|
||||
- `RUSTSEC-2024-0411` through `RUSTSEC-2024-0420` (GTK3 bindings) and
|
||||
`RUSTSEC-2024-0370` (`proc-macro-error`) are Linux-only dependencies reached
|
||||
through Tauri/Wry's GTK3 and tray integration.
|
||||
- `RUSTSEC-2024-0429` (`glib` 0.18.5 iterator unsoundness) is in that same
|
||||
Linux Tauri/Wry GTK3 graph. Firelink does not directly use
|
||||
`glib::VariantStrIter`, but this remains an upstream risk rather than a
|
||||
Firelink-level remediation.
|
||||
- `RUSTSEC-2025-0075`, `RUSTSEC-2025-0080`, `RUSTSEC-2025-0081`,
|
||||
`RUSTSEC-2025-0098`, and `RUSTSEC-2025-0100` are unmaintained UNIC crates
|
||||
reached through `tauri-utils -> urlpattern`.
|
||||
|
||||
Review these paths with every Tauri/Wry update and no later than 2026-12-05.
|
||||
Remove this acknowledgement when the upstream graph no longer contains the
|
||||
affected packages. Do not add these advisory IDs to Cargo's ignore list: a
|
||||
future severity change must remain visible.
|
||||
Reference in New Issue
Block a user