DEV Community

Cover image for A Practical Security Guide for Developers (and Teams)
Synergy Shock
Synergy Shock

Posted on

A Practical Security Guide for Developers (and Teams)

Generally speaking, 2026 has been a busy year in terms of security.

In just the past few weeks, we’ve seen incidents and supply-chain attacks hit widely used tools like Trivy GitHub Action, LiteLLM, and Axios; a reminder that modern development is deeply connected, and that small configuration decisions can have a huge impact.

That’s why we wanted to share this guide.

One of our teammates put together an excellent internal reference focused on practical security habits that actually reduce risk. It brings together concrete steps developers and teams can start applying right away.

The guide covers topics like:

  • safer npm and pnpm configuration
  • reducing exposure through exact dependency versions and minimum release age
  • why password managers are essential
  • protecting SSH keys
  • avoiding plaintext secrets in .env files
  • safer ways to manage credentials with tools like 1Password

What makes this guide especially valuable is that it focuses on the lowest hanging fruit: the changes that are simple to apply, but can meaningfully improve your security posture. For example, it recommends disabling install scripts in npm, pinning dependency versions and delaying adoption of newly released packages to reduce exposure to short-lived supply-chain attacks.

It also makes an important point. Security is not only about avoiding dramatic breaches. It’s also about everyday operational discipline. How we install dependencies, manage secrets, store credentials and protect the tools we use every day.

We’re sharing it here because we think it can be useful not only for our team, but for any developer who wants a more grounded, practical approach to security. With that in mind, let’s get started!

The Lowest Hanging Fruit: Configuring NPM

A useful way to think about security is that sometimes the most effective protections are also the simplest. Years ago, a Microsoft report found that 90% of critical vulnerabilities could have been mitigated simply by avoiding administrator privileges. The lesson still holds: reducing unnecessary permissions often removes a huge part of the risk surface.

In NodeJS there are also simple things to do that will prevent most of the attacks making noise these days: ignore-scripts

The postinstall and preinstall scripts are the most exploited features of NPM and at the same time they are simple to disable, just configure ignore-scripts=true in your .npmrc or with the following command:

  npm config set ignore-scripts true
Enter fullscreen mode Exit fullscreen mode

By default pnpm does not run those scripts if they are inside a dependency, for that reason pnpm users were not affected by the Axios attack, regardless I would still recommend configuring .npmrc to ignore scripts in case a more elaborate attack manages to sneak into your own source code.

With the main attack vector disabled, the next step is to minimize the time window in which your applications are susceptible to attacks and for that we have save-exact and min-release-age

    npm config set save-exact true
    npm config set min-release-age 7
    pnpm config set minimum-release-age 10080
Enter fullscreen mode Exit fullscreen mode

Or in your pnpm-workspace.yaml (if you use pnpm): minimumReleaseAge: 10080 and savePrefix: ''

save-exact (and savePrefix) will keep your dependencies on the same version until explicitly updated, drastically reducing the time window in which an application is susceptible to being attacked. To complement this, min-release-age (and minimumReleaseAge) ignores versions that have not been published long enough, for example within the last seven days. This helps reduce exposure to attacks that depend on a very short publication window. The Axios incident is a good example: the malicious release was active for only around three hours before being detected. Compared to that kind of timeline, a one-week waiting period provides a much safer buffer.

A final recommendation regarding npm dependencies is to keep them to a minimum. Every additional package expands the attack surface, which means that unused or forgotten dependencies can quietly become unnecessary risk over time. If a project has been around for a while, gone through refactors, or dropped features along the way, it is worth checking whether all of its dependencies are still doing real work. Tools like Knip can help identify dead code and orphaned packages, making it easier to reduce clutter and keep the dependency tree lean.

The Next Low Hanging Fruit: Password Manager

Because you can't steal credentials that you can't read

A password manager is another completely essential recommendation, the simple fact of using one in conjunction with its respective browser plugin protects you from the most exploited vulnerabilities:

  • Reused Passwords: Using compromised passwords across multiple services (a.k.a Account Takeover) was the main attack vector in 2022. A password manager is the only practical way to have unique and strong passwords for every site.
  • Second factor authentication: The most efficient way to protect your accounts from attacks, as much as 99.9% according to Microsoft in 2019. A password manager not only automates autofill, but synchronization between devices saves a ton of management time in case of "loss".
  • Phishing: The attack modality that AI has boosted the most making it harder than ever to differentiate between a fake site and an original one. A password manager won't suggest using passwords if the site isn't the same one where it was created.

