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
55 changes: 54 additions & 1 deletion .github/workflows/evaos-beta-rc-canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -656,16 +656,69 @@ jobs:
PRE_CANARY_DIR="$PROOF_DIR/installed-candidate-pre-canary"
CONNECTOR_CANARY_DIR="$PROOF_DIR/installed-candidate-connector"
rm -rf "$PRE_CANARY_DIR" "$CONNECTOR_CANARY_DIR"
set +e
"$BRIDGE_COMMAND" pre-canary \
--json \
--control-surface bridge-peekaboo \
--expected-version "$SHORT_VERSION" \
--expected-build "$BUNDLE_VERSION" \
--expected-source-commit "$TAG_COMMIT" \
--canary-artifact-root "$RUNNER_TEMP" \
Comment thread
100yenadmin marked this conversation as resolved.
Comment thread
100yenadmin marked this conversation as resolved.
--artifact-dir "$PRE_CANARY_DIR" \
> "$PROOF_DIR/installed-candidate-pre-canary.stdout.json" \
2> "$PROOF_DIR/installed-candidate-pre-canary.stderr.txt"
cp "$PRE_CANARY_DIR/qa-report.json" "$PROOF_DIR/installed-candidate-pre-canary.json"
PRE_CANARY_EXIT=$?
set -e
if [ -f "$PRE_CANARY_DIR/qa-report.json" ]; then
cp "$PRE_CANARY_DIR/qa-report.json" "$PROOF_DIR/installed-candidate-pre-canary.json"
fi
if [ "$PRE_CANARY_EXIT" -ne 0 ]; then
echo "Pre-canary exit code: $PRE_CANARY_EXIT"
if [ -f "$PROOF_DIR/installed-candidate-pre-canary.json" ]; then
set +e
node - "$PROOF_DIR/installed-candidate-pre-canary.json" <<'NODE'
const fs = require('fs');
const reportPath = process.argv[2];
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
const sanitizeMessage = (value) =>
String(value ?? '')
.replace(/https?:\/\/\S+/gi, '[redacted]')
.replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, '[redacted]')
.replace(/\/(?:[^/\s]+\/)*[^\s]*/g, '[redacted]')
.replace(/\b(token|secret|key|authorization|bearer)\b(?:\s*[:=]\s*|\s+)\S+/gi, '$1=[redacted]')
.replace(/[^\x20-\x7e]/g, '?')
.replace(/\s+/g, ' ')
.trim()
.slice(0, 240);
const checks = Array.isArray(report.checks) ? report.checks : [];
const failedChecks = checks.filter((check) => check && check.status === 'fail');
const sanitizedChecks = failedChecks.map((check) => ({
code:
typeof check.code === 'string' && /^[a-z0-9_.-]{1,96}$/i.test(check.code)
? check.code
: 'invalid_check_code',
status: ['fail', 'warn'].includes(check.status) ? check.status : 'unknown',
message: sanitizeMessage(check.message),
}));
if (sanitizedChecks.length === 0) {
console.error('Pre-canary failed without a non-passing sanitized check.');
} else {
for (const check of sanitizedChecks) {
console.error(`Pre-canary sanitized check: ${JSON.stringify(check)}`);
}
}
NODE
Comment thread
100yenadmin marked this conversation as resolved.
PRE_CANARY_SANITIZER_EXIT=$?
set -e
if [ "$PRE_CANARY_SANITIZER_EXIT" -ne 0 ]; then
echo "Pre-canary report could not be reduced to a sanitized check summary."
fi
else
echo "Pre-canary failed without a report that can be summarized safely."
fi
echo "::error::Installed candidate pre-canary failed; see the sanitized check summary above."
exit "$PRE_CANARY_EXIT"
fi

TOKEN_FILE="$HOME/Library/Application Support/evaos-desktop-bridge/connector.token"
for _attempt in $(seq 1 30); do
Expand Down
25 changes: 22 additions & 3 deletions resources/evaos-beta/bridge/src/evaos_desktop_bridge/pre_canary.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,17 @@ def gather_inventory(
bundle_id: str = DEFAULT_BUNDLE_ID,
artifact_roots: Sequence[str] | None = None,
) -> WorkbenchInventory:
registered_paths = _unique_paths(
registered_paths = tuple(
path
for candidate_bundle_id in (bundle_id, *sorted(LEGACY_BUNDLE_IDS))
for path in _mdfind_bundle_paths(candidate_bundle_id)
for path in _unique_paths(
path
for candidate_bundle_id in (bundle_id, *sorted(LEGACY_BUNDLE_IDS))
for path in _mdfind_bundle_paths(candidate_bundle_id)
)
# Spotlight can retain paths from updater/fallback extraction after the
# temporary app has been removed. Discard only definitively missing
# targets; existing or unverifiable paths remain fail-closed.
if _registered_path_exists_or_is_unverifiable(path)
)
artifact_paths = tuple(_artifact_workbench_bundle_paths(artifact_roots=artifact_roots))
bundle_paths = _unique_paths((*registered_paths, *artifact_paths, canonical_path))
Expand Down Expand Up @@ -410,6 +417,18 @@ def _unique_paths(paths: Iterable[str]) -> tuple[str, ...]:
return tuple(ordered)


def _registered_path_exists_or_is_unverifiable(path: str) -> bool:
try:
Path(path).stat()
except (FileNotFoundError, NotADirectoryError):
return False
except OSError:
# Keep permission and other inspection failures fail-closed. Only a
# definitively removed Spotlight target is safe to ignore.
return True
return True


def _run(command: Sequence[str]) -> str:
try:
completed = subprocess.run(command, check=False, capture_output=True, text=True, timeout=10)
Expand Down
39 changes: 39 additions & 0 deletions tests/unit/process/prepareEvaosDesktopBridgeResource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ describe('prepareEvaosDesktopBridgeResource', () => {
}
});

