Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/workflows/release-fast.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Release Fast

on:
workflow_dispatch:
inputs:
reddb_version:
description: "Pinned RedDB release tag to smoke-package with"
required: true
default: "v1.11.0"

permissions:
contents: read

concurrency:
group: release-fast-${{ github.ref }}
cancel-in-progress: true

env:
REDDB_VERSION: ${{ github.event.inputs.reddb_version }}

jobs:
linux-deb:
name: linux-x86_64 deb smoke
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v7

- name: Linux system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev \
librsvg2-dev build-essential curl wget file libssl-dev libxdo-dev \
clang mold

- uses: pnpm/action-setup@v6
with:
version: 10.33.3

- uses: actions/setup-node@v6
with:
node-version: "22"
cache: pnpm

- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"

- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu

- uses: swatinem/rust-cache@v2
with:
workspaces: "apps/desktop/src-tauri -> target"

- name: Install
run: pnpm install --frozen-lockfile

- name: Check RedDB sidecar release asset
run: node scripts/check-reddb-release-assets.mjs x86_64-unknown-linux-gnu
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Brand sync
run: pnpm brand:sync

- name: Brand icons
run: pnpm brand:icons

- name: Build core contract
run: pnpm --filter @red-request/core build

- name: Build engine sidecar
run: pnpm engine:build

- name: Provision RedDB sidecar
run: pnpm reddb:fetch
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REDDB_TARGET: x86_64-unknown-linux-gnu

- name: Build Linux deb only
run: pnpm --filter @red-request/desktop tauri build --bundles deb

