Skip to content

security: expand secret redaction, pin @types/bun, add .env to .gitignore#64

Closed
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1782266230-security-audit-fixes
Closed

security: expand secret redaction, pin @types/bun, add .env to .gitignore#64
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1782266230-security-audit-fixes

Conversation

@devin-ai-integration

Copy link
Copy Markdown

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:

redactSecrets coverage gaps — bare tokens from several common providers could leak into audit logs:

# Slack: only xoxb- (bot) was covered; xoxp- (user), xoxa- (app), xoxs- were not
- /\bxoxb-[A-Za-z0-9-]{20,}\b/
+ /\bxox[bpas]-[A-Za-z0-9-]{20,}\b/

# Added: OpenAI, Anthropic, Google, SendGrid API key patterns
+ /\bsk-(?:proj-)?[A-Za-z0-9]{20,}\b/           # OpenAI
+ /\bsk-ant-(?:api\d+-)?[A-Za-z0-9_-]{20,}\b/   # Anthropic
+ /\bAIzaSy[A-Za-z0-9_-]{33}\b/                 # Google
+ /\bSG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/  # SendGrid

Supply chain@types/bun: "latest" pinned to ^1.3.5 to avoid auto-resolving to unvetted new releases.

.gitignore — added .env / .env.* to prevent accidental secret commits by contributors.

Full audit findings (no fix needed)

Category Status
Hardcoded secrets Clean — only test fixtures and redaction patterns
SQL injection N/A — no database usage
CORS N/A — CLI tool, no HTTP server
Debug endpoints N/A — no HTTP endpoints
Authentication N/A — local CLI tool
Path traversal Already mitigated (sanitizeSessionIdForFilename, scope-policy relative() checks)
Command injection Safe — proper spawn() with stdio isolation and timeouts
Input validation Thorough — JSON parsing, type checking, config validation throughout
GitHub API rate limiting Unauthenticated (60 req/hr) — low concern for CLI usage patterns

Link to Devin session: https://app.devin.ai/sessions/1849edbf27c1444e94b0b04383a75e19
Requested by: @kenryu42

…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>
@kenryu42 kenryu42 self-assigned this Jun 24, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.40%. Comparing base (14ec035) to head (5f0cd99).
⚠️ Report is 3 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown

Greptile Summary

This PR hardens the redactSecrets function in src/core/audit.ts (and its three compiled dist/ counterparts) by adding regex patterns for previously uncovered Slack token types (xoxp-, xoxa-, xoxs-) and four AI-provider key formats (OpenAI sk-, Anthropic sk-ant-, Google AIzaSy, SendGrid SG.<seg>.<seg>), accompanied by new unit tests for each.

  • Secret redaction patterns: Four new regexes are added in a dedicated "AI provider API keys" block; the patterns are non-overlapping and correctly ordered relative to one another and to the existing JWT/AWS catch-all.
  • Supply chain: @types/bun is changed from \"latest\" to \"^1.3.5\", reducing exposure to unreviewed major releases, though the caret still permits minor-version bumps on a fresh install.
  • .gitignore: .env and .env.* are now ignored, preventing accidental secret commits by contributors.

Confidence Score: 4/5

Safe 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 ^1.3.5 still allowing unreviewed minor releases, and the new AI-key test not asserting the exact <redacted> replacement or covering the bare sk- (no proj-) variant — are low-risk but worth addressing before the next contributor relies on those tests as a complete regression guard.

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

Filename Overview
src/core/audit.ts Adds four new redaction patterns for Slack extended prefixes, OpenAI, Anthropic, Google, and SendGrid; patterns are correctly ordered and non-overlapping
tests/core/audit.test.ts Adds coverage for new Slack variants and AI-provider key formats; AI-key assertions are weaker (not.toContain only) and the bare sk- OpenAI variant is untested
package.json Pins @types/bun from "latest" to "^1.3.5"; caret still permits minor-version bumps so the pin is not fully reproducible
.gitignore Adds .env and .env.* entries to prevent accidental secret commits; straightforward and correct
dist/bin/cc-safety-net.js Compiled artifact updated to mirror src/core/audit.ts changes; identical logic, in sync with source
dist/index.js Compiled artifact updated to mirror src/core/audit.ts changes; identical logic, in sync with source
dist/pi/index.js Compiled artifact updated to mirror src/core/audit.ts changes; identical logic, in sync with source

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
Loading
%%{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
Loading

Comments Outside Diff (1)

  1. package.json

    P2 Caret range still allows unreviewed minor releases

    ^1.3.5 resolves to >=1.3.5 <2.0.0, so npm install / bun install on a fresh checkout could still pull a 1.4.x release automatically. The PR description says the goal is to prevent "auto-resolving to unvetted new releases." A bare version without the caret is the only way to guarantee a reproducible install.

    Fix in Codex

Fix All in Codex

Reviews (1): Last reviewed commit: "security: expand secret redaction covera..." | Re-trigger Greptile

Comment thread tests/core/audit.test.ts
Comment on lines +84 to +95
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);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 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!

Fix in Codex

@kenryu42 kenryu42 closed this Jul 3, 2026
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