BK BERND KUHLENAll notes โ†—
โ† Back to field notes

What I Learned in October 2026: Making Secure Development Routine

Security work is often described as a gate: development happens first, then somebody checks the result. My main lesson this month is that secure development works better as a loop. Small automated checks run while the system is changing, findings arrive with enough context to be understood, and remediation becomes part of ordinary engineering rather than an exceptional clean-up project.

I have been focusing on two practical parts of that loop: security linting and GitHub Dependabot alerts. Neither is new, and neither is a complete security program. Together, however, they expose two common classes of risk early: insecure patterns in code and configuration, and known vulnerabilities in third-party dependencies.

A security tool creates value only when its findings can be understood, prioritized and acted on.

Security linting is executable guidance

A good security linter is more than a syntax checker. It turns agreed engineering rules into repeatable feedback. Depending on the project, that can include detecting embedded secrets, unsafe shell construction, weak cryptographic choices, overly broad permissions, insecure infrastructure defaults or suspicious data handling.

The advantage is timing. A warning shown while a change is still small is cheaper to understand and fix than the same issue discovered after deployment. The developer still remembers why the line exists, the review is still focused, and there is less surrounding code to reconsider.

But more rules do not automatically produce more security. A noisy rule set trains people to ignore the output. I found it more useful to start with high-confidence checks, document why they matter, and expand only when the team can distinguish a real weakness from an irrelevant pattern.

Dependabot is an inbox, not an autopilot

Dependabot alerts provide valuable information: a dependency is affected by a published advisory, the vulnerable version range is known, and an upgrade path may exist. The dangerous interpretation is that every alert should immediately trigger a blind version bump.

Each alert needs context:

  • Is the vulnerable component present in production or only in development tooling?
  • Does the application exercise the affected code path?
  • Is the package directly controlled or pulled in transitively?
  • Does the suggested version introduce breaking behaviour?
  • Are compensating controls already reducing exposure?

Severity is a starting point, not the complete priority. A medium-severity issue on an exposed request path can deserve attention before a critical advisory in an unreachable build-time component. The decision should combine the advisory, the actual architecture and the cost of a safe update.

The lockfile is part of the security boundary

Dependency management is not finished when a package name appears in a manifest. The resolved dependency tree matters. Lockfiles make builds reproducible, reveal the versions actually installed and give automated scanners a concrete graph to evaluate.

This leads to a simple but important discipline: update the manifest and lockfile together, review unexpected transitive changes, run the complete test and quality suite, and avoid merging generated dependency changes that nobody has examined. Automation can prepare the change; ownership still belongs to the engineer accepting it.

Quality gates need an escape from false confidence

Automated gates are attractive because they produce a clear answer: pass or fail. That clarity is useful, but it can also create false confidence. A passing scanner means that its configured rules did not find a matching problem in the material it inspected. It does not mean the design is secure.

For this website, the automated gate checks JavaScript syntax, internal links, referenced assets, JSON structure, duplicate IDs, shared metrics and other consistency rules before deployment. Security-focused checks fit naturally beside them, but architecture still requires human questions: Is this endpoint necessary? Does the browser need this data? Can the operation remain static? What is the smallest IAM permission? What happens if a scheduled process fails?

The strongest result comes from combining deterministic automation with deliberate review.

Prioritization should be visible

A growing alert count is not a remediation strategy. Findings become manageable when their state and reasoning are visible. A lightweight workflow can be enough:

  1. Validate that the finding applies to the current code and deployed architecture.
  2. Classify exposure, impact and exploitability rather than relying on one score.
  3. Decide whether to update, mitigate, remove, accept temporarily or investigate further.
  4. Record the reason, owner and expected review point.
  5. Verify with tests and a second scan after the change.

This makes exceptions reviewable. Suppressing a false positive can be legitimate; silently hiding it is not. The difference is an explanation that a future maintainer can challenge.

Secure defaults are cheaper than repeated reminders

One of the most useful outcomes of recurring findings is not another closed alert but a better default. If the same unsafe configuration appears repeatedly, the durable fix may be a template, shared workflow, reusable policy or project scaffold that makes the preferred choice automatic.

This principle shaped the portfolio as well. The public site remains static. S3 is private behind CloudFront. Browser code receives public aggregate data rather than raw operational records. Scheduled functions have narrow write targets. Those architectural defaults remove entire categories of application risk before linting begins.

Five lessons I am keeping

Fast feedback changes behaviour. A precise warning during development is more useful than a long report weeks later.

Noise is a security problem. Low-quality alerts consume attention that should be spent on meaningful findings.

Automation proposes; engineers decide. Dependency updates still need architectural context, testing and review.

A pass is evidence, not proof. Tools cover known patterns; threat modelling and design review cover intent and system boundaries.

The best remediation improves the path for the next change. Templates, policies and secure defaults scale better than repeatedly correcting the same mistake.

What I want to improve next

My next iteration is to make the feedback loop easier to understand at a glance: separate urgent exposure from routine maintenance, keep exception reasoning close to the finding, and measure how quickly actionable alerts move from detection to verified remediation.

I also want to connect these checks more clearly to the architecture they protect. A dependency alert, an IAM policy finding and a public-data decision may come from different tools, but they all describe trust boundaries in the same system.

Final takeaway

Secure development is not created by adding one scanner or enabling one alert feed. It emerges when useful signals arrive early, decisions include context, and the normal delivery process makes the safe path understandable and repeatable.

That is the routine I am trying to build: automated enough to be consistent, quiet enough to be trusted and human enough to make sound decisions when the tool cannot.

BERND KUHLEN ยท CLOUD ENGINEERING FIELD NOTES