Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changeset/cool-oranges-cut.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@calycode/cli": minor
---

refactor: fixed several inconsistencies with the native host implementation
5 changes: 5 additions & 0 deletions .changeset/pretty-dodos-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@calycode/cli": patch
---

refactor: adjusted extension id discovery
5 changes: 5 additions & 0 deletions .changeset/solid-carpets-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@calycode/cli": minor
---

feat: downloadable bootstrapper for the cli for windows and mac os
87 changes: 87 additions & 0 deletions .github/workflows/build-bootstrapper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# .github/workflows/build-bootstrapper.yml
name: Build Bootstrapper

on:
push:
branches:
- main
paths:
- "bootstrapper/**"
- ".github/workflows/build-bootstrapper.yml"
workflow_dispatch:
release:
types: [published]

permissions:
contents: write

jobs:
build:
name: Build all targets
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5

- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff
with:
go-version: "1.21"
Comment on lines +23 to +29

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/build-bootstrapper.yml"

if [ ! -f "$FILE" ]; then
  echo "Missing $FILE"
  exit 1
fi

echo "=== File: $FILE ==="
nl -ba "$FILE" | sed -n '1,200p'

Repository: calycode/xano-tools

Length of output: 180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/build-bootstrapper.yml"

if [ ! -f "$FILE" ]; then
  echo "Missing $FILE"
  exit 1
fi

echo "=== File: $FILE ==="
awk '{printf "%4d\t%s\n", NR, $0}' "$FILE" | sed -n '1,200p'

Repository: calycode/xano-tools

Length of output: 3447


🌐 Web query:

actions/checkout persist-credentials default true behavior git push

💡 Result:

The persist-credentials input for the actions/checkout GitHub Action has a default value of true [1][2]. When persist-credentials is set to true (the default), the action configures the runner's local Git environment with the authentication token provided to the workflow (typically the GITHUB_TOKEN) [1][3]. This allows subsequent steps in your job to execute authenticated Git commands—such as git fetch or git push—without requiring additional authentication setup [1][2][3]. Recent updates to actions/checkout have improved the security of this feature by storing these credentials in a separate file within the runner's temporary directory ($RUNNER_TEMP) rather than directly inside the repository's .git/config [2][3][4]. The action still performs cleanup by removing these credentials during the post-job phase [1][3]. If you set persist-credentials: false, the action will not persist these credentials into the Git configuration [1][5]. While this is considered a recommended security best practice to reduce potential credential exposure [5][6][7], it means you must handle Git authentication manually in any subsequent steps where you need to perform authorized operations like git push (e.g., by using an alternative authentication method or configuring credentials explicitly) [8][9][7].

Citations:


🌐 Web query:

actions/checkout release.published event which ref it checks out github.sha tag commit

💡 Result:

For a workflow triggered by the GitHub release event types (e.g., on: release: types: [published]), actions/checkout checks out the ref or SHA for the workflow trigger event; by default it uses “the reference or SHA for that event” (unless you set inputs.ref explicitly) [1]. So, if you configure actions/checkout without specifying ref, the commit it checks out corresponds to the commit SHA that GitHub Actions associates with that release event (i.e., the event’s ref/SHA), rather than a branch name [1]. If you want to be explicit in the release.published workflow, set the checkout ref to the commit SHA you intend to build (commonly derived from the event payload via the github.* context), using actions/checkout’s ref input which accepts a branch, tag, or SHA [1]. Note: This is consistent with actions/checkout’s documented behavior that the default checkout for the “repository that triggered a workflow” is the reference or SHA for that event, and it only fetches a single commit by default for that ref/SHA [1].

Citations:


🌐 Web query:

GitHub tag name allowed characters restrictions for shell injection

💡 Result:

