Repository navigation
[codex] Guard public repo sensitive content #497
Changes from 5 commits
2aa036a
af94155
eea0de1
66b6df3
e3f6e3b
102fb96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -229,6 +229,9 @@ jobs: | |
| - name: Run postinstall | ||
| run: npm run postinstall || true | ||
|
|
||
| - name: Run public sensitive content scan | ||
| run: node scripts/security/check-public-sensitive-content.js | ||
|
|
||
| - name: Install prek | ||
| run: npm install -g @j178/prek | ||
|
|
||
|
|
@@ -725,7 +728,7 @@ jobs: | |
|
|
||
| BUNDLE_ID="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$APP_PATH/Contents/Info.plist")" | ||
| VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP_PATH/Contents/Info.plist")" | ||
| BRIDGE_SUMMARY="$(node -e "const fs=require('fs'); const m=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); if (m.placeholder !== true) { console.error('::error::Expected thin-app-smoke to bundle the diagnostic Bridge placeholder'); process.exit(1); } console.log('diagnostic-placeholder')" "$BRIDGE_MANIFEST")" | ||
| BRIDGE_SUMMARY="$(node -e "const fs=require('fs'); const m=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const sha=/^[0-9a-f]{40}$/i; if (m.placeholder === true) { console.log('diagnostic-placeholder'); process.exit(0); } if (!sha.test(String(m.requestedSourceRef || '')) || !sha.test(String(m.sourceCommit || '')) || m.requestedSourceRef !== m.sourceCommit) { console.error('::error::Expected thin-app-smoke to bundle a diagnostic Bridge placeholder or the pinned real Bridge source'); process.exit(1); } console.log('pinned-real-bridge@' + String(m.sourceCommit).slice(0, 12));" "$BRIDGE_MANIFEST")" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the thin-app smoke workflow, the build step pins Useful? React with 👍 / 👎. |
||
| node scripts/evaosVerifyRendererDependencyPrune.js "$APP_PATH" | ||
|
|
||
| { | ||
|
|
@@ -738,7 +741,7 @@ jobs: | |
| echo "- Bridge manifest: \`$BRIDGE_SUMMARY\`" | ||
| echo "- Renderer dependency prune: verified \`app.asar\` and \`app.asar.unpacked/node_modules\`" | ||
| echo | ||
| echo "This PR artifact is intentionally unpacked and may use a diagnostic Bridge placeholder when private source access is unavailable. It may be ad-hoc/non-Developer-ID signed by packaging hooks. It produces no DMG, no release metadata, no notarization/stapling proof, no TCC or permission proof, and no public release proof." | ||
| echo "This PR artifact is intentionally unpacked and may use a diagnostic Bridge placeholder when private source access is unavailable, or a pinned real Bridge source when CI can fetch it. It may be ad-hoc/non-Developer-ID signed by packaging hooks. It produces no DMG, no release metadata, no notarization/stapling proof, no TCC or permission proof, and no public release proof." | ||
| echo | ||
| echo "### Size" | ||
| echo '```' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| name: Public Security Scan | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
|
|
||
| jobs: | ||
| public-sensitive-content: | ||
| name: Public Sensitive Content | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | ||
| with: | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
|
|
||
| - name: Setup Node | ||
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 | ||
| with: | ||
| node-version: 24 | ||
|
|
||
| - name: Run repo-owned public scan | ||
| run: node scripts/security/check-public-sensitive-content.js | ||
|
|
||
| gitleaks: | ||
| name: Gitleaks Full History | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | ||
| with: | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: Run Gitleaks | ||
| uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e | ||
|
Comment on lines
+62
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On Useful? React with 👍 / 👎. |
||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITLEAKS_ENABLE_UPLOAD_ARTIFACT: false | ||
| GITLEAKS_NOTIFY_USER_LIST: '' | ||
|
|
||
| trufflehog: | ||
| name: TruffleHog Verified | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | ||
| with: | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
|
|
||
| - name: Run TruffleHog verified full-history scan | ||
| run: | | ||
| docker run --rm \ | ||
| -v "$PWD:/repo:ro" \ | ||
| ghcr.io/trufflesecurity/trufflehog:3.95.7 \ | ||
| git file:///repo \ | ||
| --only-verified \ | ||
| --no-update \ | ||
| --fail | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| title = "AionUi public repository Gitleaks configuration" | ||
|
|
||
| [extend] | ||
| useDefault = true | ||
|
|
||
| [[allowlists]] | ||
| description = "Fake short OpenAI protocol detector fixture" | ||
| condition = "AND" | ||
| paths = ['''^tests/unit/common/protocolDetector\.test\.ts$'''] | ||
| regexes = ['''sk-abc123def456ghi789'''] | ||
|
|
||
| [[allowlists]] | ||
| description = "Fake long OpenAI protocol detector fixture" | ||
| condition = "AND" | ||
| paths = ['''^tests/unit/common/protocolDetector\.test\.ts$'''] | ||
| regexes = ['''sk-abc123def456ghi789jkl012'''] | ||
|
|
||
| [[allowlists]] | ||
| description = "Fake Google API key protocol detector fixture" | ||
| condition = "AND" | ||
| paths = ['''^tests/unit/common/protocolDetector\.test\.ts$'''] | ||
| regexes = ['''AIzaa{35}'''] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Gitleaks allowlist regex AIzaa{35} over-matches; will not match the 35-a fixture and may leak/err In the 'Fake Google API key protocol detector fixture' allowlist, Why this matters: A misconfigured allowlist either breaks the new required CI gate (Gitleaks Full History) with false positives on a known fixture, or silently disables coverage so a real Google key could pass review. |
||
|
|
||
| [[allowlists]] | ||
| description = "Fake bridge resource token fixture" | ||
| condition = "AND" | ||
| paths = ['''^tests/unit/bootstrap/prepareEvaosDesktopBridgeResource\.test\.ts$'''] | ||
| regexes = ['''super-secret-token'''] | ||
|
|
||
| [[allowlists]] | ||
| description = "Fake bridge resource credential URL fixture" | ||
| condition = "AND" | ||
| paths = ['''^tests/unit/bootstrap/prepareEvaosDesktopBridgeResource\.test\.ts$'''] | ||
| regexes = ['''https://x-access-token:super-secret-token@github\.com/electricsheephq/evaos-desktop-bridge\.git'''] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ const fs = require('fs'); | |
| const path = require('path'); | ||
| const { execSync } = require('child_process'); | ||
|
|
||
| const projectRoot = path.join(__dirname, '..'); | ||
|
|
||
| // Parse command line arguments | ||
| const args = process.argv.slice(2); | ||
| const profileIndex = args.indexOf('--profile'); | ||
|
|
@@ -28,6 +30,15 @@ if (!profile) { | |
| process.exit(1); | ||
| } | ||
|
|
||
| function requireEnv(name, purpose) { | ||
| const value = process.env[name]; | ||
| if (!value) { | ||
| console.error(`Error: ${name} is required for ${purpose}.`); | ||
| process.exit(1); | ||
| } | ||
| return value; | ||
| } | ||
|
|
||
| // Read current version | ||
| const versionPath = path.join(__dirname, '..', 'versions', 'version.json'); | ||
| let versionData; | ||
|
|
@@ -53,9 +64,18 @@ try { | |
|
|
||
| // Build eas command args | ||
| const outputExt = platform === 'ios' ? '.ipa' : '.apk'; | ||
| const localOutputPath = path.join(__dirname, '..', `build-${Date.now()}${outputExt}`); | ||
| const localOutputPath = path.join(projectRoot, `build-${Date.now()}${outputExt}`); | ||
| let buildArgs = args.filter((a) => a !== '--auto-submit' && a !== '--direct-submit'); | ||
|
|
||
| if (!isLocal && directSubmit) { | ||
| console.error('Error: --direct-submit is only supported with --local builds.'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| if (!isLocal && autoSubmit && !buildArgs.includes('--auto-submit-with-profile')) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Non-local auto-submit rewrites --auto-submit to --auto-submit-with-profile but eas submit profiles no longer carry Apple credentials For cloud ( Why this matters: The implicit contract between eas.json (credentials removed) and build.js (env vars now mandatory) is easy to break in a future edit; a comment prevents regression. |
||
| buildArgs.push('--auto-submit-with-profile', profile); | ||
| } | ||
|
|
||
| // For local builds with submit, capture output path for later submission | ||
| if (isLocal && (autoSubmit || directSubmit)) { | ||
| if (!buildArgs.includes('--output')) { | ||
|
|
@@ -84,20 +104,34 @@ if (isLocal && platform === 'ios') { | |
| const easCommand = `eas build ${buildArgs.join(' ')}`; | ||
| console.log(`\nRunning: ${easCommand}\n`); | ||
|
|
||
| // Apple-specific env vars (only needed for iOS builds) | ||
| const appleEnv = | ||
| platform === 'ios' | ||
| ? { | ||
| EXPO_APPLE_TEAM_ID: process.env.EXPO_APPLE_TEAM_ID || 'M4AG47ZV62', | ||
| EXPO_APPLE_ID: process.env.EXPO_APPLE_ID || 'liangzhewei@gmail.com', | ||
| ...(applePassword ? { EXPO_APPLE_PASSWORD: applePassword } : {}), | ||
| } | ||
| : {}; | ||
| const expoAppleId = process.env.EXPO_APPLE_ID || process.env.APPLE_ID || process.env.appleId; | ||
| const expoAppleTeamId = | ||
| process.env.EXPO_APPLE_TEAM_ID || process.env.TEAM_ID || process.env.teamId; | ||
| const appleEnv = {}; | ||
| if (platform === 'ios') { | ||
| if (expoAppleTeamId) { | ||
| appleEnv.EXPO_APPLE_TEAM_ID = expoAppleTeamId; | ||
| } | ||
| if (expoAppleId) { | ||
| appleEnv.EXPO_APPLE_ID = expoAppleId; | ||
| } | ||
| if (applePassword) { | ||
| appleEnv.EXPO_APPLE_PASSWORD = applePassword; | ||
| } | ||
| if (autoSubmit || directSubmit) { | ||
| appleEnv.EXPO_APPLE_ID = expoAppleId || requireEnv('EXPO_APPLE_ID', 'iOS submission'); | ||
| } | ||
| if (autoSubmit) { | ||
| appleEnv.EXPO_APPLE_TEAM_ID = | ||
| expoAppleTeamId || requireEnv('EXPO_APPLE_TEAM_ID', 'EAS iOS submission'); | ||
|
100yenadmin marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
| // Execute eas build | ||
| try { | ||
| execSync(easCommand, { | ||
| stdio: 'inherit', | ||
| cwd: projectRoot, | ||
| env: { | ||
| ...process.env, | ||
| PATH: `/usr/bin:${process.env.PATH}`, | ||
|
|
@@ -123,7 +157,7 @@ if (platform === 'ios' && isLocal && (autoSubmit || directSubmit)) { | |
|
|
||
| if (directSubmit) { | ||
| // Upload directly to App Store Connect via xcrun altool (bypasses EAS) | ||
| const appleId = process.env.APPLE_ID || 'liangzhewei@gmail.com'; | ||
| const appleId = expoAppleId || requireEnv('EXPO_APPLE_ID', 'direct iOS submission'); | ||
| const submitCommand = `xcrun altool --upload-app -f "${outputFile}" -t ${platform} -u "${appleId}" -p "@keychain:AC_PASSWORD"`; | ||
| console.log(`\nUploading directly to TestFlight: xcrun altool --upload-app\n`); | ||
| try { | ||
|
|
@@ -135,17 +169,18 @@ if (platform === 'ios' && isLocal && (autoSubmit || directSubmit)) { | |
| ' Make sure your App-Specific Password is saved in Keychain as "AC_PASSWORD".', | ||
| ); | ||
| console.error( | ||
| ' To save it: security add-generic-password -a "liangzhewei@gmail.com" -s "AC_PASSWORD" -w "<your-app-specific-password>" -U', | ||
| ' To save it: security add-generic-password -a "$EXPO_APPLE_ID" -s "AC_PASSWORD" -w "<your-app-specific-password>" -U', | ||
| ); | ||
| process.exit(1); | ||
| } | ||
| } else { | ||
| // Upload via EAS submit | ||
| const submitCommand = `eas submit --platform ${platform} --path ${outputFile} --non-interactive`; | ||
| const submitCommand = `eas submit --platform ${platform} --profile ${profile} --path ${outputFile} --non-interactive`; | ||
| console.log(`\nSubmitting to TestFlight: ${submitCommand}\n`); | ||
| try { | ||
| execSync(submitCommand, { | ||
| stdio: 'inherit', | ||
| cwd: projectRoot, | ||
| env: { | ||
| ...process.env, | ||
| ...appleEnv, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.