Adopt these controls in order. The first three — locked dependencies, secret scanning, and dependency scanning (SCA) — reduce most day-to-day risk.
Contents
- Lock dependency versions
- Scan for secrets early
- Scan dependencies (SCA)
- Scan code for vulnerabilities (SAST)
- Handle scanner false positives and triage
- Harden CI/CD and build environments
- Account hygiene
- Notebook and data-file hygiene
- Containers, SBOM, and artifact signing
- Monitor and respond
- Know the OWASP Top 10
1) Lock dependency versions
You want reproducible installs: same versions on every machine and CI run. Each tool has two phases: one for installing dependencies and generating a lock file, and one for building and running code using that lock file.
Python (commit lock output):
uv→uv.lockpoetry→poetry.lockpip-tools→ pinnedrequirements.txtwith hashes
Conda / mamba (scientific Python):
- Export from explicit history:
conda env export --from-history > environment.ymlto avoid capturing platform-specific transitive pins. - Use
conda-lockto generate a multi-platform lock file (conda-lock.yml) that pins every package, version, and hash. - Prefer
conda-forgeover ad-hoc channels. Conda-forge has recipe review, but is not immune to supply-chain issues.
Node.js (commit lock output):
npm→package-lock.jsonyarn→yarn.lockpnpm→pnpm-lock.yaml
Use clean-install commands in CI:
- Node:
npm ci - Python (
uv):uv sync --frozen - Python (
pip-tools):pip install --require-hashes -r requirements.txt - Conda:
conda-lock install --name env conda-lock.yml
package.json exact pins can be useful in applications, but lock files and controlled updates are the primary control.
2) Scan for secrets early
Catch secrets before push and in CI:
- GitHub secret scanning for public repos and private repos where enabled in your org/plan.
gitleaksortrufflehoglocally and in CI.pre-committo run secret checks at commit time.
Important:
- Scan history, not just current files.
- Default detectors do not cover every internal token format; add custom patterns for organization-specific secrets.
- Use push protection where available to block commits containing detectable credentials.
3) Scan dependencies (SCA)
SCA (Software Composition Analysis) compares your dependency graph against known vulnerabilities. This is where most real-world damage happens, so run SCA first.
osv-scanner(multi-ecosystem: Python, npm, Go, Rust, Maven, Cargo, …). One tool covers most scientific stacks.- Python:
pip-audit - Node:
npm audit --audit-level=high - GitHub Dependabot: enable automated upgrade PRs and alerts where available in your repository settings.
Run SCA in CI and fail builds on policy-defined severe findings.
4) Scan code for vulnerabilities (SAST)
SAST (Static Application Security Testing) flags suspicious code patterns.
- Python:
bandit -r src/ - JavaScript/TypeScript:
eslint+eslint-plugin-security - Multi-language:
semgrep --config=auto; CodeQL on GitHub where available in your org/plan
Start with high-confidence findings and tune rules to reduce noise.
5) Handle scanner false positives and triage
Scanners are useful, but they are noisy at first. Use a short, consistent triage flow:
- Validate that the finding is real and reachable in your code path.
- Prioritize by severity and exploitability (internet-facing path, auth bypass, secret exposure, RCE).
- If you suppress a false positive, record a reason, owner, and expiration date.
- If you defer a true positive, file a tracked issue with a remediation target date.
6) Harden CI/CD and build environments
Supply-chain attacks increasingly target CI and build systems. Use this baseline:
- Run builds on ephemeral runners where possible.
- Use least-privilege tokens for CI jobs.
- Prefer short-lived credentials (OIDC federation) over long-lived static secrets.
- Restrict outbound network access from build jobs to trusted endpoints when practical.
- Do not expose privileged secrets to untrusted pull requests (especially forks).
- Treat lifecycle scripts (
preinstall,install,postinstall) as executable code and monitor new script changes in dependency updates.
7) Account hygiene
The Shai-Hulud campaign succeeded because maintainer accounts were compromised. Protect yours.
- Enable two-factor authentication on GitHub, PyPI, npm, conda-forge, and any cloud console. Prefer hardware security keys (FIDO2/WebAuthn) over SMS or TOTP where possible.
- Use a password manager. No reuse.
- Use personal access tokens with the narrowest scope that works, and set expirations. Prefer fine-grained PATs on GitHub, and OIDC federation from CI when you can avoid a static token entirely.
- Review authorized OAuth apps and SSH keys on your GitHub account at least yearly.
8) Notebook and data-file hygiene
Scientific workflows run on notebooks and shared data. Both leak secrets and execute code.
- Strip notebook outputs before commit: add
nbstripoutas apre-commithook. Output cells often contain API responses, tokens, printedos.environ, and PII. - Treat “Run All” on a downloaded notebook the same as running an unreviewed script: read it first.
- Keep credentials out of notebooks. Load them from environment variables or a secret manager, not from a cell.
- Do not unpickle (
pickle,joblib) ortorch.loadfiles from untrusted sources. Useweights_only=Truewhenever your installed PyTorch supports it, or prefersafetensors. - On shared HPC / multi-user systems, check permissions:
~/.sshshould be700, key files600. Do not write secrets to world-readable scratch directories.
9) Containers, SBOM, and artifact signing
If you ship containers or build reusable artifacts:
- Scan images:
trivy image your/image:tag(orgrype) in CI, on the same schedule as SCA. - Pin base images by digest (
FROM python@sha256:…), not just by tag. - Generate an SBOM for each release.
Example commands:
syft your/image:tag -o cyclonedx-json, orpip-audit --format=cyclonedx-jsonfor pure-Python projects. Several DOE and federal guidelines increasingly expect one. - Sign releases and images with sigstore / cosign or GitHub artifact attestations. Consumers can then verify provenance.
10) Monitor and respond
Scanning only helps if findings are triaged and owned.
- Check security alerts (Dependabot, code scanning, secret scanning) on a fixed schedule.
- Track open high/critical findings.
- Define ownership and remediation SLAs.
- Maintain a simple exception process with expiration dates for accepted risk.
Example response policy using CVSS:
| CVSS Score | Severity | Suggested response time |
|---|---|---|
| >= 9.0 | Critical | Immediate / best effort |
| 7.0–8.9 | High | Within 7 days |
| 4.0–6.9 | Medium | Planned remediation |
| <= 3.9 | Low | Backlog / opportunistic |
11) Know the OWASP Top 10
The OWASP Top 10 is the shared language for common web-app risk classes:
- Broken Access Control
- Cryptographic Failures
- Injection
- Insecure Design
- Security Misconfiguration
- Vulnerable and Outdated Components
- Identification and Authentication Failures
- Software and Data Integrity Failures
- Security Logging and Monitoring Failures
- Server-Side Request Forgery (SSRF)
Continue with AI-assisted coding and agentic security review.