Git/GitHub tag names aren’t “specially restricted” to prevent shell injection; instead, Git allows a fairly wide character set, and shell-injection risk comes from how tag strings are interpolated into shell commands by downstream tooling. 1) What characters are allowed for Git tag names (the practical restrictions) - Git is very permissive about what characters may appear in branch and tag names; you may need to escape/quote special characters when using the names in a command-line shell. GitHub’s docs note that Git has “very few restrictions” and only calls out exceptions like slash placement/duplication. [1] - For the underlying ref-name rules, Git’s check-ref-format documentation specifies key constraints for reference names: - A ref component cannot begin with “.” and cannot end with “.lock”. [2] - A ref cannot begin or end with “/” and cannot contain multiple consecutive “/”. [2] - A ref must contain at least one “/” in general (because refs are in hierarchies like heads/ or tags/); for one-level refs this rule can be waived with an option, but normal refnames (like refs/tags/…) do include “/”. [2] - A refname cannot contain the sequence “@{”. [2] (These are the main “format” restrictions Git enforces; they’re about ref parsing/semantics, not about preventing shell meta-characters like; or |.) - GitHub also adds a small additional push-time restriction on names that look like Git object IDs and on names beginning with “refs/” to avoid confusion. [1] 2) Why this relates to shell injection (what the “allowed characters restrictions” really mean) - The relevant security issue is not “GitHub’s tag character policy”; it’s whether a tag string (often from GITHUB_REF / user input) is inserted into a shell command string and executed with a shell. - A concrete example: an action had a bug where attacker-controlled “tag” input could run arbitrary shell commands; the fix was to properly quote/escape the tag string before passing it to exec. [3] 3) Safe guidance for preventing shell injection with tag values - Treat tag strings as untrusted input and do not concatenate them into shell command strings. - Prefer APIs that avoid a shell (e.g., spawn/execFile-style parameter passing rather than exec with a single command line). - If you must use a shell command string, you must quote/escape arguments so shell metacharacters are not interpreted. The referenced fix escapes the tag argument and wraps it in single quotes. [3] - Even with quoting, ensure your quoting context matches how the command is executed; security guidance emphasizes that quoting/escaping alone can be unreliable if you pass untrusted input into a shell without controlling the interpreter behavior. [4] 4) Practical “safe allowlist” approach (what to use instead of relying on GitHub/Git rules) - GitHub suggests using a safe default set of characters for branch/tag names to avoid needing escapes when working in shells: English letters (A–Z, a–z), digits (0–9), and punctuation. - _ /. [1] Answer in one line: There isn’t a GitHub-specific “shell-injection-safe” character restriction for tag names; Git allows many characters, and shell injection is prevented by handling tag strings as untrusted and avoiding/quoting shell interpretation when building commands. [1][2][3]

Citations:


Harden the workflow: pin actions and fix checkout-credentials handling for the tag push.

  • Pin actions/checkout@v4 and actions/setup-go@v5 to commit SHAs (supply-chain hardening).
  • Checkout currently keeps persisted Git credentials (no persist-credentials: false). The workflow later runs git push in Update bootstrapper-latest tag, so setting persist-credentials: false without adding explicit git auth would break the job—either keep persisted credentials or update the workflow to authenticate git push explicitly before that step.
  • gh release upload uses ${{ github.event.release.tag_name }} directly in the run: shell line; move it to an environment variable (e.g., env: RELEASE_TAG: ... and use "$RELEASE_TAG") to avoid shell interpretation risks from tag names.
  • On release.published, default checkout is the event’s ref/SHA, so bootstrapper-latest will track the release-tag commit (not necessarily the main HEAD), matching the job’s actual behavior.
Suggested hardening patch (pin actions; checkout auth needs follow-up)
-         - name: Checkout
-           uses: actions/checkout@v4
+         - name: Checkout
+           uses: actions/checkout@<PINNED_COMMIT_SHA_FOR_V4>
 
-         - name: Setup Go
-           uses: actions/setup-go@v5
+         - name: Setup Go
+           uses: actions/setup-go@<PINNED_COMMIT_SHA_FOR_V5>
            with:
               go-version: "1.21"
🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


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

(unpinned-uses)


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

(unpinned-uses)


[error] 27-27: 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/build-bootstrapper.yml around lines 23 - 29, Pin the
GitHub actions used (actions/checkout and actions/setup-go) to specific commit
SHAs instead of floating tags to harden supply chain; for the Checkout step
adjust the persist-credentials setting—either keep persist-credentials: true so
the later "Update bootstrapper-latest tag" git push works, or set
persist-credentials: false and add an explicit authentication step before that
push (e.g., gh auth login or setting GITHUB_TOKEN) to ensure git push can
authenticate; move the release tag usage in the "gh release upload" run into an
environment variable (e.g., env: RELEASE_TAG: ${{ github.event.release.tag_name
}}) and reference it as "$RELEASE_TAG" in the shell command to avoid
shell-interpretation issues; verify behavior on release.published matches
expectations (checkout will be at the release ref).


