security: expand secret redaction, pin @types/bun, add .env to .gitignore#64
security: expand secret redaction, pin @types/bun, add .env to .gitignore#64devin-ai-integration[bot] wants to merge 1 commit into
Conversation
…to .gitignore - Expand Slack token redaction from xoxb- only to xox[bpas]- (covers user, app, system tokens) - Add redaction patterns for OpenAI (sk-proj-*), Anthropic (sk-ant-*), Google (AIzaSy*), and SendGrid (SG.*) API keys - Pin @types/bun from 'latest' to '^1.3.5' to avoid supply chain risk - Add .env and .env.* to .gitignore to prevent accidental secret commits - Add tests for new Slack token variants and AI provider key redaction Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #64 +/- ##
=======================================
Coverage 97.40% 97.40%
=======================================
Files 94 94
Lines 10341 10345 +4
=======================================
+ Hits 10073 10077 +4
Misses 268 268 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Greptile SummaryThis PR hardens the
Confidence Score: 4/5Safe to merge; the new patterns are non-overlapping and cover genuine redaction gaps, with no regressions to existing behaviour. The regex changes are correct and well-tested. The two minor gaps — the caret in tests/core/audit.test.ts — the new AI-provider test block would benefit from stronger assertions; package.json — consider removing the caret from the @types/bun version. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Input text] --> B[PEM blocks]
B --> C[ENV var patterns\nTOKEN= / API_KEY= etc.]
C --> D[Authorization headers]
D --> E[URL credentials\nscheme://user:pass@host]
E --> F[GitHub tokens\nghp_ gho_ etc.]
F --> G[Slack tokens\nxox b/p/a/s - NEW: p,a,s added]
G --> H[npm tokens\nnpm_]
H --> I[Stripe keys\nsk_live_ / sk_test_]
I --> J[PyPI tokens\npypi-]
J --> K[OpenAI keys NEW\nsk- / sk-proj-]
K --> L[Anthropic keys NEW\nsk-ant-]
L --> M[Google keys NEW\nAIzaSy...]
M --> N[SendGrid keys NEW\nSG...segA...segB]
N --> O[JWTs\nseg.seg.sig]
O --> P[AWS access keys\nAKIA / ASIA]
P --> Q[Redacted output]
style K fill:#d4edda,stroke:#28a745
style L fill:#d4edda,stroke:#28a745
style M fill:#d4edda,stroke:#28a745
style N fill:#d4edda,stroke:#28a745
style G fill:#d4edda,stroke:#28a745
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Input text] --> B[PEM blocks]
B --> C[ENV var patterns\nTOKEN= / API_KEY= etc.]
C --> D[Authorization headers]
D --> E[URL credentials\nscheme://user:pass@host]
E --> F[GitHub tokens\nghp_ gho_ etc.]
F --> G[Slack tokens\nxox b/p/a/s - NEW: p,a,s added]
G --> H[npm tokens\nnpm_]
H --> I[Stripe keys\nsk_live_ / sk_test_]
I --> J[PyPI tokens\npypi-]
J --> K[OpenAI keys NEW\nsk- / sk-proj-]
K --> L[Anthropic keys NEW\nsk-ant-]
L --> M[Google keys NEW\nAIzaSy...]
M --> N[SendGrid keys NEW\nSG...segA...segB]
N --> O[JWTs\nseg.seg.sig]
O --> P[AWS access keys\nAKIA / ASIA]
P --> Q[Redacted output]
style K fill:#d4edda,stroke:#28a745
style L fill:#d4edda,stroke:#28a745
style M fill:#d4edda,stroke:#28a745
style N fill:#d4edda,stroke:#28a745
style G fill:#d4edda,stroke:#28a745
|
| test('redacts AI provider API keys', () => { | ||
| const openaiKey = 'sk-proj-abcdefghijklmnopqrstuvwxyz1234567890'; | ||
| const anthropicKey = 'sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890'; | ||
| const googleKey = 'AIzaSyA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q'; | ||
| const sendgridKey = 'SG.abcdefghijklmnopqrstuv.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst'; | ||
|
|
||
| const result = redactSecrets(`${openaiKey} ${anthropicKey} ${googleKey} ${sendgridKey}`); | ||
| expect(result).not.toContain(openaiKey); | ||
| expect(result).not.toContain(anthropicKey); | ||
| expect(result).not.toContain(googleKey); | ||
| expect(result).not.toContain(sendgridKey); | ||
| }); |
There was a problem hiding this comment.
Weaker assertions than the existing provider-token test
The new AI-key test only asserts the original value is absent (not.toContain), not that the replacement is <redacted>. The existing redacts raw provider token formats test goes further, asserting result.split(' ') equals the expected array of '<redacted>' strings. If any AI key were silently removed by a different upstream pattern (e.g., the JWT catch-all for a hypothetically dot-containing key), this test would still green even though the dedicated AI-key pattern was broken. It's also worth adding a case for the bare OpenAI key without the proj- segment (sk-<20+ alphanum>) to guard against a future regression that accidentally makes (?:proj-) required.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Security audit of the codebase. The repo is well-secured overall — no hardcoded secrets, no SQL/CORS/auth concerns (CLI tool), proper path traversal prevention, safe command spawning. Three actionable gaps were found and fixed:
redactSecretscoverage gaps — bare tokens from several common providers could leak into audit logs:Supply chain —
@types/bun: "latest"pinned to^1.3.5to avoid auto-resolving to unvetted new releases..gitignore— added.env/.env.*to prevent accidental secret commits by contributors.Full audit findings (no fix needed)
sanitizeSessionIdForFilename, scope-policyrelative()checks)spawn()with stdio isolation and timeoutsLink to Devin session: https://app.devin.ai/sessions/1849edbf27c1444e94b0b04383a75e19
Requested by: @kenryu42