it('captures pre-canary failures as sanitized check summaries before preserving the exit code', () => {
const workflow = readFileSync(join(process.cwd(), '.github', 'workflows', 'evaos-beta-rc-canary.yml'), 'utf8');
const failureBlock = workflow.slice(
workflow.indexOf('PRE_CANARY_EXIT=$?'),
workflow.indexOf('TOKEN_FILE="$HOME/Library/Application Support/evaos-desktop-bridge/connector.token"')
);

expect(failureBlock).toContain('PRE_CANARY_EXIT=$?');
expect(workflow).toContain('--canary-artifact-root "$RUNNER_TEMP"');
expect(failureBlock).toContain('Pre-canary exit code: $PRE_CANARY_EXIT');
expect(failureBlock).toContain('Pre-canary sanitized check: ${JSON.stringify(check)}');
expect(failureBlock).toContain('exit "$PRE_CANARY_EXIT"');
expect(failureBlock).not.toMatch(/\.evidence|\.inventory/);
});

it('rejects dirty or untracked vendored bridge bytes in strict provenance checks', () => {
expect(() =>
bridgeResource.assertVendoredBridgeSourceMatchesHead(
Expand Down Expand Up @@ -621,6 +636,30 @@ describe('prepareEvaosDesktopBridgeResource', () => {
'report = pre_canary.evaluate_inventory(inventory, expected_version="2.1.36", expected_build="2.1.36")',
'assert report.ok, report.to_dict()',
'assert pre_canary._workbench_app_path_from_command(current_process.command) == pre_canary.DEFAULT_CANONICAL_PATH',
'with TemporaryDirectory() as inventory_root:',
' canonical = Path(inventory_root) / "evaOS Workbench.app"',
' canonical.mkdir()',
' removed = Path(inventory_root) / "removed-updater-extract" / "evaOS Workbench.app"',
' removed_parent = Path(inventory_root) / "removed-parent"',
' removed_parent.write_text("not a directory", encoding="utf-8")',
' removed_below_file = removed_parent / "evaOS Workbench.app"',
' existing_duplicate = Path(inventory_root) / "fallback-extract" / "evaOS Workbench.app"',
' pre_canary._read_app_bundle = lambda path: pre_canary.AppBundle(path=path, bundle_id=pre_canary.DEFAULT_BUNDLE_ID, version="2.1.36", build="2.1.36", team_id=pre_canary.DEFAULT_TEAM_ID)',
' pre_canary._process_inventory = lambda: (pre_canary.ProcessInfo(pid=2, command=f"{canonical}/Contents/MacOS/evaOS Workbench", path=str(canonical), kind="workbench"),)',
' pre_canary._mdfind_bundle_paths = lambda _bundle_id: (str(canonical), str(removed), str(removed_below_file))',
' filtered_inventory = pre_canary.gather_inventory(canonical_path=str(canonical), artifact_roots=())',
' assert filtered_inventory.registered_paths == (str(canonical),), filtered_inventory.to_dict()',
' filtered_report = pre_canary.evaluate_inventory(filtered_inventory, canonical_path=str(canonical), expected_version="2.1.36", expected_build="2.1.36")',
' assert filtered_report.ok, filtered_report.to_dict()',
' existing_duplicate.mkdir(parents=True)',
' pre_canary._mdfind_bundle_paths = lambda _bundle_id: (str(canonical), str(removed), str(removed_below_file), str(existing_duplicate), str(existing_duplicate))',
' duplicate_inventory = pre_canary.gather_inventory(canonical_path=str(canonical), artifact_roots=())',
' assert str(removed) not in duplicate_inventory.registered_paths, duplicate_inventory.to_dict()',
' assert str(removed_below_file) not in duplicate_inventory.registered_paths, duplicate_inventory.to_dict()',
' assert duplicate_inventory.registered_paths == (str(canonical), str(existing_duplicate)), duplicate_inventory.to_dict()',
' duplicate_report = pre_canary.evaluate_inventory(duplicate_inventory, canonical_path=str(canonical))',
' assert not duplicate_report.ok, duplicate_report.to_dict()',
' assert "duplicate_registered_workbench_app" in {check.code for check in duplicate_report.checks}',
'with TemporaryDirectory() as artifact_dir:',
' report_path = pre_canary._write_report(report.to_dict(), Path(artifact_dir))',
' assert report_path.name == "qa-report.json" and report_path.is_file()',
Expand Down
Loading