- name: Build Windows x64
working-directory: bootstrapper
run: |
mkdir -p dist
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -ldflags "-s -w -H=windowsgui" \
-o dist/calycode-installer-windows-x64.exe \
.

- name: Build macOS x64
working-directory: bootstrapper
run: |
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 \
go build -ldflags "-s -w" \
-o dist/calycode-installer-darwin-x64 \
.
cd dist
zip -9 calycode-installer-darwin-x64.zip calycode-installer-darwin-x64

- name: Build macOS arm64
working-directory: bootstrapper
run: |
GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 \
go build -ldflags "-s -w" \
-o dist/calycode-installer-darwin-arm64 \
.
cd dist
zip -9 calycode-installer-darwin-arm64.zip calycode-installer-darwin-arm64

- name: Generate checksums
working-directory: bootstrapper/dist
run: sha256sum * > SHA256SUMS

# --- Release attachment ---
# Triggered by changesets creating a GitHub Release after npm publish.
# `gh release upload` attaches to the release that fired this workflow.
- name: Attach binaries to GitHub Release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
gh release upload "$RELEASE_TAG" \
bootstrapper/dist/calycode-installer-windows-x64.exe \
bootstrapper/dist/calycode-installer-darwin-x64.zip \
bootstrapper/dist/calycode-installer-darwin-arm64.zip \
bootstrapper/dist/SHA256SUMS \
--clobber

# --- Floating tag ---
# Keeps `bootstrapper-latest` pointing at HEAD so
# dev builds are always downloadable at a stable URL.
- name: Update bootstrapper-latest tag
if: github.event_name == 'push'
run: |
git tag -f bootstrapper-latest
git push -f origin bootstrapper-latest
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ jobs:
NPM_CONFIG_PROVENANCE: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
CALY_BUILD_OC_EXT_PUBLIC_KEY_B64: ${{ secrets.CALY_BUILD_OC_EXT_PUBLIC_KEY_B64 }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,8 @@ coverage/
# Native binary assets
**/*/.sea-cache/

# Local planning docs
plans/native-host-security-hardening.md

# Xano's ai supporting assets:
util-resources/xano-agentic-setups/
util-resources/xano-agentic-setups/
48 changes: 48 additions & 0 deletions bootstrapper/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# CalyCode Bootstrapper Build
# Produces standalone installers for Windows (exe) and macOS (macho binary).
#
# Prerequisites: Go 1.21+
#
# Usage:
# make all Build all targets
# make windows Build Windows .exe (from any OS)
# make darwin-amd64 Build macOS Intel binary
# make darwin-arm64 Build macOS Apple Silicon binary
# make clean Remove build artifacts

OUT_DIR := dist
BINARY := calycode-installer
MODULE := github.com/calycode/xano-tools/bootstrapper

.PHONY: all windows darwin-amd64 darwin-arm64 clean

all: windows darwin-amd64 darwin-arm64

$(OUT_DIR):
mkdir -p $(OUT_DIR)

windows: $(OUT_DIR)
@echo "Building Windows x64..."
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build \
-ldflags "-s -w -H=windowsgui" \
-o $(OUT_DIR)/$(BINARY)-windows-x64.exe \
$(MODULE)

darwin-amd64: $(OUT_DIR)
@echo "Building macOS Intel x64..."
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build \
-ldflags "-s -w" \
-o $(OUT_DIR)/$(BINARY)-darwin-x64 \
$(MODULE)
cd $(OUT_DIR) && zip -9 $(BINARY)-darwin-x64.zip $(BINARY)-darwin-x64

darwin-arm64: $(OUT_DIR)
@echo "Building macOS Apple Silicon..."
GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build \
-ldflags "-s -w" \
-o $(OUT_DIR)/$(BINARY)-darwin-arm64 \
$(MODULE)
cd $(OUT_DIR) && zip -9 $(BINARY)-darwin-arm64.zip $(BINARY)-darwin-arm64

clean:
rm -rf $(OUT_DIR)
3 changes: 3 additions & 0 deletions bootstrapper/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/calycode/xano-tools/bootstrapper

go 1.21
Loading