Skip to content

Fix/export sandbox security - #459

Open
harsh21234i wants to merge 3 commits into
reflex-dev:mainfrom
harsh21234i:fix/export-sandbox-security-449
Open

Fix/export sandbox security #459
harsh21234i wants to merge 3 commits into
reflex-dev:mainfrom
harsh21234i:fix/export-sandbox-security-449

Conversation

@harsh21234i

@harsh21234i harsh21234i commented Aug 5, 2026

Copy link
Copy Markdown

Closses #449

Summary

  • Make Chromium export fail closed when sandboxed launch fails.
  • Remove automatic retries with --no-sandbox.
  • Keep sandbox=False as the explicit caller opt-out.
  • Add regression coverage for both export paths.
  • Add dependency lockfile inventory validation.
  • Add scheduled audits for Python, Rust, npm, Bun, and benchmark dependencies.
  • Update security and production-readiness documentation.
  • Include dependency inventory checks in make check-security.

Testing

  • 54 passed
  • Ruff checks passed
  • Dependency lockfile inventory passed
  • Security workflow YAML validated
  • make check-security checks passed locally

Review in cubic

Summary by CodeRabbit

  • Security

    • Browser-based image exports now fail safely when sandboxed Chromium cannot start, without automatically retrying in an unsandboxed mode.
    • Added scheduled dependency security auditing across Python, Rust, npm, and Bun projects.
  • New Features

    • Added documented APIs for controlling chart view ranges, selections, and view state.
    • Added Selection.rows() documentation for retrieving selected rows with an optional limit.
  • Documentation

    • Improved API references, security guidance, and production-readiness documentation.
  • Quality Improvements

    • Expanded local documentation, dependency, and public API validation checks.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds fail-closed Chromium behavior, scheduled dependency audits, local documentation checks, and reflective public API validation. It also documents view, selection, callback, and security behavior and updates related tests.

Changes

Security controls