There are several managers out there and they all cover the basic points one way or another. Even if you are deeply immersed in the Apple ecosystem, the Passwords app is already integrated into all devices although it might not be recommended if at some point you need to use Android or Linux.

Once the basics are covered, in the case of developers there are advanced features we can use and which we will exemplify with 1password for simplicity.

Biometrically protected SSH

The private ssh keys living in ~/.ssh are very sensitive files that we use to authenticate connections to services like GitHub or connect to remote servers, so they are among the first targets of an attack, and originally the only way to protect these files is with a password with a complexity matching what you are trying to protect, something that becomes annoying if you are constantly pulling and pushing to GitHub.

Instead we can delete those files and use 1Password as an SSH Agent and have the password automatically loaded using TouchID (or equivalent).

1) Enable the agent: In 1Password, Settings > Developer, and check the Use the SSH agent option.

2) Configure your SSH client: Add the following snippet to your ~/.ssh/config file (create it if it doesn't exist):

Host *
    IdentityAgent "{AGEN_SOCK}"
Enter fullscreen mode Exit fullscreen mode

(Note: {AGEN_SOCK} varies by operating system. Check the specific paths for each OS.)

3) Add Key in Github: In the "Add new SSH Key" section fill out the form with a title, the key type as "Authentication Key" and in the Key, 1Password will suggest creating a new key (or using an existing one, but having one per service is recommended).

4) Authorize Access from now on when any program tries to use your SSH keys, for example when doing pull or push from github or via ssh -T git@github.com, 1Password will ask you to authorize it using TouchID.

No plaintext keys

The next target of an attack on a developer will surely be your .env files or even worse... One might even publish them by accident.. With a password manager we can avoid this completely and along the way automate the propagation of changes to the whole team.

In 1Password there are two ways to inject secrets as environment variables: "Secret references" and "1Password Environment" (currently in Beta). we will explain both and leave the decision of which to use to the reader's discretion and taste.

Secret References

For this approach it is necessary to have the 1Password CLI installed. Once the op command is installed, you would only have to:

1) Replace Variables with References: Swap your plaintext secrets for these references

DATABASE_URL="op://Synergy Shock/Project/Local/DATABASE_URL"
OPENAPI_KEY="op://Synergy Shock/Global/Local/OPENAPI_KEY"
Enter fullscreen mode Exit fullscreen mode

2) Run your application: Using the op run command to inject the secrets into your application's environment

   op run --env-file=.env.local -- pnpm run dev
Enter fullscreen mode Exit fullscreen mode

This method minimizes the exposure of our secrets and exposes them only during the runtime of our command, but having to use the op command as a prefix for everything makes it less practical than the next approach.

1Password Environment (Beta)

Here you don't need to have the CLI installed, but it is a Beta feature and it's not available for Windows.

1) Create a new environment In the Desktop APP, Development > Environment > New Environment, and give it a name.

2) Load your variables one by one or using your original .env.

3) Create one or more destination files

4) Access the file: From now on when someone tries to access your environment file 1Password will ask you for authorization.

A Final Note from the Synergy Shock Team

By directly protecting the .env file, this method is often more practical than using Secret References, but it still comes with trade-offs worth considering. At the moment, it is not available on Windows, which may or may not matter depending on the development stack. And once access to the file is authorized, its contents remain available in plaintext until 1Password is locked again, which creates a temporary exposure window.

In practice, Environments still appears to be the stronger option for most teams. That risk window becomes much easier to manage when local environments avoid using production credentials altogether. That means using local or disposable databases, keeping infrastructure keys out of development machines whenever possible, limiting access to only what is necessary, and applying spending limits or read-only permissions to external service keys.

More broadly, that is the spirit behind this guide: security is rarely about a single perfect tool and more often about reducing exposure through small, consistent decisions. At Synergy Shock, this is how security is approached as well, not as something separate from development, but as part of the way teams build every day. Hopefully this guide becomes a useful reference for your own work, your team and the habits that make systems more resilient over time.

Top comments (0)