- name: Upload deb artifact
uses: actions/upload-artifact@v5
with:
name: red-request-linux-x86_64-deb
path: apps/desktop/src-tauri/target/release/bundle/deb/*.deb
if-no-files-found: error
18 changes: 18 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,26 @@ env:
NO_STRIP: "1"

jobs:
preflight:
name: release preflight
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- uses: actions/setup-node@v6
with:
node-version: "22"

Comment on lines +33 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/release.yml | head -60

Repository: reddb-io/red-request

Length of output: 2305


🏁 Script executed:

# Check what the actual commit SHAs are for the recommended action versions
# First, let's see if there are any GitHub Actions versioning details or security scanning in the repo

fd -e yml -e yaml . --max-depth 3 | grep -E "(workflow|action|security)" | head -20

Repository: reddb-io/red-request

Length of output: 158


🏁 Script executed:

# Let's verify the actual commit SHAs for actions/checkout@v7 and actions/setup-node@v6
# by checking GitHub's official releases

curl -s https://api.github.com/repos/actions/checkout/releases/tags/v7 | jq -r '.target_commitish' 2>/dev/null || echo "API check failed"
curl -s https://api.github.com/repos/actions/setup-node/releases/tags/v6 | jq -r '.target_commitish' 2>/dev/null || echo "API check failed"

Repository: reddb-io/red-request

Length of output: 168


🏁 Script executed:

# Let's also search for any existing hardening patterns or zizmor config in the repo

fd -name "*.mjs" -o -name "*.js" -o -name ".zizmor*" -o -name "*zizmor*" . --max-depth 3
rg "zizmor|persist-credentials|package-manager-cache" . --type yml --type yaml -C 2

Repository: reddb-io/red-request

Length of output: 417


🏁 Script executed:

# Check if there are other workflows in the repo and how they pin actions
rg "actions/(checkout|setup-node)" .github/workflows/ -A 2

Repository: reddb-io/red-request

Length of output: 2172


🏁 Script executed:

# Let's check if there's any documentation or comments in the repo about action pinning or security policies
rg "persist-credentials|package-manager-cache|full.commit.sha|SHA-pinned" . -i --type yaml -B 2 -A 2

Repository: reddb-io/red-request

Length of output: 158


🏁 Script executed:

# Check the .github directory structure to see if there are any security or dependabot configs
ls -la .github/

Repository: reddb-io/red-request

Length of output: 392


🏁 Script executed:

# Let's also verify whether these are legitimate security concerns by checking if there's any known vulnerability or recommendation
# for these specific action versions
cat .github/workflows/release.yml | grep -A 5 "checkout@v7\|setup-node@v6"

Repository: reddb-io/red-request

Length of output: 826


🌐 Web query:

actions/checkout@v7 SHA pinning security best practices GitHub Actions

💡 Result:

Pinning actions/checkout@v7 (or any third-party GitHub Action) to a full-length commit SHA is a recommended security best practice to prevent supply chain attacks [1][2][3]. ### Why SHA Pinning is Required By default, referencing actions by a tag (like @v7) is mutable, meaning the tag can be moved or deleted by an attacker who gains access to the repository, potentially leading to the execution of malicious code [1][2][3]. Pinning to an immutable, full-length commit SHA ensures that your workflow always executes the exact code you have audited [1][2][3]. ### How to Pin Correctly To maintain both security and readability, use the following pattern in your workflow files [3][4]: - uses: actions/checkout@9c091bb # v7.0.0 The full 40-character SHA provides security against repository compromise, while the trailing comment serves as a human-readable reference for version tracking [3][4]. You can retrieve the correct SHA for any tag using standard Git commands or the GitHub CLI [3]: # Using Git git ls-remote --tags https://github.com/actions/checkout.git v7.0.0 # Using GitHub CLI gh api repos/actions/checkout/git/ref/tags/v7.0.0 --jq '.object.sha' ### Operational Best Practices - Automation: Use tools like Dependabot or Renovate to manage these pins [5][3][4]. These tools can automatically open pull requests to update the SHA and comment when a new version is released, reducing the maintenance burden while maintaining security [5][3][6]. - Policy Enforcement: If you are an administrator, you can enforce SHA pinning at the repository, organization, or enterprise level via GitHub’s "allowed actions" policies [2][7][8]. When enabled, any workflow using a tag instead of a SHA will fail automatically [7][8]. - Security Context: Note that actions/checkout@v7 specifically introduces enhanced security protections against insecure pull request checkout patterns (such as in pull_request_target workflows) [9]. While upgrading to v7 provides these native safeguards, pinning remains a fundamental best practice for all actions to ensure supply chain integrity [1][3][9].

Citations:


🌐 Web query:

actions/setup-node package-manager-cache security risk cache poisoning

💡 Result:

The actions/setup-node action includes a feature that automatically caches dependencies by default when using npm [1][2]. This automatic caching introduces a potential security risk related to cache poisoning, particularly in privileged workflows [3][4]. If a workflow is compromised or if an attacker can manipulate the environment, they may be able to poison the cache [3]. A poisoned cache could lead to the execution of malicious code or the exfiltration of sensitive information, such as credentials or secrets, during subsequent workflow runs [3][5]. This is a particular concern in workflows that have elevated privileges or access to high-value secrets [3][1]. To mitigate this risk, the following recommendations are provided by the official documentation: 1. Disable automatic caching: For workflows with elevated privileges or access to sensitive information, it is strongly recommended to set package-manager-cache: false in your setup-node step [1][2]. This prevents the action from automatically caching or restoring dependencies [3]. 2. Use explicit configurations: By disabling automatic caching, you maintain more control over the caching process [3]. If you require caching for performance, ensure it is configured explicitly and securely [3]. 3. Maintain lockfiles: Always commit your package manager's lockfile (e.g., package-lock.json). This ensures consistent dependency resolution and is a best practice for security and performance [1][6]. The maintainers of actions/setup-node have noted that the action cannot automatically detect if it is running in a privileged context, making manual configuration by the workflow author the primary defense [4]. Consequently, disabling automatic caching is the most effective way to eliminate this specific attack vector in sensitive environments [3][5].

Citations:


Harden the preflight job actions: SHA-pin to full commit SHA and disable setup-node package-manager cache.

actions/checkout@v7 and actions/setup-node@v6 are not pinned to immutable commit SHAs. The preflight job accesses secrets and makes API calls, making it sensitive to supply chain attack and cache poisoning risks. Disable package-manager caching here since this job does not need it.

🔧 Suggested hardening changes
-      - uses: actions/checkout@v7
+      - uses: actions/checkout@<full_commit_sha>
         with:
           ref: ${{ github.event.inputs.tag || github.ref }}
+          persist-credentials: false

-      - uses: actions/setup-node@v6
+      - uses: actions/setup-node@<full_commit_sha>
         with:
           node-version: "22"
+          package-manager-cache: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 33-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 33-33: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 37-37: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 37-37: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default

(cache-poisoning)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 33 - 40, The actions/checkout@v7
and actions/setup-node@v6 in the preflight job are not pinned to immutable
commit SHAs, creating supply chain attack risks since this job accesses secrets.
Replace the version tags (v7 and v6) with their full commit SHAs to harden
against tampering. Additionally, disable package-manager caching in the
setup-node action by adding the cache configuration set to false, since this
preflight job does not require dependency caching.

Source: Linters/SAST tools

- name: Check RedDB sidecar release assets
run: node scripts/check-reddb-release-assets.mjs x86_64-unknown-linux-gnu x86_64-pc-windows-msvc
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build:
name: ${{ matrix.label }}
needs: preflight
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
- Prefer indexed lookups, single-pass loops, lazy or partial rendering, storage-side filtering, and realistic fixtures over speculative rewrites.
- Add or update lightweight perf workloads when touching hot paths. Benchmarks can start non-blocking, but visible regressions should become hard to ignore.
- For Rust/Tauri performance work, profile release builds before invasive changes; keep `cargo fmt`, Clippy, frame-pointer/debug-info profiling, LTO, allocator, and PGO decisions tied to evidence.
- Use `Release Fast` for a Linux `.deb` packaging smoke test; keep `Release` as the full Linux/macOS/Windows publishing path. RedDB sidecar assets must pass preflight before spending matrix time.
- Treat `lto`, `codegen-units`, `strip`, allocator swaps, and PGO as measured release-profile experiments. Avoid `target-cpu=native` for public binaries unless distribution compatibility is intentionally narrowed.

## Agent skills

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"desktop:dev": "pnpm brand:sync && pnpm --filter @red-request/core build && pnpm --filter @red-request/engine build && pnpm --filter @red-request/desktop tauri dev",
"desktop:build": "pnpm brand:sync && pnpm brand:icons && pnpm --filter @red-request/core build && pnpm engine:build && pnpm --filter @red-request/desktop tauri build",
"engine:build": "node scripts/build-engine.mjs",
"reddb:preflight": "node scripts/check-reddb-release-assets.mjs x86_64-unknown-linux-gnu x86_64-pc-windows-msvc",
"reddb:sync": "node scripts/sync-reddb.mjs",
"reddb:fetch": "node scripts/fetch-reddb.mjs",
"reddb:migration-demo": "node scripts/reddb-migration-demo.mjs",
Expand Down
78 changes: 78 additions & 0 deletions scripts/check-reddb-release-assets.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env node
// Fast release preflight for the embedded RedDB sidecar.
//
// The desktop app cannot be packaged for Linux/Windows unless the pinned RedDB
// release exposes the prebuilt `red-<os>-<arch>` assets that fetch-reddb.mjs
// downloads. Check that up front so release jobs fail before runner setup,
// dependency install, and Tauri packaging work.
//
// REDDB_VERSION=v1.11.0 node scripts/check-reddb-release-assets.mjs \
// x86_64-unknown-linux-gnu x86_64-pc-windows-msvc
import { env, exit } from "node:process";

const REPO = "reddb-io/reddb";

function assetName(triple) {
const [arch] = triple.split("-");
const os = triple.includes("linux")
? "linux"
: triple.includes("darwin")
? "darwin"
: triple.includes("windows")
? "windows"
: null;
if (!os) throw new Error(`unsupported target triple: ${triple}`);
const ext = os === "windows" ? ".exe" : "";
return `red-${os}-${arch}${ext}`;
}

async function ghJson(path) {
const headers = {
Accept: "application/vnd.github+json",
"User-Agent": "red-request-reddb-preflight",
};
if (env.GITHUB_TOKEN) headers.Authorization = `Bearer ${env.GITHUB_TOKEN}`;
const res = await fetch(`https://api.github.com/${path}`, { headers });
if (!res.ok) throw new Error(`${path} -> ${res.status} ${res.statusText}`);
return res.json();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

const targets = process.argv.slice(2);
if (targets.length === 0) {
console.error("usage: check-reddb-release-assets.mjs <target-triple> [...]");
exit(2);
}

const required = targets.map(assetName);
const tag = env.REDDB_VERSION;

let release;
try {
release = tag
? await ghJson(`repos/${REPO}/releases/tags/${encodeURIComponent(tag)}`)
: await ghJson(`repos/${REPO}/releases/latest`);
} catch (err) {
console.error(`RedDB release preflight failed: ${err.message}`);
console.error(
"Publish the pinned RedDB release, fix REDDB_VERSION, or build the sidecar from source."
);
exit(1);
}

const available = new Set((release.assets ?? []).map((asset) => asset.name));
const missing = required.filter((name) => !available.has(name));

if (missing.length > 0) {
console.error(
`RedDB ${release.tag_name} is missing required release assets:`
);
for (const name of missing) console.error(` - ${name}`);
console.error("");
console.error("Available assets:");
for (const name of [...available].sort()) console.error(` - ${name}`);
exit(1);
}

console.log(
`RedDB ${release.tag_name} has required assets: ${required.join(", ")}`
);