Security Guide · codelake Research

What to do when you receive a security alert

Practical steps for the most common required actions in a codelake Research alert — key rotation, removing secrets from packages and git history, auditing access logs, and preventing future leaks.

Credential Exposure Supply Chain Lifecycle Hooks Malicious Packages
Understanding the finding
What was exposed and what it means for you

A live, production-level credential was found embedded in plain text inside a published package. Anyone who installed or inspected that package while it was in the registry could have copied the secret — no hacking or special tools required.

A Critical rating means immediate action is required. Exposed API keys, tokens, and signing secrets give direct access to the accounts and services they belong to.

codelake detected, archived, and verified the finding before the package was removed. The alert you received documents the exposure window, the observed reach, and the exact file and line where the credentials appeared.

Check whether the affected package version is in your dependency tree — directly or transitively:

Terminal
$ npm ls <package-name>
# or check the lockfile directly:
$ grep <package-name> package-lock.json

If the affected version appears, your environment installed the compromised package. Treat the exposed credentials as compromised regardless of whether you personally used them.

Exposed credentials often belong to the package author, not your project. But anyone with access to the tarball — CI systems, developers, automated scanners — may have captured them.
Key rotation
What it means and how to do it correctly

Key rotation is replacing a compromised credential with a newly generated one, then revoking the old one. It is the single most important immediate response to a credential leak.

The goal is to make the exposed credential useless to anyone who captured it. Until you rotate, anyone who found the key in the tarball can use it — regardless of whether the package was removed.

Removing the package does not invalidate the key. The tarball may already have been downloaded many times. Rotation is the only way to cut off access.

Follow this order: generate new → deploy new → revoke old. Never revoke first — it will break your service before the new key is in place.

The process is the same regardless of provider (Stripe, AWS, GitHub, etc.):

01
Generate a new key in the provider's dashboard or API — before revoking anything.
02
Apply minimum scopes — give the new key only the permissions it needs. This limits blast radius for any future leak.
03
Deploy the new key to every environment: production, staging, CI/CD, local machines. Use environment variables or a secrets manager — never source code.
04
Verify the new key works with a non-destructive call before proceeding.
05
Revoke the old key and monitor for errors for a few minutes to confirm nothing was missed.
Store the new key in an environment variable or a secrets manager (AWS Secrets Manager, HashiCorp Vault, Doppler, 1Password). Never commit secrets to source control.

Use environment variables as the baseline — your app reads the key at runtime from the environment, not from source:

Node.js — correct pattern
// ✓ read from environment
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
// ✗ never do this
const stripe = require('stripe')('sk_live_abc123…');

Set env vars in your host's secrets panel (Vercel, Railway, Heroku…), not in committed .env files. A local .env is fine — but it must be in .gitignore:

.gitignore — minimum
# secrets
.env
.env.local
.env.production
*.pem
*.key

For teams and production, use a secrets manager — they add auditing, rotation automation, and access control that environment variables alone don't.

Remove from package & git history
How to scrub secrets from code and version history

If you're the package author, removing it from the current source is only the first step — git history still contains every previous commit.

01
Delete the secret from the file and replace it with an environment variable reference.
02
Commit and push the clean version.
03
Publish a new version with a semver bump and deprecate the affected ones: npm deprecate <pkg>@"<=<bad-version>" "Contains exposed credentials — upgrade"
04
Clean the git history (see Q7) — a clean commit does not remove the secret from old commits.
Deleting the file and committing does not remove the secret from history — the old commit remains accessible via git log and git show.

The recommended tool is git filter-repo (the modern replacement for git filter-branch and BFG). It rewrites every commit containing the secret.

This rewrites history. Every collaborator must re-clone or rebase. Coordinate with your team first.
Install + purge a literal secret from all history
$ pip install git-filter-repo # or: brew install git-filter-repo
$ git filter-repo --replace-text replacements.txt
replacements.txt
# format: literal==>replacement
sk_live_youractualkey==>REDACTED_SECRET_KEY
Force-push the rewritten history
$ git push origin --force --all
$ git push origin --force --tags

After force-pushing, ask all collaborators to delete their clone and re-clone. Old clones still contain the full history.

On GitHub, after rewriting history, contact Support to purge cached views — see "Removing sensitive data from a repository."
Auditing access logs
How to check whether the exposed credentials were used

Review your provider's API access logs for the exposure window — the period between when the package was published and when you rotated the credentials. The exact window is documented in your alert.

Filter logs by that date range and look for:

  • Requests from unusual IP addresses or regions
  • Unexpected charges, refunds, or payout modifications
  • Customer-data reads (list/retrieve customers)
  • Webhook endpoint modifications (someone adding their own endpoint)

If you find suspicious activity, preserve the logs and contact the provider's security team before anything else.

No suspicious activity + rotated credentials = you're clear. Document the audit result and close the incident.