Layer / File(s) Summary
Fail-closed Chromium exports
python/xy/export.py, tests/test_figure.py, tests/test_image_export.py, SECURITY.md, spec/process/*
Chromium failures no longer trigger an automatic unsandboxed retry. Tests and security documentation require explicit unsandboxed execution.
Dependency audit and lock inventory
.github/workflows/security-audit.yml, scripts/verify_dependency_lock_inventory.py, scripts/verify_local.py, Makefile
The repository verifies expected lockfiles and audits Python, Rust, npm, and Bun dependencies through local and scheduled checks.

Documentation quality

Layer / File(s) Summary
Local documentation verification
scripts/verify_docs_local.py, scripts/verify_local.py, Makefile
Local checks now run documentation tests, quickstart validation, Ruff, and codespell, with failures returned immediately.

Public API validation

Layer / File(s) Summary
Reflective API inventory
scripts/check_public_api.py
Public component exports and Chart and Selection methods are derived through reflection and annotations.
API documentation and contract checks
scripts/check_public_api.py, docs/api-reference/events-and-callbacks.md, docs/api-reference/figure-methods.md, tests/test_public_api.py
The checker validates API-reference coverage. Documentation adds Selection.rows and view and selection state APIs.
API fixture and type-surface tests
tests/test_public_api.py, tests/test_type_surface.py
Tests use concrete exports and reflective inventories to validate public factories, return types, chart construction, and Selection.rows typing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

  • reflex-dev/xy#451: Both changes modify public API validation, including scripts/check_public_api.py.
  • reflex-dev/xy#458: Shares the public API inventory, API documentation, and documentation-check changes.

Suggested reviewers: alek99

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: fixing sandbox security for Chromium exports.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes Chromium exports fail closed instead of retrying without sandboxing, and adds scheduled dependency audits plus committed-lockfile inventory validation.

  • Removes implicit unsandboxed retries from both Chromium export paths.
  • Adds regression tests for fail-closed browser launches.
  • Adds Python, Rust, npm, Bun, and benchmark dependency auditing.
  • Integrates dependency inventory validation into make check-security.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains, and the previous filesystem-scan issue is resolved because inventory discovery now considers only Git-tracked files.

Important Files Changed

Filename Overview
python/xy/export.py Removes automatic unsandboxed Chromium fallback while preserving explicit sandbox=False behavior.
scripts/verify_dependency_lock_inventory.py Uses Git’s tracked-file inventory, resolving the prior false failures caused by gitignored or untracked local lockfiles.
.github/workflows/security-audit.yml Adds scheduled and lockfile-triggered audits across the repository’s dependency ecosystems.
scripts/verify_local.py Registers dependency lock inventory validation with the local verification harness.
tests/test_figure.py Updates single-shot Chromium export coverage to require fail-closed sandbox behavior.
tests/test_image_export.py Adds persistent-session coverage ensuring sandbox launch failures are not retried unsandboxed.

Reviews (4): Last reviewed commit: "Harden lock inventory error handling" | Re-trigger Greptile

Comment thread scripts/verify_dependency_lock_inventory.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (6)
scripts/check_public_api.py (3)

222-227: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider reporting annotation resolution failures.

_return_type_name returns None for every exception. An export with an unresolvable return annotation is then reported only as "unclassified", which hides the real cause. validate_public_api_inventory still fails, so the checker does not pass silently. Surfacing the original exception would shorten diagnosis.

🤖 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 `@scripts/check_public_api.py` around lines 222 - 227, Update _return_type_name
to report annotation-resolution exceptions while preserving its existing None
return behavior, including the original exception details in the diagnostic
output so unresolvable return annotations can be diagnosed.

340-381: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hoist the Selection dunder alias map next to its discovery constant.

SPECIAL_PUBLIC_SELECTION_METHODS at Line 55 decides which dunders enter the inventory. selection_aliases at Line 373 decides how each dunder is matched in the documentation. The two lists must stay in agreement. If a second dunder joins the public Selection surface and only Line 55 is updated, validate_docs_inventory demands a literal `__name__` token and reports a missing document entry even when the documentation uses the idiomatic form.

Define the alias map as a module constant beside Line 55 and derive the special-method set from its keys.

Separately, note that _has_doc_reference matches bare substrings such as rows(. An incidental mention in the documentation satisfies the check. The consequence is missed drift, not a false failure.

♻️ Proposed single source for the alias map
-SPECIAL_PUBLIC_SELECTION_METHODS = {"__len__"}
+SELECTION_METHOD_DOC_ALIASES = {"__len__": "len(selection)"}
+SPECIAL_PUBLIC_SELECTION_METHODS = set(SELECTION_METHOD_DOC_ALIASES)
-    selection_aliases = {"__len__": "len(selection)"}
     for method in inventory.selection_methods:
-        token = selection_aliases.get(method)
+        token = SELECTION_METHOD_DOC_ALIASES.get(method)
🤖 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 `@scripts/check_public_api.py` around lines 340 - 381, Move the Selection
dunder alias mapping beside SPECIAL_PUBLIC_SELECTION_METHODS, derive that set
from the alias-map keys, and update validate_docs_inventory to reuse the
module-level map. Also tighten _has_doc_reference so bare method references such
as rows( require an actual documentation reference rather than matching
incidental substrings.

261-275: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

_public_methods misses inherited public methods.

The loop reads only cls.__dict__. Inherited public methods are not discovered. Today Chart and Selection define their public methods locally, so the inventory is complete. If either class later gains a base class that carries public methods, the inventory under-reports the surface. validate_docs_inventory then stops requiring documentation for those methods, which defeats the drift check.

Consider walking the MRO and excluding object.

♻️ Proposed MRO-aware collection
 def _public_methods(
     cls: type[Any],
     *,
     special_public_methods: set[str],
 ) -> tuple[str, ...]:
     methods: list[str] = []
-    for name, value in cls.__dict__.items():
-        if name == "__init__":
-            continue
-        if not callable(value) and not isinstance(value, property):
-            continue
-        if name.startswith("_") and name not in special_public_methods:
-            continue
-        methods.append(name)
+    seen: set[str] = set()
+    for klass in cls.__mro__:
+        if klass is object:
+            continue
+        for name, value in klass.__dict__.items():
+            if name == "__init__" or name in seen:
+                continue
+            if not callable(value) and not isinstance(value, property):
+                continue
+            if name.startswith("_") and name not in special_public_methods:
+                continue
+            seen.add(name)
+            methods.append(name)
     return tuple(methods)
🤖 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 `@scripts/check_public_api.py` around lines 261 - 275, Update `_public_methods`
to collect public callables from the class MRO instead of only `cls.__dict__`,
while still skipping `object` and preserving the existing `__init__` and
underscore/special-public filtering. Use the same `special_public_methods`
handling when walking base classes so inherited methods on classes like `Chart`
and `Selection` are included in the inventory and still flow correctly into
`validate_docs_inventory`.
tests/test_public_api.py (2)

293-320: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The fake modules do not isolate this test from the real package.

fake is named "xy". build_public_api_inventory runs importlib.import_module("._figure", pkg.__name__) at scripts/check_public_api.py Line 298, so it imports the real xy._figure and reflects the real Selection. validate_declarative_api_contract then calls validate_docs_inventory(inventory) at Line 441 with the default CHART_METHOD_DOC and SELECTION_METHOD_DOC paths, so it reads the real documentation files.

The effect: test_public_api_checker_accepts_declarative_api_contract asserts errors == [], and that assertion depends on real Selection methods and real documentation content. It passes now only because the fake Chart.figure and Chart.html names also appear in docs/api-reference/figure-methods.md. If a public method is added to the real Selection without documentation, this fixture-based test fails with a Selection error that names neither the fixture nor the real cause.

Accept the Selection source and the documentation paths as parameters of build_public_api_inventory and validate_declarative_api_contract, then inject fakes here.

🤖 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 `@tests/test_public_api.py` around lines 293 - 320, Parameterize
build_public_api_inventory and validate_declarative_api_contract to accept the
Selection source and chart/selection documentation paths instead of relying on
real package modules and default constants. Update this fixture to provide fake
Selection data and temporary or fixture-specific documentation paths, ensuring
test_public_api_checker_accepts_declarative_api_contract validates only the
constructed fake API.

385-398: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the __len__ alias branch.

selection_methods includes __len__, and the temporary document contains len(selection). No assertion covers that pairing. If the selection_aliases mapping in validate_docs_inventory were removed, __len__ would fall through to _has_doc_reference, none of whose tokens appear in the written text, and an error would be reported. Every current assertion would still pass, because none mentions __len__. Add the negative assertion to pin the alias behavior.

💚 Proposed assertion
     assert not any("visible_method" in error for error in errors)
     assert not any("'rows'" in error for error in errors)
+    assert not any("__len__" in error for error in errors)
🤖 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 `@tests/test_public_api.py` around lines 385 - 398, Add an assertion in
validate_docs_inventory coverage to explicitly verify the __len__ alias path in
selection_methods. Use the existing check_public_api.validate_docs_inventory
call and the current selection_doc setup, and assert that no error entry
contains "__len__" so the selection_aliases mapping remains required and the
alias continues to resolve through len(selection).
tests/test_type_surface.py (1)

31-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Deriving the expected inventory from the code under test removes the removal signal.

MARK_FACTORIES, CHART_FACTORIES, CHROME_FACTORIES, SUPPORT_FACTORIES, and CHART_READOUTS now come from reflection over components.__all__ and the Chart class. The previous hard-coded lists acted as an independent expectation.

Concrete consequence: if a factory is dropped from components.__all__, it also disappears from the derived tuple. test_public_factories_are_typed_root_exports and test_composition_alpha_contract_is_explicitly_exported then iterate fewer names and still pass. validate_public_api_inventory in scripts/check_public_api.py does not close this gap, because it only checks that each listed export is classified.

Keep one independent expectation. A minimum-count assertion, or an explicit frozen set of names that must always be present, restores the signal without reintroducing full hard-coded lists.

🤖 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 `@tests/test_type_surface.py` around lines 31 - 42, Restore an independent
expectation in tests/test_type_surface.py for the reflected public API
inventory: add either minimum-count assertions or a frozen required-name set
covering MARK_FACTORIES, CHART_FACTORIES, CHROME_FACTORIES, SUPPORT_FACTORIES,
and CHART_READOUTS. Ensure tests such as
test_public_factories_are_typed_root_exports and
test_composition_alpha_contract_is_explicitly_exported still fail when an
expected export is removed from components.__all__ or Chart.
🤖 Prompt for all review comments with 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.

Inline comments:
In @.github/workflows/security-audit.yml:
- Around line 27-29: Update the actions/checkout step in the security-audit
workflow to set persist-credentials to false alongside fetch-depth, ensuring the
workflow token is not retained before dependency installation.
- Line 65: Replace the unpinned npm-based Bun installation in the security-audit
workflow with an integrity-pinned bootstrap: use a setup action pinned to a
commit SHA, or download the official Bun release and verify its checksum before
execution. Preserve the required Bun version while ensuring the installed binary
is independently authenticated.

In `@docs/api-reference/figure-methods.md`:
- Around line 109-126: Update the select() entry in the “View and Selection
State” documentation to describe Chart.select’s keyword-only range, polygon,
rows, and history parameters, removing the unsupported positional selection and
source arguments. Revise the accompanying description to reflect applying these
supported selection options through the chart state path.

In `@scripts/check_public_api.py`:
- Around line 437-441: Update the validation loop over inventory.chart_methods
to accept property descriptors as valid readouts, matching the property handling
already allowed by _public_methods, while continuing to require other entries to
be callable. Preserve the existing error for names that are neither callable nor
properties.

In `@scripts/verify_dependency_lock_inventory.py`:
- Around line 34-37: Update the lockfile discovery loop in the inventory
function to use os.walk with top-down traversal, removing names in
EXCLUDED_DIRECTORIES from dirnames before descending. Preserve the existing file
checks and _is_lockfile filtering for traversed files, while avoiding traversal
into excluded directories such as node_modules, .venv, and target.

In `@scripts/verify_docs_local.py`:
- Around line 19-60: Update the local docs setup or verification flow around the
existing docs/app commands to run “uv sync --project docs/app --frozen --group
dev” before any --no-sync checks, ensuring the docs environment is synchronized
without changing the subsequent test and lint commands.

---

Nitpick comments:
In `@scripts/check_public_api.py`:
- Around line 222-227: Update _return_type_name to report annotation-resolution
exceptions while preserving its existing None return behavior, including the
original exception details in the diagnostic output so unresolvable return
annotations can be diagnosed.
- Around line 340-381: Move the Selection dunder alias mapping beside
SPECIAL_PUBLIC_SELECTION_METHODS, derive that set from the alias-map keys, and
update validate_docs_inventory to reuse the module-level map. Also tighten
_has_doc_reference so bare method references such as rows( require an actual
documentation reference rather than matching incidental substrings.
- Around line 261-275: Update `_public_methods` to collect public callables from
the class MRO instead of only `cls.__dict__`, while still skipping `object` and
preserving the existing `__init__` and underscore/special-public filtering. Use
the same `special_public_methods` handling when walking base classes so
inherited methods on classes like `Chart` and `Selection` are included in the
inventory and still flow correctly into `validate_docs_inventory`.

In `@tests/test_public_api.py`:
- Around line 293-320: Parameterize build_public_api_inventory and
validate_declarative_api_contract to accept the Selection source and
chart/selection documentation paths instead of relying on real package modules
and default constants. Update this fixture to provide fake Selection data and
temporary or fixture-specific documentation paths, ensuring
test_public_api_checker_accepts_declarative_api_contract validates only the
constructed fake API.
- Around line 385-398: Add an assertion in validate_docs_inventory coverage to
explicitly verify the __len__ alias path in selection_methods. Use the existing
check_public_api.validate_docs_inventory call and the current selection_doc
setup, and assert that no error entry contains "__len__" so the
selection_aliases mapping remains required and the alias continues to resolve
through len(selection).

In `@tests/test_type_surface.py`:
- Around line 31-42: Restore an independent expectation in
tests/test_type_surface.py for the reflected public API inventory: add either
minimum-count assertions or a frozen required-name set covering MARK_FACTORIES,
CHART_FACTORIES, CHROME_FACTORIES, SUPPORT_FACTORIES, and CHART_READOUTS. Ensure
tests such as test_public_factories_are_typed_root_exports and
test_composition_alpha_contract_is_explicitly_exported still fail when an
expected export is removed from components.__all__ or Chart.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f22a4bd-7ebe-48f2-9af0-7dfe2c809cca

📥 Commits

Reviewing files that changed from the base of the PR and between 37c3d91 and 7c236fa.

📒 Files selected for processing (16)
  • .github/workflows/security-audit.yml
  • Makefile
  • SECURITY.md
  • docs/api-reference/events-and-callbacks.md
  • docs/api-reference/figure-methods.md
  • python/xy/export.py
  • scripts/check_public_api.py
  • scripts/verify_dependency_lock_inventory.py
  • scripts/verify_docs_local.py
  • scripts/verify_local.py
  • spec/process/production-readiness.md
  • spec/process/security-audit-2026-07-06.md
  • tests/test_figure.py
  • tests/test_image_export.py
  • tests/test_public_api.py
  • tests/test_type_surface.py

Comment thread .github/workflows/security-audit.yml

- name: Audit Bun lock
run: |
npm install --global bun@1.2.20

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 | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
file=".github/workflows/security-audit.yml"
printf '%s\n' '--- workflow excerpt ---'
sed -n '1,110p' "$file"
printf '%s\n' '--- related workflow references ---'
rg -n -C 2 'bun|npm install|audit|workflow_dispatch|pull_request|push|permissions|runs-on' .github/workflows "$file" 2>/dev/null || true

Repository: reflex-dev/xy

Length of output: 43325


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import json, urllib.request
url = "https://registry.npmjs.org/bun/1.2.20"
with urllib.request.urlopen(url, timeout=15) as r:
    data = json.load(r)
print("name:", data.get("name"))
print("version:", data.get("version"))
print("scripts:", json.dumps(data.get("scripts", {}), sort_keys=True))
print("dist:", json.dumps({
    k: data.get("dist", {}).get(k)
    for k in ("tarball", "integrity", "shasum")
}, sort_keys=True))
PY

Repository: reflex-dev/xy

Length of output: 2437


🌐 Web query:

npm bun 1.2.20 package.json scripts postinstall dist integrity

💡 Result:

In Bun, including version 1.2.20, the handling of package.json scripts like postinstall is distinct from npm due to a "default-secure" security model [1][2][3]. 1. Default Security Behavior: Bun does not execute arbitrary lifecycle scripts (such as postinstall, preinstall, or prepare) for installed dependencies by default [1][2][3]. This is done to mitigate the security risks associated with running unknown code during package installation [1][2][3]. 2. Opt-in via trustedDependencies: To run lifecycle scripts for specific packages, you must explicitly allow them by adding the package name to the trustedDependencies array in your root package.json [1][2][3]. Once added, Bun will execute the lifecycle scripts for those packages upon installation [1][2][3]. 3. Project-Level Scripts: Bun does execute lifecycle scripts defined in your own project's package.json at the appropriate time when you run commands like bun install [1][4]. 4. Integrity and dist: Bun verifies the integrity of downloaded packages [1][4]. Recent updates, including those relevant to the 1.2.x series, have improved how Bun handles and stores integrity hashes (such as sha512) in the lockfile for various dependency types, including remote tarballs, to ensure consistency and security [5]. 5. Dist/Optimization: Bun automatically optimizes postinstall scripts for certain popular packages (e.g., esbuild, sharp) by determining if they are necessary, though this behavior can be configured or disabled using specific environment variables like BUN_FEATURE_FLAG_DISABLE_NATIVE_DEPENDENCY_LINKER [1][4]. For your specific scenario, if you are expecting a postinstall script to run for a dependency and it is not, ensure the package is listed in your package.json's trustedDependencies [1][2]. Integrity verification is handled automatically by Bun and is recorded in the lockfile to maintain security [1][4][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
json="$(mktemp)"
trap 'rm -f "$json"' EXIT
curl -fsSLk --max-time 20 'https://registry.npmjs.org/bun/1.2.20' -o "$json"
python3 - "$json" <<'PY'
import json, sys
with open(sys.argv[1]) as f:
    data = json.load(f)
print("name:", data.get("name"))
print("version:", data.get("version"))
print("scripts:", json.dumps(data.get("scripts", {}), sort_keys=True))
print("dist:", json.dumps({
    k: data.get("dist", {}).get(k)
    for k in ("tarball", "integrity", "shasum")
}, sort_keys=True))
PY

Repository: reflex-dev/xy

Length of output: 451


🏁 Script executed:

#!/bin/bash
set -eu
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
curl -fsSLk --max-time 30 'https://registry.npmjs.org/bun/-/bun-1.2.20.tgz' -o "$tmp/bun.tgz"
tar -tzf "$tmp/bun.tgz" | sed -n '1,80p'
tar -xzf "$tmp/bun.tgz" -C "$tmp"
printf '%s\n' '--- package manifest ---'
cat "$tmp/package/package.json"
printf '%s\n' '--- install.js (first 240 lines) ---'
sed -n '1,240p' "$tmp/package/install.js"

Repository: reflex-dev/xy

Length of output: 9695


🏁 Script executed:

#!/bin/bash
set -eu
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
curl -fsSLk --max-time 30 'https://registry.npmjs.org/bun/-/bun-1.2.20.tgz' -o "$tmp/bun.tgz"
tar -xzf "$tmp/bun.tgz" -C "$tmp"
script="$tmp/package/install.js"
printf '%s\n' '--- installer security-relevant references ---'
rg -n -i 'sha|hash|checksum|integrity|download|fetch|exec|spawn|child_process|https?://|optional|binary|rename|chmod|writeFile|bun' "$script"
printf '%s\n' '--- installer tail ---'
tail -n 180 "$script"

Repository: reflex-dev/xy

Length of output: 10718


Security Misconfiguration (CWE-494): Download of Code Without Integrity Check

Reachability: External · Exploitability: Difficult

Use an integrity-pinned Bun bootstrap.

npm install --global bun@1.2.20 runs the package’s postinstall script. That script installs or downloads the platform Bun binary without an independently pinned checksum. Use a commit-SHA-pinned setup action or verify an official release checksum before execution.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 65-65: ad-hoc installation of packages (adhoc-packages): installs a package outside of a lockfile

(adhoc-packages)

🤖 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/security-audit.yml at line 65, Replace the unpinned
npm-based Bun installation in the security-audit workflow with an
integrity-pinned bootstrap: use a setup action pinned to a commit SHA, or
download the official Bun release and verify its checksum before execution.
Preserve the required Bun version while ensuring the installed binary is
independently authenticated.

Source: Linters/SAST tools

Comment thread docs/api-reference/figure-methods.md Outdated
Comment thread scripts/check_public_api.py Outdated
Comment thread scripts/verify_dependency_lock_inventory.py Outdated
Comment thread scripts/verify_docs_local.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

All reported issues were addressed across 16 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread docs/api-reference/figure-methods.md Outdated
Comment thread docs/api-reference/figure-methods.md Outdated
Comment thread python/xy/export.py
Comment thread scripts/verify_docs_local.py Outdated
Comment thread .github/workflows/security-audit.yml
Comment thread scripts/verify_docs_local.py Outdated
Comment thread scripts/verify_dependency_lock_inventory.py Outdated
Comment thread tests/test_type_surface.py Outdated
Comment thread .github/workflows/security-audit.yml
Comment thread scripts/check_public_api.py Outdated
@harsh21234i
harsh21234i force-pushed the fix/export-sandbox-security-449 branch from 7c236fa to e6b55d7 Compare August 5, 2026 08:32

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

All reported issues were addressed across 3 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread scripts/verify_dependency_lock_inventory.py Outdated
Comment thread scripts/verify_dependency_lock_inventory.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant